@getmicdrop/venue-calendar 3.3.7 → 3.3.9
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 +661 -661
- package/dist/{VenueCalendar-2gCRs3C_.js → VenueCalendar-D_YV5apb.js} +9119 -8558
- package/dist/VenueCalendar-D_YV5apb.js.map +1 -0
- package/dist/api/api.cjs.map +1 -1
- package/dist/api/api.mjs.map +1 -1
- package/dist/api/types.d.ts +289 -289
- package/dist/{index-bNIvTwbi.js → index-3p4o1V0I.js} +2 -2
- package/dist/{index-bNIvTwbi.js.map → index-3p4o1V0I.js.map} +1 -1
- package/dist/types/index.d.ts +395 -395
- package/dist/venue-calendar.css +1 -1
- package/dist/venue-calendar.es.js +1 -1
- package/dist/venue-calendar.iife.js +24 -24
- package/dist/venue-calendar.iife.js.map +1 -1
- package/dist/venue-calendar.umd.js +24 -24
- package/dist/venue-calendar.umd.js.map +1 -1
- package/package.json +96 -96
- package/src/lib/theme.js +209 -209
- package/dist/VenueCalendar-2gCRs3C_.js.map +0 -1
package/dist/api/api.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.mjs","sources":["../../src/lib/utils/logger.js","../../src/lib/api/client.ts","../../src/lib/api/orders.ts","../../src/lib/api/promo.ts","../../src/lib/api/events.ts","../../src/lib/api/venues.ts","../../src/lib/api/transformers/order.ts","../../src/lib/api/transformers/event.ts","../../src/lib/api/transformers/venue.ts"],"sourcesContent":["/**\n * Centralized logger utility for MicDrop applications\n * Can be disabled in production or configured for different log levels\n */\n\n/**\n * @typedef {'debug' | 'info' | 'warn' | 'error'} LogLevel\n */\n\n/**\n * @typedef {Object} LoggerConfig\n * @property {boolean} enabled\n * @property {LogLevel} level\n * @property {string} prefix\n */\n\n/** @type {Record<LogLevel, number>} */\nconst LOG_LEVELS = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/** @type {LoggerConfig} */\nlet config = {\n enabled: typeof window !== 'undefined' && import.meta.env?.DEV !== false,\n level: 'debug',\n prefix: '[MicDrop]',\n};\n\n/**\n * Configure the logger\n * @param {Partial<LoggerConfig>} options\n */\nexport function configureLogger(options) {\n config = { ...config, ...options };\n}\n\n/**\n * Check if a log level should be logged\n * @param {LogLevel} level\n * @returns {boolean}\n */\nfunction shouldLog(level) {\n return config.enabled && LOG_LEVELS[level] >= LOG_LEVELS[config.level];\n}\n\n/**\n * Format a log message\n * @param {LogLevel} level\n * @param {string} message\n * @returns {string}\n */\nfunction formatMessage(level, message) {\n return `${config.prefix} [${level.toUpperCase()}] ${message}`;\n}\n\nexport const logger = {\n /**\n * Log debug message\n * @param {string} message\n * @param {...unknown} args\n */\n debug: (message, ...args) => {\n if (shouldLog('debug')) {\n console.log(formatMessage('debug', message), ...args);\n }\n },\n\n /**\n * Log info message\n * @param {string} message\n * @param {...unknown} args\n */\n info: (message, ...args) => {\n if (shouldLog('info')) {\n console.info(formatMessage('info', message), ...args);\n }\n },\n\n /**\n * Log warning message\n * @param {string} message\n * @param {...unknown} args\n */\n warn: (message, ...args) => {\n if (shouldLog('warn')) {\n console.warn(formatMessage('warn', message), ...args);\n }\n },\n\n /**\n * Log error message\n * @param {string} message\n * @param {...unknown} args\n */\n error: (message, ...args) => {\n if (shouldLog('error')) {\n console.error(formatMessage('error', message), ...args);\n }\n },\n};\n\nexport default logger;\n","/**\n * API Client for MicDrop Public Checkout API\n *\n * Provides a centralized HTTP client with:\n * - Configurable base URL\n * - Error handling and logging\n * - Request/response typing\n * - IP address capture for payment intents\n */\n\nimport { logger } from '../utils/logger.js';\nimport type { ApiConfig, ApiResponse } from './types.js';\n\n// Default API configuration\nconst DEFAULT_CONFIG: Required<ApiConfig> = {\n baseUrl: 'https://get-micdrop.com',\n timeout: 30000,\n onError: (error: Error) => logger.error('API Error:', error),\n};\n\n// Global configuration (can be overridden)\nlet globalConfig: Required<ApiConfig> = { ...DEFAULT_CONFIG };\n\n/**\n * Configure the API client\n */\nexport function configureApi(config: Partial<ApiConfig>): void {\n globalConfig = { ...globalConfig, ...config };\n}\n\n/**\n * Get the current API configuration\n */\nexport function getApiConfig(): Required<ApiConfig> {\n return { ...globalConfig };\n}\n\n/**\n * Get the public API base URL for v2 endpoints\n */\nexport function getPublicBaseUrl(): string {\n return `${globalConfig.baseUrl}/api/v2/public`;\n}\n\n/**\n * Get the legacy public API base URL\n */\nexport function getLegacyPublicUrl(): string {\n return `${globalConfig.baseUrl}/api/public`;\n}\n\n/**\n * Get the orders API base URL\n */\nexport function getOrdersPublicUrl(): string {\n return `${globalConfig.baseUrl}/api/orders/public`;\n}\n\n/**\n * Get the user's IP address for payment intents\n */\nexport async function getClientIP(): Promise<string> {\n try {\n const response = await fetch('https://api.ipify.org?format=json');\n const data = await response.json();\n return data.ip || '';\n } catch (error) {\n logger.warn('Could not fetch client IP:', error);\n return '';\n }\n}\n\n/**\n * Make a GET request to the API\n */\nexport async function apiGet<T>(\n endpoint: string,\n options?: RequestInit\n): Promise<ApiResponse<T>> {\n return apiRequest<T>('GET', endpoint, undefined, options);\n}\n\n/**\n * Make a POST request to the API\n */\nexport async function apiPost<T>(\n endpoint: string,\n body?: unknown,\n options?: RequestInit\n): Promise<ApiResponse<T>> {\n return apiRequest<T>('POST', endpoint, body, options);\n}\n\n/**\n * Make a PUT request to the API\n */\nexport async function apiPut<T>(\n endpoint: string,\n body?: unknown,\n options?: RequestInit\n): Promise<ApiResponse<T>> {\n return apiRequest<T>('PUT', endpoint, body, options);\n}\n\n/**\n * Make a DELETE request to the API\n */\nexport async function apiDelete<T>(\n endpoint: string,\n options?: RequestInit\n): Promise<ApiResponse<T>> {\n return apiRequest<T>('DELETE', endpoint, undefined, options);\n}\n\n/**\n * Core API request function\n */\nasync function apiRequest<T>(\n method: string,\n endpoint: string,\n body?: unknown,\n options?: RequestInit\n): Promise<ApiResponse<T>> {\n const url = endpoint.startsWith('http')\n ? endpoint\n : `${getPublicBaseUrl()}${endpoint}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), globalConfig.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n credentials: 'include',\n signal: controller.signal,\n ...options,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n const error = new Error(\n errorData.error || errorData.message || `HTTP ${response.status}`\n );\n globalConfig.onError(error);\n\n return {\n success: false,\n error: errorData.error || errorData.message || `HTTP ${response.status}`,\n statusCode: response.status,\n };\n }\n\n const data = await response.json();\n return {\n success: true,\n data: data as T,\n statusCode: response.status,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n const errorMessage =\n error instanceof Error\n ? error.name === 'AbortError'\n ? 'Request timed out'\n : error.message\n : 'Unknown error';\n\n globalConfig.onError(error instanceof Error ? error : new Error(errorMessage));\n\n return {\n success: false,\n error: errorMessage,\n };\n }\n}\n\n/**\n * Simple fetch wrapper for backwards compatibility\n * Returns data directly or null on error\n */\nexport async function simpleFetch<T>(\n url: string,\n options?: RequestInit\n): Promise<T | null> {\n try {\n const response = await fetch(url, {\n credentials: 'include',\n ...options,\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n logger.error(`API request failed: ${response.status}`, errorData);\n return null;\n }\n\n return response.json();\n } catch (error) {\n logger.error('API request error:', error);\n return null;\n }\n}\n","/**\n * Orders API\n *\n * Functions for managing orders, payments, and reservations\n * in the public checkout flow.\n */\n\nimport { logger } from '../utils/logger.js';\nimport {\n getPublicBaseUrl,\n getLegacyPublicUrl,\n getOrdersPublicUrl,\n getClientIP,\n simpleFetch,\n} from './client.js';\nimport type {\n PaymentIntentResponse,\n CompleteReservationResponse,\n CancelReservationResponse,\n CreateOrderResponse,\n ValidatePaymentRequest,\n ValidatePaymentResponse,\n ExtendSessionResponse,\n SessionStatus,\n Order,\n} from './types.js';\n\n/**\n * Create a payment intent for the cart\n *\n * This initiates the Stripe payment flow by creating a PaymentIntent\n * on the backend. The response includes the client_secret needed\n * for Stripe Elements.\n *\n * @param cartId - The cart/order UUID\n * @param quantities - Map of ticketId -> quantity\n * @returns Payment intent data including client_secret, or null on error\n */\nexport async function createPaymentIntent(\n cartId: string,\n quantities: Record<string | number, number>\n): Promise<PaymentIntentResponse | null> {\n try {\n // Uses /api/orders/public/cart/:uuid/payment-intent (same as micdrop-frontend)\n const response = await fetch(\n `${getOrdersPublicUrl()}/cart/${cartId}/payment-intent`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n credentials: 'include',\n body: JSON.stringify({\n productQuantities: quantities,\n }),\n }\n );\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n logger.error('Payment intent creation failed:', errorData);\n throw new Error(errorData.error || 'Failed to create payment intent');\n }\n\n const data = await response.json();\n logger.debug('Payment intent created:', data);\n return data;\n } catch (error) {\n logger.error('createPaymentIntent error:', error);\n return null;\n }\n}\n\n/**\n * Complete reservation after successful payment\n *\n * Called after Stripe confirms the payment to finalize the order\n * and generate tickets.\n *\n * @param orderUuid - The order UUID\n * @returns Success status and message\n */\nexport async function completeReservation(\n orderUuid: string\n): Promise<CompleteReservationResponse> {\n try {\n const response = await fetch(\n `${getPublicBaseUrl()}/orders/complete/${orderUuid}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n );\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n return {\n success: false,\n error: errorData.error || 'Failed to complete reservation',\n };\n }\n\n const result = await response.json();\n return {\n success: true,\n message: result.message,\n };\n } catch (error) {\n logger.error('Error completing reservation:', error);\n return { success: false, error: 'Network error completing reservation' };\n }\n}\n\n/**\n * Cancel reservation and release tickets back to inventory\n *\n * Called when user abandons checkout or session expires.\n *\n * @param orderUuid - The order UUID\n * @returns Success status and message\n */\nexport async function cancelReservation(\n orderUuid: string\n): Promise<CancelReservationResponse> {\n try {\n const response = await fetch(\n `${getPublicBaseUrl()}/orders/cancel/${orderUuid}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n );\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n return {\n success: false,\n error: errorData.error || 'Failed to cancel reservation',\n };\n }\n\n const result = await response.json();\n return {\n success: true,\n message: result.message,\n };\n } catch (error) {\n logger.error('Error cancelling reservation:', error);\n return { success: false, error: 'Network error cancelling reservation' };\n }\n}\n\n/**\n * Create a new order/cart\n *\n * This creates an empty order that can be used for checkout.\n * The order UUID is used for all subsequent operations.\n *\n * @param eventId - The event ID\n * @param promoCode - Optional promo code to apply\n * @returns The order UUID, or null on error\n */\nexport async function createOrder(\n eventId: string | number,\n promoCode?: string\n): Promise<CreateOrderResponse | null> {\n try {\n // Uses /api/public/createOrder (same as micdrop-frontend)\n const response = await fetch(`${getLegacyPublicUrl()}/createOrder`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n eventID: eventId,\n promoCode,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n logger.error('Create order failed:', errorData);\n return null;\n }\n\n return response.json();\n } catch (error) {\n logger.error('createOrder error:', error);\n return null;\n }\n}\n\n/**\n * Get order details (public, no auth required)\n *\n * Fetches the order details for displaying on the success page.\n *\n * @param orderId - The order UUID or ID\n * @returns The order details, or null on error\n */\nexport async function getOrder(orderId: string): Promise<Order | null> {\n // Uses /api/public/getOrder/:id (same as micdrop-frontend)\n return simpleFetch<Order>(`${getLegacyPublicUrl()}/getOrder/${orderId}`);\n}\n\n/**\n * Validate payment intent and complete the order\n *\n * This is an alternative to completeReservation that accepts\n * additional payment details. Used by micdrop-frontend.\n *\n * @param cartId - The cart/order UUID\n * @param payload - Payment validation payload\n * @returns Validation result\n */\nexport async function validatePaymentIntent(\n cartId: string,\n payload: ValidatePaymentRequest\n): Promise<ValidatePaymentResponse | null> {\n try {\n // Uses /api/public/validatePaymentIntent/:id (same as micdrop-frontend)\n const response = await fetch(\n `${getLegacyPublicUrl()}/validatePaymentIntent/${cartId}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n logger.error('Payment validation failed:', errorData);\n return {\n success: false,\n status: 'failed',\n error: errorData.error || 'Payment validation failed',\n };\n }\n\n const result = await response.json();\n return {\n success: true,\n status: result.status || 'Payment succeeded',\n orderUUID: result.orderUUID || result.uuid,\n };\n } catch (error) {\n logger.error('validatePaymentIntent error:', error);\n return null;\n }\n}\n\n/**\n * Extend the checkout session by 15 minutes\n *\n * Users get a limited number of extensions (typically 2-3).\n *\n * @param orderUuid - The order UUID\n * @returns Extension result with new expiry time\n */\nexport async function extendCheckoutSession(\n orderUuid: string\n): Promise<ExtendSessionResponse> {\n try {\n const response = await fetch(`${getPublicBaseUrl()}/orders/extend-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ orderUuid }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n return {\n success: false,\n error: errorData.error || 'Failed to extend session',\n };\n }\n\n const result = await response.json();\n return {\n success: true,\n newExpiryTime: result.newExpiryTime,\n remainingExtensions: result.remainingExtensions,\n };\n } catch (error) {\n logger.error('Error extending checkout session:', error);\n return { success: false, error: 'Network error extending session' };\n }\n}\n\n/**\n * Get current session status including expiry time\n *\n * Used to display countdown timer and check if extensions are available.\n *\n * @param orderUuid - The order UUID\n * @returns Session status including expiry time\n */\nexport async function getSessionStatus(orderUuid: string): Promise<SessionStatus> {\n try {\n const response = await fetch(\n `${getPublicBaseUrl()}/orders/session/${orderUuid}`\n );\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n return { error: errorData.error || 'No active session found' };\n }\n\n const result = await response.json();\n return {\n expiresAt: result.expiresAt,\n extensionCount: result.extensionCount,\n remainingExtensions: result.remainingExtensions,\n canExtend: result.canExtend,\n reservationCount: result.reservationCount,\n };\n } catch (error) {\n logger.error('Error getting session status:', error);\n return { error: 'Network error getting session status' };\n }\n}\n\n/**\n * Initiate a new order (alias for createOrder)\n *\n * This function provides backwards compatibility with micdrop-frontend.\n * It accepts the same parameters as the legacy initiateOrder function.\n *\n * @param cartData - Object containing eventID and optional quantities/promoCode\n * @returns The order UUID, or null on error\n */\nexport async function initiateOrder(\n cartData: { eventID: string | number; promoCode?: string; quantities?: Record<string | number, number> } = {} as any\n): Promise<string | null> {\n try {\n // Uses /api/public/createOrder (same as micdrop-frontend)\n const response = await fetch(`${getLegacyPublicUrl()}/createOrder`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(cartData),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n logger.error('Order initiation failed:', errorData);\n return null;\n }\n\n const data = await response.json();\n return data.uuid;\n } catch (error) {\n logger.error('initiateOrder error:', error);\n return null;\n }\n}\n\n/**\n * Track UTM source for analytics\n *\n * Records the traffic source (utm_source parameter) for marketing analytics.\n *\n * @param venueId - The venue ID\n * @returns Promise that resolves when tracking is complete\n */\nexport async function trackUTMSource(venueId: string | number): Promise<void> {\n if (typeof window === 'undefined') return;\n\n const urlParams = new URLSearchParams(window.location.search);\n const utmSource = urlParams.get('utm_source') || 'Direct';\n\n try {\n // Uses /api/public/increment/:venueId/:source (same as micdrop-frontend)\n await fetch(\n `${getLegacyPublicUrl()}/increment/${venueId}/${encodeURIComponent(utmSource)}`\n );\n } catch (error) {\n logger.error('UTM tracking failed:', error);\n }\n}\n","/**\n * Promo Codes API\n *\n * Functions for validating and checking promo codes\n * in the public checkout flow.\n */\n\nimport { logger } from '../utils/logger.js';\nimport { getPublicBaseUrl } from './client.js';\nimport type { PromoValidationResponse, HasPromoCodesResponse } from './types.js';\n\n/**\n * Validate a promo code for an event\n *\n * Checks if a promo code is valid and returns its effects:\n * - Discount amount and type\n * - Hidden ticket reveal\n *\n * @param eventId - The event ID\n * @param code - The promo code to validate\n * @returns Validation result with discount info\n */\nexport async function validatePromoCode(\n eventId: string | number,\n code: string\n): Promise<PromoValidationResponse> {\n try {\n if (!code || !code.trim()) {\n return { valid: false, error: 'Promo code is required' };\n }\n\n // API uses GET with code in URL path\n const encodedCode = encodeURIComponent(code.trim());\n const response = await fetch(\n `${getPublicBaseUrl()}/promo-codes/validate/${eventId}/${encodedCode}`\n );\n\n if (!response.ok) {\n // 404 = invalid code, other errors are server issues\n if (response.status === 404) {\n return { valid: false, error: 'Invalid promo code' };\n }\n const errorData = await response.json().catch(() => ({}));\n return { valid: false, error: errorData.error || 'Failed to validate code' };\n }\n\n const result = await response.json();\n return {\n valid: result.valid ?? true,\n revealHiddenTickets: result.revealHiddenTickets,\n revealTicketIds: result.revealTicketIds,\n provideDiscount: result.provideDiscount,\n discountType: result.discountType,\n amount: result.amount,\n code: result.code || code,\n };\n } catch (error) {\n logger.error('Error validating promo code:', error);\n return { valid: false, error: 'Network error validating code' };\n }\n}\n\n/**\n * Check if promo codes are available for an event\n *\n * Used to conditionally show/hide the promo code input field.\n *\n * @param eventId - The event ID\n * @returns Whether promo codes exist for this event\n */\nexport async function hasPromoCodes(eventId: string | number): Promise<boolean> {\n try {\n const response = await fetch(\n `${getPublicBaseUrl()}/promo-codes/check/${eventId}`\n );\n\n if (!response.ok) {\n // If endpoint doesn't exist or errors, default to showing the input\n return true;\n }\n\n const result: HasPromoCodesResponse = await response.json();\n return result.hasPromoCodes === true;\n } catch (error) {\n logger.error('Error checking promo codes availability:', error);\n // Default to showing promo input if we can't check\n return true;\n }\n}\n\n/**\n * Apply a promo code to a cart\n *\n * This updates the cart with the promo code discount.\n *\n * @param cartId - The cart UUID\n * @param code - The promo code to apply\n * @returns Success status\n */\nexport async function applyPromoCode(\n cartId: string,\n code: string\n): Promise<{ success: boolean; error?: string }> {\n try {\n const response = await fetch(\n `${getPublicBaseUrl()}/orders/${cartId}/apply-promo`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ code }),\n }\n );\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n return {\n success: false,\n error: errorData.error || 'Failed to apply promo code',\n };\n }\n\n return { success: true };\n } catch (error) {\n logger.error('Error applying promo code:', error);\n return { success: false, error: 'Network error applying code' };\n }\n}\n\n/**\n * Remove a promo code from a cart\n *\n * @param cartId - The cart UUID\n * @returns Success status\n */\nexport async function removePromoCode(\n cartId: string\n): Promise<{ success: boolean; error?: string }> {\n try {\n const response = await fetch(\n `${getPublicBaseUrl()}/orders/${cartId}/remove-promo`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n );\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n return {\n success: false,\n error: errorData.error || 'Failed to remove promo code',\n };\n }\n\n return { success: true };\n } catch (error) {\n logger.error('Error removing promo code:', error);\n return { success: false, error: 'Network error removing code' };\n }\n}\n","/**\n * Events API\n *\n * Functions for fetching event data, tickets, and performers\n * in the public checkout flow.\n */\n\nimport { logger } from '../utils/logger.js';\nimport { getPublicBaseUrl, simpleFetch } from './client.js';\nimport type {\n Event,\n AvailableTicket,\n EventPerformersResponse,\n SeriesOccurrencesResponse,\n} from './types.js';\n\n/**\n * Fetch event details\n *\n * Gets full event information including venue and ticket data.\n *\n * @param eventId - The event ID\n * @param customFetch - Optional custom fetch function (for SSR)\n * @returns Event details or null on error\n */\nexport async function fetchEventDetails(\n eventId: string | number,\n customFetch: typeof fetch = fetch\n): Promise<Event | null> {\n try {\n const response = await customFetch(`${getPublicBaseUrl()}/events/${eventId}`);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch event details: ${response.status}`);\n }\n\n return response.json();\n } catch (error) {\n logger.error('Error fetching event details:', error);\n return null;\n }\n}\n\n/**\n * Fetch available tickets for an event\n *\n * Returns all ticket types that are currently available for sale.\n *\n * @param eventId - The event ID\n * @returns Array of available tickets\n */\nexport async function fetchEventTickets(\n eventId: string | number\n): Promise<AvailableTicket[]> {\n try {\n const response = await fetch(\n `${getPublicBaseUrl()}/tickets/event/${eventId}`\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch tickets: ${response.status}`);\n }\n\n const tickets = await response.json();\n return Array.isArray(tickets) ? tickets : [];\n } catch (error) {\n logger.error('Error fetching tickets:', error);\n return [];\n }\n}\n\n/**\n * Fetch performers for an event\n *\n * Returns the lineup with pre-resolved avatar URLs.\n *\n * @param eventId - The event ID\n * @returns Performers list and visibility flag\n */\nexport async function fetchEventPerformers(\n eventId: string | number\n): Promise<EventPerformersResponse> {\n try {\n if (!eventId) {\n logger.warn('fetchEventPerformers called without eventId');\n return { performers: [], showPerformers: false };\n }\n\n const response = await fetch(\n `${getPublicBaseUrl()}/events/${eventId}/performers`\n );\n\n if (!response.ok) {\n logger.error(\n `Failed to fetch performers: ${response.status} ${response.statusText}`\n );\n return { performers: [], showPerformers: false };\n }\n\n const data = await response.json();\n return {\n performers: Array.isArray(data.performers) ? data.performers : [],\n showPerformers: data.showPerformers === true,\n };\n } catch (error) {\n logger.error('Error fetching event performers:', error);\n return { performers: [], showPerformers: false };\n }\n}\n\n/**\n * Fetch all venues for an organization\n *\n * @param orgId - The organization ID\n * @returns Array of venues\n */\nexport async function fetchAllVenues(orgId: string | number): Promise<any[]> {\n try {\n if (!orgId) {\n logger.warn('fetchAllVenues called without orgId');\n return [];\n }\n\n const response = await fetch(\n `${getPublicBaseUrl()}/venues/organization/${orgId}`\n );\n\n if (!response.ok) {\n logger.error(\n `Failed to fetch venues: ${response.status} ${response.statusText}`\n );\n return [];\n }\n\n const venues = await response.json();\n return Array.isArray(venues) ? venues : [];\n } catch (error) {\n logger.error('Error fetching venues:', error);\n return [];\n }\n}\n\n/**\n * Fetch events for a venue\n *\n * @param venueId - The venue ID\n * @returns Array of events\n */\nexport async function fetchVenueEvents(venueId: string | number): Promise<Event[]> {\n try {\n if (!venueId) {\n logger.warn('fetchVenueEvents called without venueId');\n return [];\n }\n\n const response = await fetch(\n `${getPublicBaseUrl()}/events/venue/${venueId}`\n );\n\n if (!response.ok) {\n logger.error(\n `Failed to fetch venue events: ${response.status} ${response.statusText}`\n );\n return [];\n }\n\n const events = await response.json();\n return Array.isArray(events) ? events : [];\n } catch (error) {\n logger.error('Error fetching venue events:', error);\n return [];\n }\n}\n\n/**\n * Get events for a specific month\n *\n * Used for calendar views to efficiently load events.\n *\n * @param venueId - The venue ID\n * @param year - The year (e.g., 2024)\n * @param month - The month (1-12)\n * @returns Array of events for the month\n */\nexport async function getMonthEvents(\n venueId: string | number,\n year: number,\n month: number\n): Promise<Event[]> {\n try {\n const response = await fetch(\n `${getPublicBaseUrl()}/events/venue/${venueId}/month/${year}/${month}`\n );\n\n if (!response.ok) {\n logger.error(`Failed to fetch month events: ${response.status}`);\n return [];\n }\n\n const data = await response.json();\n return Array.isArray(data.events) ? data.events : Array.isArray(data) ? data : [];\n } catch (error) {\n logger.error('Error fetching month events:', error);\n return [];\n }\n}\n\n/**\n * Get events for an organization for a specific month\n *\n * @param orgId - The organization ID\n * @param year - The year (e.g., 2024)\n * @param month - The month (1-12)\n * @returns Array of events for the month\n */\nexport async function getOrgMonthEvents(\n orgId: string | number,\n year: number,\n month: number\n): Promise<Event[]> {\n try {\n const response = await fetch(\n `${getPublicBaseUrl()}/events/organization/${orgId}/month/${year}/${month}`\n );\n\n if (!response.ok) {\n logger.error(`Failed to fetch org month events: ${response.status}`);\n return [];\n }\n\n const data = await response.json();\n return Array.isArray(data.events) ? data.events : Array.isArray(data) ? data : [];\n } catch (error) {\n logger.error('Error fetching org month events:', error);\n return [];\n }\n}\n\n/**\n * Get series occurrences for date selector\n *\n * Returns all instances of a recurring event series.\n *\n * @param eventSeriesId - The series ID\n * @returns Series occurrences\n */\nexport async function getSeriesOccurrences(\n eventSeriesId: number\n): Promise<SeriesOccurrencesResponse | null> {\n try {\n const response = await fetch(\n `${getPublicBaseUrl()}/series/${eventSeriesId}/occurrences`\n );\n\n if (!response.ok) {\n logger.error(`Failed to fetch series occurrences: ${response.status}`);\n return null;\n }\n\n return response.json();\n } catch (error) {\n logger.error('Error fetching series occurrences:', error);\n return null;\n }\n}\n\n/**\n * Fetch series occurrences with CTA state\n *\n * Returns full series data including availability status.\n *\n * @param eventSeriesId - The series ID\n * @param venueId - The venue ID\n * @returns Series occurrences with CTA state\n */\nexport async function fetchSeriesOccurrences(\n eventSeriesId: number,\n venueId: string | number\n): Promise<SeriesOccurrencesResponse | null> {\n try {\n const response = await fetch(\n `${getPublicBaseUrl()}/series/${eventSeriesId}/occurrences?venueId=${venueId}`\n );\n\n if (!response.ok) {\n logger.error(`Failed to fetch series with CTA: ${response.status}`);\n return null;\n }\n\n return response.json();\n } catch (error) {\n logger.error('Error fetching series occurrences:', error);\n return null;\n }\n}\n\n/**\n * Check event password\n *\n * Validates password for password-protected events.\n *\n * @param eventId - The event ID\n * @param password - The password to check\n * @returns Whether the password is valid\n */\nexport async function checkEventPassword(\n eventId: string | number,\n password: string\n): Promise<boolean> {\n try {\n const encodedPassword = encodeURIComponent(password);\n const response = await fetch(\n `${getPublicBaseUrl()}/events/${eventId}/check-password/${encodedPassword}`\n );\n\n if (!response.ok) {\n return false;\n }\n\n const result = await response.json();\n return result.valid === true;\n } catch (error) {\n logger.error('Error checking event password:', error);\n return false;\n }\n}\n\n/**\n * Test network connection\n *\n * Health check endpoint for connectivity testing.\n *\n * @param orgId - Optional org ID\n * @param venueId - Optional venue ID\n * @returns Whether the connection is working\n */\nexport async function testNetworkConnection(\n orgId?: string | number,\n venueId?: string | number\n): Promise<boolean> {\n try {\n // Use a simple endpoint to test connectivity\n const url = venueId\n ? `${getPublicBaseUrl()}/events/venue/${venueId}`\n : orgId\n ? `${getPublicBaseUrl()}/venues/organization/${orgId}`\n : `${getPublicBaseUrl()}/health`;\n\n const response = await fetch(url, {\n method: 'HEAD',\n });\n\n return response.ok;\n } catch (error) {\n logger.error('Network connection test failed:', error);\n return false;\n }\n}\n","/**\n * Venues API\n *\n * Functions for fetching venue data including\n * service fees and tax configuration.\n */\n\nimport { logger } from '../utils/logger.js';\nimport { getPublicBaseUrl, getLegacyPublicUrl, simpleFetch } from './client.js';\nimport type { Venue } from './types.js';\n\n/**\n * Get venue details (public, no auth required)\n *\n * Fetches venue information including service fees and taxes\n * needed for checkout calculations.\n *\n * @param venueId - The venue ID\n * @returns Venue details or null on error\n */\nexport async function getVenue(venueId: string | number): Promise<Venue | null> {\n try {\n if (!venueId) {\n logger.warn('getVenue called without venueId');\n return null;\n }\n\n // Uses /api/public/getVenue/:id (same as micdrop-frontend)\n const response = await fetch(`${getLegacyPublicUrl()}/getVenue/${venueId}`);\n\n if (!response.ok) {\n logger.error(`Failed to fetch venue: ${response.status}`);\n return null;\n }\n\n return response.json();\n } catch (error) {\n logger.error('Error fetching venue:', error);\n return null;\n }\n}\n\n/**\n * Get venue service fee configuration\n *\n * Returns just the fee-related fields for checkout calculations.\n *\n * @param venueId - The venue ID\n * @returns Fee configuration or null on error\n */\nexport async function getVenueFees(\n venueId: string | number\n): Promise<{\n serviceFeePercentage: number;\n serviceFeeCents: number;\n taxPercentage: number;\n} | null> {\n const venue = await getVenue(venueId);\n\n if (!venue) {\n return null;\n }\n\n return {\n serviceFeePercentage: venue.serviceFeePercentage ?? 0,\n serviceFeeCents: venue.serviceFeeCents ?? 0,\n taxPercentage: venue.taxPercentage ?? 0,\n };\n}\n\n/**\n * Get venue by slug\n *\n * Fetches venue using its URL-friendly slug.\n *\n * @param slug - The venue slug\n * @returns Venue details or null on error\n */\nexport async function getVenueBySlug(slug: string): Promise<Venue | null> {\n try {\n if (!slug) {\n logger.warn('getVenueBySlug called without slug');\n return null;\n }\n\n const encodedSlug = encodeURIComponent(slug);\n // Uses /api/public/venue/:slug (same as micdrop-frontend)\n const response = await fetch(`${getLegacyPublicUrl()}/venue/${encodedSlug}`);\n\n if (!response.ok) {\n logger.error(`Failed to fetch venue by slug: ${response.status}`);\n return null;\n }\n\n return response.json();\n } catch (error) {\n logger.error('Error fetching venue by slug:', error);\n return null;\n }\n}\n","/**\n * Order Transformer\n *\n * Normalizes API order responses to a consistent format.\n * Handles variations in field names between different API versions.\n */\n\nimport type { Order, PurchasedTicket } from '../types.js';\n\n/**\n * Raw API order response (may have varying field names)\n */\ninterface ApiOrder {\n uuid?: string;\n id?: number;\n ID?: number;\n customerEmail?: string;\n email?: string;\n customer_email?: string;\n customerFirstName?: string;\n firstName?: string;\n first_name?: string;\n customerLastName?: string;\n lastName?: string;\n last_name?: string;\n status?: string;\n totalAmount?: number;\n total?: number;\n total_amount?: number;\n subtotal?: number;\n serviceFeesAmount?: number;\n serviceFee?: number;\n service_fee?: number;\n service_fees_amount?: number;\n taxAmount?: number;\n tax?: number;\n tax_amount?: number;\n discount?: number;\n paymentIntentId?: string;\n payment_intent_id?: string;\n paymentMethod?: string;\n payment_method?: string;\n purchasedTickets?: any[];\n tickets?: any[];\n purchased_tickets?: any[];\n createdAt?: string;\n created_at?: string;\n updatedAt?: string;\n updated_at?: string;\n}\n\n/**\n * Raw API ticket response\n */\ninterface ApiTicket {\n uuid?: string;\n id?: number;\n ID?: number;\n ticketNumber?: string;\n ticket_number?: string;\n orderId?: string | number;\n order_id?: string | number;\n attendeeFirstName?: string;\n attendee_first_name?: string;\n firstName?: string;\n attendeeLastName?: string;\n attendee_last_name?: string;\n lastName?: string;\n attendeeEmail?: string;\n attendee_email?: string;\n email?: string;\n ticketName?: string;\n ticket_name?: string;\n name?: string;\n ticketTypeId?: number;\n ticket_type_id?: number;\n purchasePrice?: number;\n purchase_price?: number;\n price?: number;\n status?: string;\n checkedIn?: boolean;\n checked_in?: boolean;\n checkedInAt?: string;\n checked_in_at?: string;\n}\n\n/**\n * Transform a raw API ticket to normalized PurchasedTicket\n */\nexport function transformTicket(apiTicket: ApiTicket): PurchasedTicket {\n return {\n uuid: apiTicket.uuid || String(apiTicket.id || apiTicket.ID || ''),\n id: apiTicket.id || apiTicket.ID,\n ticketNumber: apiTicket.ticketNumber || apiTicket.ticket_number,\n orderId: apiTicket.orderId || apiTicket.order_id,\n attendeeFirstName:\n apiTicket.attendeeFirstName ||\n apiTicket.attendee_first_name ||\n apiTicket.firstName,\n attendeeLastName:\n apiTicket.attendeeLastName ||\n apiTicket.attendee_last_name ||\n apiTicket.lastName,\n attendeeEmail:\n apiTicket.attendeeEmail || apiTicket.attendee_email || apiTicket.email,\n ticketName:\n apiTicket.ticketName || apiTicket.ticket_name || apiTicket.name || '',\n ticketTypeId: apiTicket.ticketTypeId || apiTicket.ticket_type_id,\n purchasePrice:\n apiTicket.purchasePrice ||\n apiTicket.purchase_price ||\n apiTicket.price ||\n 0,\n status: apiTicket.status,\n checkedIn: apiTicket.checkedIn || apiTicket.checked_in,\n checkedInAt: apiTicket.checkedInAt || apiTicket.checked_in_at,\n };\n}\n\n/**\n * Transform a raw API order to normalized Order\n *\n * Handles various field name patterns:\n * - camelCase (customerEmail)\n * - snake_case (customer_email)\n * - Shortened names (email)\n */\nexport function transformOrder(apiOrder: ApiOrder): Order {\n // Extract tickets array from various possible field names\n const rawTickets =\n apiOrder.purchasedTickets ||\n apiOrder.tickets ||\n apiOrder.purchased_tickets ||\n [];\n\n return {\n uuid: apiOrder.uuid || String(apiOrder.id || apiOrder.ID || ''),\n id: apiOrder.id || apiOrder.ID,\n customerEmail:\n apiOrder.customerEmail ||\n apiOrder.email ||\n apiOrder.customer_email ||\n '',\n customerFirstName:\n apiOrder.customerFirstName ||\n apiOrder.firstName ||\n apiOrder.first_name,\n customerLastName:\n apiOrder.customerLastName ||\n apiOrder.lastName ||\n apiOrder.last_name,\n status: apiOrder.status || 'unknown',\n totalAmount:\n apiOrder.totalAmount ||\n apiOrder.total ||\n apiOrder.total_amount ||\n 0,\n subtotal: apiOrder.subtotal,\n serviceFeesAmount:\n apiOrder.serviceFeesAmount ||\n apiOrder.serviceFee ||\n apiOrder.service_fee ||\n apiOrder.service_fees_amount ||\n 0,\n taxAmount:\n apiOrder.taxAmount || apiOrder.tax || apiOrder.tax_amount || 0,\n discount: apiOrder.discount || 0,\n paymentIntentId:\n apiOrder.paymentIntentId || apiOrder.payment_intent_id,\n paymentMethod: apiOrder.paymentMethod || apiOrder.payment_method,\n purchasedTickets: rawTickets.map(transformTicket),\n createdAt: apiOrder.createdAt || apiOrder.created_at,\n updatedAt: apiOrder.updatedAt || apiOrder.updated_at,\n };\n}\n\n/**\n * Transform order for display on success page\n *\n * Returns a simplified object with display-ready values.\n */\nexport function transformOrderForDisplay(apiOrder: ApiOrder): {\n orderId: string;\n displayOrderId: string;\n email: string;\n customerName: string;\n total: number;\n formattedTotal: string;\n ticketCount: number;\n status: string;\n} {\n const order = transformOrder(apiOrder);\n const displayId = order.uuid.split('-')[0] || order.uuid;\n\n return {\n orderId: order.uuid,\n displayOrderId: displayId,\n email: order.customerEmail,\n customerName: [order.customerFirstName, order.customerLastName]\n .filter(Boolean)\n .join(' '),\n total: order.totalAmount,\n formattedTotal: `$${(order.totalAmount / 100).toFixed(2)}`,\n ticketCount: order.purchasedTickets.length,\n status: order.status,\n };\n}\n","/**\n * Event Transformer\n *\n * Normalizes API event responses to a consistent format.\n * Handles image URL resolution and CTA state calculation.\n */\n\nimport type { Event, AvailableTicket } from '../types.js';\n\n// CDN base URL for images\nconst CDN_BASE_URL = 'https://micdrop-images.sfo3.digitaloceanspaces.com';\n\n/**\n * Raw API event response (may have varying field names)\n */\ninterface ApiEvent {\n eventID?: number;\n id?: number;\n ID?: number;\n name?: string;\n title?: string;\n slug?: string;\n description?: string;\n date?: string;\n startDateTime?: string;\n start_date_time?: string;\n endDateTime?: string;\n end_date_time?: string;\n doorsOpenTime?: string;\n doors_open_time?: string;\n timezone?: string;\n time_zone?: string;\n venueId?: number;\n venue_id?: number;\n venueName?: string;\n venue_name?: string;\n venueAddress?: string;\n venue_address?: string;\n location?: string;\n imageUrl?: string;\n imageURL?: string;\n image_url?: string;\n image?: string;\n status?: string;\n isPublished?: boolean;\n is_published?: boolean;\n isCancelled?: boolean;\n is_cancelled?: boolean;\n availableTickets?: any[];\n available_tickets?: any[];\n tickets?: any[];\n ticketsAvailable?: number;\n tickets_available?: number;\n ticketsSold?: number;\n tickets_sold?: number;\n minPrice?: number;\n min_price?: number;\n maxPrice?: number;\n max_price?: number;\n ctaText?: string;\n cta_text?: string;\n ctaState?: string;\n cta_state?: string;\n showPerformers?: boolean;\n show_performers?: boolean;\n eventSeriesId?: number;\n event_series_id?: number;\n seriesInstanceNumber?: number;\n series_instance_number?: number;\n}\n\n/**\n * Get CDN image URL\n *\n * Prepends the CDN base URL if the path is relative.\n */\nexport function getCDNImageUrl(path: string | undefined): string {\n if (!path) return '';\n if (path.startsWith('http')) return path;\n return `${CDN_BASE_URL}/${path.replace(/^\\//, '')}`;\n}\n\n/**\n * Extract image URL from event with fallbacks\n */\nexport function getEventImageUrl(apiEvent: ApiEvent): string {\n const rawUrl =\n apiEvent.imageUrl ||\n apiEvent.imageURL ||\n apiEvent.image_url ||\n apiEvent.image ||\n '';\n\n return getCDNImageUrl(rawUrl);\n}\n\n/**\n * Calculate CTA state based on ticket availability\n */\nexport function calculateCtaState(\n apiEvent: ApiEvent\n): 'available' | 'sold_out' | 'coming_soon' | 'ended' {\n // Check explicit CTA state first\n const explicitState = apiEvent.ctaState || apiEvent.cta_state;\n if (explicitState) {\n return explicitState as any;\n }\n\n // Check if event is cancelled or ended\n if (apiEvent.isCancelled || apiEvent.is_cancelled) {\n return 'ended';\n }\n\n // Check event date\n const eventDate = apiEvent.startDateTime || apiEvent.start_date_time || apiEvent.date;\n if (eventDate) {\n const eventTime = new Date(eventDate).getTime();\n const now = Date.now();\n\n if (eventTime < now) {\n return 'ended';\n }\n }\n\n // Check ticket availability\n const availableCount =\n apiEvent.ticketsAvailable ?? apiEvent.tickets_available;\n\n if (availableCount !== undefined) {\n if (availableCount <= 0) {\n return 'sold_out';\n }\n return 'available';\n }\n\n // Check tickets array\n const tickets =\n apiEvent.availableTickets ||\n apiEvent.available_tickets ||\n apiEvent.tickets ||\n [];\n\n if (tickets.length === 0) {\n return 'coming_soon';\n }\n\n const totalAvailable = tickets.reduce((sum: number, t: any) => {\n const qty =\n t.quantityAvailable ?? t.quantity_available ?? t.quantity ?? 0;\n const sold = t.quantitySold ?? t.quantity_sold ?? 0;\n return sum + Math.max(0, qty - sold);\n }, 0);\n\n if (totalAvailable <= 0) {\n return 'sold_out';\n }\n\n return 'available';\n}\n\n/**\n * Transform a raw API ticket to normalized AvailableTicket\n */\nexport function transformTicket(apiTicket: any): AvailableTicket {\n return {\n id: apiTicket.id || apiTicket.ID,\n name: apiTicket.name || apiTicket.ticketName || '',\n description: apiTicket.description,\n price: apiTicket.price || 0,\n quantity: apiTicket.quantity || apiTicket.totalQuantity || 0,\n quantitySold: apiTicket.quantitySold || apiTicket.quantity_sold || 0,\n quantityAvailable:\n apiTicket.quantityAvailable ||\n apiTicket.quantity_available ||\n (apiTicket.quantity || 0) - (apiTicket.quantitySold || 0),\n minPerOrder: apiTicket.minPerOrder || apiTicket.min_per_order || 1,\n maxPerOrder: apiTicket.maxPerOrder || apiTicket.max_per_order || 10,\n saleStartDate: apiTicket.saleStartDate || apiTicket.sale_start_date,\n saleEndDate: apiTicket.saleEndDate || apiTicket.sale_end_date,\n isHidden: apiTicket.isHidden || apiTicket.is_hidden || false,\n revealWithPromoCode:\n apiTicket.revealWithPromoCode || apiTicket.reveal_with_promo_code,\n ticketType: apiTicket.ticketType || apiTicket.ticket_type || 0,\n sectionId: apiTicket.sectionId || apiTicket.section_id,\n sortOrder: apiTicket.sortOrder || apiTicket.sort_order || 0,\n };\n}\n\n/**\n * Transform a raw API event to normalized Event\n */\nexport function transformEvent(apiEvent: ApiEvent): Event {\n // Extract tickets array from various possible field names\n const rawTickets =\n apiEvent.availableTickets ||\n apiEvent.available_tickets ||\n apiEvent.tickets ||\n [];\n\n const tickets = rawTickets.map(transformTicket);\n\n // Calculate min/max prices from tickets\n const prices = tickets.map((t) => t.price).filter((p) => p > 0);\n const minPrice = prices.length > 0 ? Math.min(...prices) : undefined;\n const maxPrice = prices.length > 0 ? Math.max(...prices) : undefined;\n\n return {\n eventID: apiEvent.eventID || apiEvent.id || apiEvent.ID || 0,\n id: apiEvent.id || apiEvent.ID,\n name: apiEvent.name || apiEvent.title || '',\n title: apiEvent.title || apiEvent.name,\n slug: apiEvent.slug,\n description: apiEvent.description,\n date: apiEvent.date || apiEvent.startDateTime || apiEvent.start_date_time || '',\n startDateTime: apiEvent.startDateTime || apiEvent.start_date_time,\n endDateTime: apiEvent.endDateTime || apiEvent.end_date_time,\n doorsOpenTime: apiEvent.doorsOpenTime || apiEvent.doors_open_time,\n timezone: apiEvent.timezone || apiEvent.time_zone,\n venueId: apiEvent.venueId || apiEvent.venue_id,\n venueName: apiEvent.venueName || apiEvent.venue_name,\n venueAddress: apiEvent.venueAddress || apiEvent.venue_address,\n location: apiEvent.location || apiEvent.venueAddress || apiEvent.venue_address,\n imageUrl: getEventImageUrl(apiEvent),\n imageURL: getEventImageUrl(apiEvent),\n status: apiEvent.status,\n isPublished: apiEvent.isPublished ?? apiEvent.is_published,\n isCancelled: apiEvent.isCancelled ?? apiEvent.is_cancelled,\n availableTickets: tickets,\n ticketsAvailable:\n apiEvent.ticketsAvailable ??\n apiEvent.tickets_available ??\n tickets.reduce((sum, t) => sum + (t.quantityAvailable || 0), 0),\n ticketsSold: apiEvent.ticketsSold ?? apiEvent.tickets_sold,\n minPrice: apiEvent.minPrice ?? apiEvent.min_price ?? minPrice,\n maxPrice: apiEvent.maxPrice ?? apiEvent.max_price ?? maxPrice,\n ctaText: apiEvent.ctaText || apiEvent.cta_text,\n ctaState: calculateCtaState(apiEvent),\n showPerformers: apiEvent.showPerformers ?? apiEvent.show_performers,\n eventSeriesId: apiEvent.eventSeriesId || apiEvent.event_series_id,\n seriesInstanceNumber:\n apiEvent.seriesInstanceNumber || apiEvent.series_instance_number,\n };\n}\n\n/**\n * Legacy transformer name for backwards compatibility\n */\nexport const transformEventData = transformEvent;\n","/**\n * Venue Transformer\n *\n * Normalizes API venue responses to a consistent format.\n */\n\nimport type { Venue } from '../types.js';\n\n// CDN base URL for images\nconst CDN_BASE_URL = 'https://micdrop-images.sfo3.digitaloceanspaces.com';\n\n/**\n * Raw API venue response (may have varying field names)\n */\ninterface ApiVenue {\n id?: number;\n ID?: number;\n name?: string;\n slug?: string;\n address?: string;\n googleLocationNameCache?: string;\n google_location_name_cache?: string;\n city?: string;\n state?: string;\n zipCode?: string;\n zip_code?: string;\n country?: string;\n timezone?: string;\n time_zone?: string;\n logoUrl?: string;\n logo_url?: string;\n logo?: string;\n serviceFeePercentage?: number;\n service_fee_percentage?: number;\n serviceFeeCents?: number;\n service_fee_cents?: number;\n taxPercentage?: number;\n tax_percentage?: number;\n organizationId?: number;\n organization_id?: number;\n}\n\n/**\n * Get CDN image URL for venue logo\n */\nfunction getLogoUrl(path: string | undefined): string {\n if (!path) return '';\n if (path.startsWith('http')) return path;\n return `${CDN_BASE_URL}/${path.replace(/^\\//, '')}`;\n}\n\n/**\n * Transform a raw API venue to normalized Venue\n */\nexport function transformVenue(apiVenue: ApiVenue): Venue {\n const logoPath =\n apiVenue.logoUrl || apiVenue.logo_url || apiVenue.logo;\n\n return {\n id: apiVenue.id || apiVenue.ID || 0,\n name: apiVenue.name || '',\n slug: apiVenue.slug,\n address: apiVenue.address,\n googleLocationNameCache:\n apiVenue.googleLocationNameCache ||\n apiVenue.google_location_name_cache,\n city: apiVenue.city,\n state: apiVenue.state,\n zipCode: apiVenue.zipCode || apiVenue.zip_code,\n country: apiVenue.country,\n timezone: apiVenue.timezone || apiVenue.time_zone,\n logoUrl: getLogoUrl(logoPath),\n serviceFeePercentage:\n apiVenue.serviceFeePercentage ??\n apiVenue.service_fee_percentage ??\n 0,\n serviceFeeCents:\n apiVenue.serviceFeeCents ?? apiVenue.service_fee_cents ?? 0,\n taxPercentage:\n apiVenue.taxPercentage ?? apiVenue.tax_percentage ?? 0,\n organizationId:\n apiVenue.organizationId || apiVenue.organization_id,\n };\n}\n\n/**\n * Extract fee configuration from venue\n */\nexport function extractVenueFees(apiVenue: ApiVenue): {\n serviceFeePercentage: number;\n serviceFeeCents: number;\n taxPercentage: number;\n} {\n return {\n serviceFeePercentage:\n apiVenue.serviceFeePercentage ??\n apiVenue.service_fee_percentage ??\n 0,\n serviceFeeCents:\n apiVenue.serviceFeeCents ?? apiVenue.service_fee_cents ?? 0,\n taxPercentage:\n apiVenue.taxPercentage ?? apiVenue.tax_percentage ?? 0,\n };\n}\n\n/**\n * Get formatted venue address\n */\nexport function formatVenueAddress(venue: Venue): string {\n const parts = [\n venue.address,\n venue.city,\n venue.state,\n venue.zipCode,\n ].filter(Boolean);\n\n return parts.join(', ');\n}\n"],"names":["logger","message","args","DEFAULT_CONFIG","error","globalConfig","configureApi","config","getApiConfig","getPublicBaseUrl","getLegacyPublicUrl","getOrdersPublicUrl","getClientIP","apiGet","endpoint","options","apiRequest","apiPost","body","apiPut","apiDelete","method","url","controller","timeoutId","response","errorData","errorMessage","simpleFetch","createPaymentIntent","cartId","quantities","data","completeReservation","orderUuid","cancelReservation","createOrder","eventId","promoCode","getOrder","orderId","validatePaymentIntent","payload","result","extendCheckoutSession","getSessionStatus","initiateOrder","cartData","trackUTMSource","venueId","utmSource","validatePromoCode","code","encodedCode","hasPromoCodes","applyPromoCode","removePromoCode","fetchEventDetails","customFetch","fetchEventTickets","tickets","fetchEventPerformers","fetchAllVenues","orgId","venues","fetchVenueEvents","events","getMonthEvents","year","month","getOrgMonthEvents","getSeriesOccurrences","eventSeriesId","fetchSeriesOccurrences","checkEventPassword","password","encodedPassword","testNetworkConnection","getVenue","getVenueFees","venue","getVenueBySlug","slug","encodedSlug","transformTicket","apiTicket","transformOrder","apiOrder","rawTickets","transformOrderForDisplay","order","displayId","CDN_BASE_URL","getCDNImageUrl","path","getEventImageUrl","apiEvent","rawUrl","calculateCtaState","explicitState","eventDate","eventTime","now","availableCount","sum","t","qty","sold","transformEvent","prices","p","minPrice","maxPrice","transformEventData","getLogoUrl","transformVenue","apiVenue","logoPath","extractVenueFees","formatVenueAddress"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api.mjs","sources":["../../src/lib/utils/logger.js","../../src/lib/api/client.ts","../../src/lib/api/orders.ts","../../src/lib/api/promo.ts","../../src/lib/api/events.ts","../../src/lib/api/venues.ts","../../src/lib/api/transformers/order.ts","../../src/lib/api/transformers/event.ts","../../src/lib/api/transformers/venue.ts"],"sourcesContent":["/**\r\n * Centralized logger utility for MicDrop applications\r\n * Can be disabled in production or configured for different log levels\r\n */\r\n\r\n/**\r\n * @typedef {'debug' | 'info' | 'warn' | 'error'} LogLevel\r\n */\r\n\r\n/**\r\n * @typedef {Object} LoggerConfig\r\n * @property {boolean} enabled\r\n * @property {LogLevel} level\r\n * @property {string} prefix\r\n */\r\n\r\n/** @type {Record<LogLevel, number>} */\r\nconst LOG_LEVELS = {\r\n debug: 0,\r\n info: 1,\r\n warn: 2,\r\n error: 3,\r\n};\r\n\r\n/** @type {LoggerConfig} */\r\nlet config = {\r\n enabled: typeof window !== 'undefined' && import.meta.env?.DEV !== false,\r\n level: 'debug',\r\n prefix: '[MicDrop]',\r\n};\r\n\r\n/**\r\n * Configure the logger\r\n * @param {Partial<LoggerConfig>} options\r\n */\r\nexport function configureLogger(options) {\r\n config = { ...config, ...options };\r\n}\r\n\r\n/**\r\n * Check if a log level should be logged\r\n * @param {LogLevel} level\r\n * @returns {boolean}\r\n */\r\nfunction shouldLog(level) {\r\n return config.enabled && LOG_LEVELS[level] >= LOG_LEVELS[config.level];\r\n}\r\n\r\n/**\r\n * Format a log message\r\n * @param {LogLevel} level\r\n * @param {string} message\r\n * @returns {string}\r\n */\r\nfunction formatMessage(level, message) {\r\n return `${config.prefix} [${level.toUpperCase()}] ${message}`;\r\n}\r\n\r\nexport const logger = {\r\n /**\r\n * Log debug message\r\n * @param {string} message\r\n * @param {...unknown} args\r\n */\r\n debug: (message, ...args) => {\r\n if (shouldLog('debug')) {\r\n console.log(formatMessage('debug', message), ...args);\r\n }\r\n },\r\n\r\n /**\r\n * Log info message\r\n * @param {string} message\r\n * @param {...unknown} args\r\n */\r\n info: (message, ...args) => {\r\n if (shouldLog('info')) {\r\n console.info(formatMessage('info', message), ...args);\r\n }\r\n },\r\n\r\n /**\r\n * Log warning message\r\n * @param {string} message\r\n * @param {...unknown} args\r\n */\r\n warn: (message, ...args) => {\r\n if (shouldLog('warn')) {\r\n console.warn(formatMessage('warn', message), ...args);\r\n }\r\n },\r\n\r\n /**\r\n * Log error message\r\n * @param {string} message\r\n * @param {...unknown} args\r\n */\r\n error: (message, ...args) => {\r\n if (shouldLog('error')) {\r\n console.error(formatMessage('error', message), ...args);\r\n }\r\n },\r\n};\r\n\r\nexport default logger;\r\n","/**\r\n * API Client for MicDrop Public Checkout API\r\n *\r\n * Provides a centralized HTTP client with:\r\n * - Configurable base URL\r\n * - Error handling and logging\r\n * - Request/response typing\r\n * - IP address capture for payment intents\r\n */\r\n\r\nimport { logger } from '../utils/logger.js';\r\nimport type { ApiConfig, ApiResponse } from './types.js';\r\n\r\n// Default API configuration\r\nconst DEFAULT_CONFIG: Required<ApiConfig> = {\r\n baseUrl: 'https://get-micdrop.com',\r\n timeout: 30000,\r\n onError: (error: Error) => logger.error('API Error:', error),\r\n};\r\n\r\n// Global configuration (can be overridden)\r\nlet globalConfig: Required<ApiConfig> = { ...DEFAULT_CONFIG };\r\n\r\n/**\r\n * Configure the API client\r\n */\r\nexport function configureApi(config: Partial<ApiConfig>): void {\r\n globalConfig = { ...globalConfig, ...config };\r\n}\r\n\r\n/**\r\n * Get the current API configuration\r\n */\r\nexport function getApiConfig(): Required<ApiConfig> {\r\n return { ...globalConfig };\r\n}\r\n\r\n/**\r\n * Get the public API base URL for v2 endpoints\r\n */\r\nexport function getPublicBaseUrl(): string {\r\n return `${globalConfig.baseUrl}/api/v2/public`;\r\n}\r\n\r\n/**\r\n * Get the legacy public API base URL\r\n */\r\nexport function getLegacyPublicUrl(): string {\r\n return `${globalConfig.baseUrl}/api/public`;\r\n}\r\n\r\n/**\r\n * Get the orders API base URL\r\n */\r\nexport function getOrdersPublicUrl(): string {\r\n return `${globalConfig.baseUrl}/api/orders/public`;\r\n}\r\n\r\n/**\r\n * Get the user's IP address for payment intents\r\n */\r\nexport async function getClientIP(): Promise<string> {\r\n try {\r\n const response = await fetch('https://api.ipify.org?format=json');\r\n const data = await response.json();\r\n return data.ip || '';\r\n } catch (error) {\r\n logger.warn('Could not fetch client IP:', error);\r\n return '';\r\n }\r\n}\r\n\r\n/**\r\n * Make a GET request to the API\r\n */\r\nexport async function apiGet<T>(\r\n endpoint: string,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('GET', endpoint, undefined, options);\r\n}\r\n\r\n/**\r\n * Make a POST request to the API\r\n */\r\nexport async function apiPost<T>(\r\n endpoint: string,\r\n body?: unknown,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('POST', endpoint, body, options);\r\n}\r\n\r\n/**\r\n * Make a PUT request to the API\r\n */\r\nexport async function apiPut<T>(\r\n endpoint: string,\r\n body?: unknown,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('PUT', endpoint, body, options);\r\n}\r\n\r\n/**\r\n * Make a DELETE request to the API\r\n */\r\nexport async function apiDelete<T>(\r\n endpoint: string,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('DELETE', endpoint, undefined, options);\r\n}\r\n\r\n/**\r\n * Core API request function\r\n */\r\nasync function apiRequest<T>(\r\n method: string,\r\n endpoint: string,\r\n body?: unknown,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n const url = endpoint.startsWith('http')\r\n ? endpoint\r\n : `${getPublicBaseUrl()}${endpoint}`;\r\n\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), globalConfig.timeout);\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...options?.headers,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n credentials: 'include',\r\n signal: controller.signal,\r\n ...options,\r\n });\r\n\r\n clearTimeout(timeoutId);\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n const error = new Error(\r\n errorData.error || errorData.message || `HTTP ${response.status}`\r\n );\r\n globalConfig.onError(error);\r\n\r\n return {\r\n success: false,\r\n error: errorData.error || errorData.message || `HTTP ${response.status}`,\r\n statusCode: response.status,\r\n };\r\n }\r\n\r\n const data = await response.json();\r\n return {\r\n success: true,\r\n data: data as T,\r\n statusCode: response.status,\r\n };\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n\r\n const errorMessage =\r\n error instanceof Error\r\n ? error.name === 'AbortError'\r\n ? 'Request timed out'\r\n : error.message\r\n : 'Unknown error';\r\n\r\n globalConfig.onError(error instanceof Error ? error : new Error(errorMessage));\r\n\r\n return {\r\n success: false,\r\n error: errorMessage,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Simple fetch wrapper for backwards compatibility\r\n * Returns data directly or null on error\r\n */\r\nexport async function simpleFetch<T>(\r\n url: string,\r\n options?: RequestInit\r\n): Promise<T | null> {\r\n try {\r\n const response = await fetch(url, {\r\n credentials: 'include',\r\n ...options,\r\n });\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n logger.error(`API request failed: ${response.status}`, errorData);\r\n return null;\r\n }\r\n\r\n return response.json();\r\n } catch (error) {\r\n logger.error('API request error:', error);\r\n return null;\r\n }\r\n}\r\n","/**\r\n * Orders API\r\n *\r\n * Functions for managing orders, payments, and reservations\r\n * in the public checkout flow.\r\n */\r\n\r\nimport { logger } from '../utils/logger.js';\r\nimport {\r\n getPublicBaseUrl,\r\n getLegacyPublicUrl,\r\n getOrdersPublicUrl,\r\n getClientIP,\r\n simpleFetch,\r\n} from './client.js';\r\nimport type {\r\n PaymentIntentResponse,\r\n CompleteReservationResponse,\r\n CancelReservationResponse,\r\n CreateOrderResponse,\r\n ValidatePaymentRequest,\r\n ValidatePaymentResponse,\r\n ExtendSessionResponse,\r\n SessionStatus,\r\n Order,\r\n} from './types.js';\r\n\r\n/**\r\n * Create a payment intent for the cart\r\n *\r\n * This initiates the Stripe payment flow by creating a PaymentIntent\r\n * on the backend. The response includes the client_secret needed\r\n * for Stripe Elements.\r\n *\r\n * @param cartId - The cart/order UUID\r\n * @param quantities - Map of ticketId -> quantity\r\n * @returns Payment intent data including client_secret, or null on error\r\n */\r\nexport async function createPaymentIntent(\r\n cartId: string,\r\n quantities: Record<string | number, number>\r\n): Promise<PaymentIntentResponse | null> {\r\n try {\r\n // Uses /api/orders/public/cart/:uuid/payment-intent (same as micdrop-frontend)\r\n const response = await fetch(\r\n `${getOrdersPublicUrl()}/cart/${cartId}/payment-intent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n credentials: 'include',\r\n body: JSON.stringify({\r\n productQuantities: quantities,\r\n }),\r\n }\r\n );\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n logger.error('Payment intent creation failed:', errorData);\r\n throw new Error(errorData.error || 'Failed to create payment intent');\r\n }\r\n\r\n const data = await response.json();\r\n logger.debug('Payment intent created:', data);\r\n return data;\r\n } catch (error) {\r\n logger.error('createPaymentIntent error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Complete reservation after successful payment\r\n *\r\n * Called after Stripe confirms the payment to finalize the order\r\n * and generate tickets.\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Success status and message\r\n */\r\nexport async function completeReservation(\r\n orderUuid: string\r\n): Promise<CompleteReservationResponse> {\r\n try {\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/orders/complete/${orderUuid}`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n }\r\n );\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n return {\r\n success: false,\r\n error: errorData.error || 'Failed to complete reservation',\r\n };\r\n }\r\n\r\n const result = await response.json();\r\n return {\r\n success: true,\r\n message: result.message,\r\n };\r\n } catch (error) {\r\n logger.error('Error completing reservation:', error);\r\n return { success: false, error: 'Network error completing reservation' };\r\n }\r\n}\r\n\r\n/**\r\n * Cancel reservation and release tickets back to inventory\r\n *\r\n * Called when user abandons checkout or session expires.\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Success status and message\r\n */\r\nexport async function cancelReservation(\r\n orderUuid: string\r\n): Promise<CancelReservationResponse> {\r\n try {\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/orders/cancel/${orderUuid}`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n }\r\n );\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n return {\r\n success: false,\r\n error: errorData.error || 'Failed to cancel reservation',\r\n };\r\n }\r\n\r\n const result = await response.json();\r\n return {\r\n success: true,\r\n message: result.message,\r\n };\r\n } catch (error) {\r\n logger.error('Error cancelling reservation:', error);\r\n return { success: false, error: 'Network error cancelling reservation' };\r\n }\r\n}\r\n\r\n/**\r\n * Create a new order/cart\r\n *\r\n * This creates an empty order that can be used for checkout.\r\n * The order UUID is used for all subsequent operations.\r\n *\r\n * @param eventId - The event ID\r\n * @param promoCode - Optional promo code to apply\r\n * @returns The order UUID, or null on error\r\n */\r\nexport async function createOrder(\r\n eventId: string | number,\r\n promoCode?: string\r\n): Promise<CreateOrderResponse | null> {\r\n try {\r\n // Uses /api/public/createOrder (same as micdrop-frontend)\r\n const response = await fetch(`${getLegacyPublicUrl()}/createOrder`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n eventID: eventId,\r\n promoCode,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n logger.error('Create order failed:', errorData);\r\n return null;\r\n }\r\n\r\n return response.json();\r\n } catch (error) {\r\n logger.error('createOrder error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get order details (public, no auth required)\r\n *\r\n * Fetches the order details for displaying on the success page.\r\n *\r\n * @param orderId - The order UUID or ID\r\n * @returns The order details, or null on error\r\n */\r\nexport async function getOrder(orderId: string): Promise<Order | null> {\r\n // Uses /api/public/getOrder/:id (same as micdrop-frontend)\r\n return simpleFetch<Order>(`${getLegacyPublicUrl()}/getOrder/${orderId}`);\r\n}\r\n\r\n/**\r\n * Validate payment intent and complete the order\r\n *\r\n * This is an alternative to completeReservation that accepts\r\n * additional payment details. Used by micdrop-frontend.\r\n *\r\n * @param cartId - The cart/order UUID\r\n * @param payload - Payment validation payload\r\n * @returns Validation result\r\n */\r\nexport async function validatePaymentIntent(\r\n cartId: string,\r\n payload: ValidatePaymentRequest\r\n): Promise<ValidatePaymentResponse | null> {\r\n try {\r\n // Uses /api/public/validatePaymentIntent/:id (same as micdrop-frontend)\r\n const response = await fetch(\r\n `${getLegacyPublicUrl()}/validatePaymentIntent/${cartId}`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(payload),\r\n }\r\n );\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n logger.error('Payment validation failed:', errorData);\r\n return {\r\n success: false,\r\n status: 'failed',\r\n error: errorData.error || 'Payment validation failed',\r\n };\r\n }\r\n\r\n const result = await response.json();\r\n return {\r\n success: true,\r\n status: result.status || 'Payment succeeded',\r\n orderUUID: result.orderUUID || result.uuid,\r\n };\r\n } catch (error) {\r\n logger.error('validatePaymentIntent error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Extend the checkout session by 15 minutes\r\n *\r\n * Users get a limited number of extensions (typically 2-3).\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Extension result with new expiry time\r\n */\r\nexport async function extendCheckoutSession(\r\n orderUuid: string\r\n): Promise<ExtendSessionResponse> {\r\n try {\r\n const response = await fetch(`${getPublicBaseUrl()}/orders/extend-session`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({ orderUuid }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n return {\r\n success: false,\r\n error: errorData.error || 'Failed to extend session',\r\n };\r\n }\r\n\r\n const result = await response.json();\r\n return {\r\n success: true,\r\n newExpiryTime: result.newExpiryTime,\r\n remainingExtensions: result.remainingExtensions,\r\n };\r\n } catch (error) {\r\n logger.error('Error extending checkout session:', error);\r\n return { success: false, error: 'Network error extending session' };\r\n }\r\n}\r\n\r\n/**\r\n * Get current session status including expiry time\r\n *\r\n * Used to display countdown timer and check if extensions are available.\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Session status including expiry time\r\n */\r\nexport async function getSessionStatus(orderUuid: string): Promise<SessionStatus> {\r\n try {\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/orders/session/${orderUuid}`\r\n );\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n return { error: errorData.error || 'No active session found' };\r\n }\r\n\r\n const result = await response.json();\r\n return {\r\n expiresAt: result.expiresAt,\r\n extensionCount: result.extensionCount,\r\n remainingExtensions: result.remainingExtensions,\r\n canExtend: result.canExtend,\r\n reservationCount: result.reservationCount,\r\n };\r\n } catch (error) {\r\n logger.error('Error getting session status:', error);\r\n return { error: 'Network error getting session status' };\r\n }\r\n}\r\n\r\n/**\r\n * Initiate a new order (alias for createOrder)\r\n *\r\n * This function provides backwards compatibility with micdrop-frontend.\r\n * It accepts the same parameters as the legacy initiateOrder function.\r\n *\r\n * @param cartData - Object containing eventID and optional quantities/promoCode\r\n * @returns The order UUID, or null on error\r\n */\r\nexport async function initiateOrder(\r\n cartData: { eventID: string | number; promoCode?: string; quantities?: Record<string | number, number> } = {} as any\r\n): Promise<string | null> {\r\n try {\r\n // Uses /api/public/createOrder (same as micdrop-frontend)\r\n const response = await fetch(`${getLegacyPublicUrl()}/createOrder`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(cartData),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n logger.error('Order initiation failed:', errorData);\r\n return null;\r\n }\r\n\r\n const data = await response.json();\r\n return data.uuid;\r\n } catch (error) {\r\n logger.error('initiateOrder error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Track UTM source for analytics\r\n *\r\n * Records the traffic source (utm_source parameter) for marketing analytics.\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Promise that resolves when tracking is complete\r\n */\r\nexport async function trackUTMSource(venueId: string | number): Promise<void> {\r\n if (typeof window === 'undefined') return;\r\n\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const utmSource = urlParams.get('utm_source') || 'Direct';\r\n\r\n try {\r\n // Uses /api/public/increment/:venueId/:source (same as micdrop-frontend)\r\n await fetch(\r\n `${getLegacyPublicUrl()}/increment/${venueId}/${encodeURIComponent(utmSource)}`\r\n );\r\n } catch (error) {\r\n logger.error('UTM tracking failed:', error);\r\n }\r\n}\r\n","/**\r\n * Promo Codes API\r\n *\r\n * Functions for validating and checking promo codes\r\n * in the public checkout flow.\r\n */\r\n\r\nimport { logger } from '../utils/logger.js';\r\nimport { getPublicBaseUrl } from './client.js';\r\nimport type { PromoValidationResponse, HasPromoCodesResponse } from './types.js';\r\n\r\n/**\r\n * Validate a promo code for an event\r\n *\r\n * Checks if a promo code is valid and returns its effects:\r\n * - Discount amount and type\r\n * - Hidden ticket reveal\r\n *\r\n * @param eventId - The event ID\r\n * @param code - The promo code to validate\r\n * @returns Validation result with discount info\r\n */\r\nexport async function validatePromoCode(\r\n eventId: string | number,\r\n code: string\r\n): Promise<PromoValidationResponse> {\r\n try {\r\n if (!code || !code.trim()) {\r\n return { valid: false, error: 'Promo code is required' };\r\n }\r\n\r\n // API uses GET with code in URL path\r\n const encodedCode = encodeURIComponent(code.trim());\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/promo-codes/validate/${eventId}/${encodedCode}`\r\n );\r\n\r\n if (!response.ok) {\r\n // 404 = invalid code, other errors are server issues\r\n if (response.status === 404) {\r\n return { valid: false, error: 'Invalid promo code' };\r\n }\r\n const errorData = await response.json().catch(() => ({}));\r\n return { valid: false, error: errorData.error || 'Failed to validate code' };\r\n }\r\n\r\n const result = await response.json();\r\n return {\r\n valid: result.valid ?? true,\r\n revealHiddenTickets: result.revealHiddenTickets,\r\n revealTicketIds: result.revealTicketIds,\r\n provideDiscount: result.provideDiscount,\r\n discountType: result.discountType,\r\n amount: result.amount,\r\n code: result.code || code,\r\n };\r\n } catch (error) {\r\n logger.error('Error validating promo code:', error);\r\n return { valid: false, error: 'Network error validating code' };\r\n }\r\n}\r\n\r\n/**\r\n * Check if promo codes are available for an event\r\n *\r\n * Used to conditionally show/hide the promo code input field.\r\n *\r\n * @param eventId - The event ID\r\n * @returns Whether promo codes exist for this event\r\n */\r\nexport async function hasPromoCodes(eventId: string | number): Promise<boolean> {\r\n try {\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/promo-codes/check/${eventId}`\r\n );\r\n\r\n if (!response.ok) {\r\n // If endpoint doesn't exist or errors, default to showing the input\r\n return true;\r\n }\r\n\r\n const result: HasPromoCodesResponse = await response.json();\r\n return result.hasPromoCodes === true;\r\n } catch (error) {\r\n logger.error('Error checking promo codes availability:', error);\r\n // Default to showing promo input if we can't check\r\n return true;\r\n }\r\n}\r\n\r\n/**\r\n * Apply a promo code to a cart\r\n *\r\n * This updates the cart with the promo code discount.\r\n *\r\n * @param cartId - The cart UUID\r\n * @param code - The promo code to apply\r\n * @returns Success status\r\n */\r\nexport async function applyPromoCode(\r\n cartId: string,\r\n code: string\r\n): Promise<{ success: boolean; error?: string }> {\r\n try {\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/orders/${cartId}/apply-promo`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({ code }),\r\n }\r\n );\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n return {\r\n success: false,\r\n error: errorData.error || 'Failed to apply promo code',\r\n };\r\n }\r\n\r\n return { success: true };\r\n } catch (error) {\r\n logger.error('Error applying promo code:', error);\r\n return { success: false, error: 'Network error applying code' };\r\n }\r\n}\r\n\r\n/**\r\n * Remove a promo code from a cart\r\n *\r\n * @param cartId - The cart UUID\r\n * @returns Success status\r\n */\r\nexport async function removePromoCode(\r\n cartId: string\r\n): Promise<{ success: boolean; error?: string }> {\r\n try {\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/orders/${cartId}/remove-promo`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n }\r\n );\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n return {\r\n success: false,\r\n error: errorData.error || 'Failed to remove promo code',\r\n };\r\n }\r\n\r\n return { success: true };\r\n } catch (error) {\r\n logger.error('Error removing promo code:', error);\r\n return { success: false, error: 'Network error removing code' };\r\n }\r\n}\r\n","/**\r\n * Events API\r\n *\r\n * Functions for fetching event data, tickets, and performers\r\n * in the public checkout flow.\r\n */\r\n\r\nimport { logger } from '../utils/logger.js';\r\nimport { getPublicBaseUrl, simpleFetch } from './client.js';\r\nimport type {\r\n Event,\r\n AvailableTicket,\r\n EventPerformersResponse,\r\n SeriesOccurrencesResponse,\r\n} from './types.js';\r\n\r\n/**\r\n * Fetch event details\r\n *\r\n * Gets full event information including venue and ticket data.\r\n *\r\n * @param eventId - The event ID\r\n * @param customFetch - Optional custom fetch function (for SSR)\r\n * @returns Event details or null on error\r\n */\r\nexport async function fetchEventDetails(\r\n eventId: string | number,\r\n customFetch: typeof fetch = fetch\r\n): Promise<Event | null> {\r\n try {\r\n const response = await customFetch(`${getPublicBaseUrl()}/events/${eventId}`);\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch event details: ${response.status}`);\r\n }\r\n\r\n return response.json();\r\n } catch (error) {\r\n logger.error('Error fetching event details:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Fetch available tickets for an event\r\n *\r\n * Returns all ticket types that are currently available for sale.\r\n *\r\n * @param eventId - The event ID\r\n * @returns Array of available tickets\r\n */\r\nexport async function fetchEventTickets(\r\n eventId: string | number\r\n): Promise<AvailableTicket[]> {\r\n try {\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/tickets/event/${eventId}`\r\n );\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch tickets: ${response.status}`);\r\n }\r\n\r\n const tickets = await response.json();\r\n return Array.isArray(tickets) ? tickets : [];\r\n } catch (error) {\r\n logger.error('Error fetching tickets:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Fetch performers for an event\r\n *\r\n * Returns the lineup with pre-resolved avatar URLs.\r\n *\r\n * @param eventId - The event ID\r\n * @returns Performers list and visibility flag\r\n */\r\nexport async function fetchEventPerformers(\r\n eventId: string | number\r\n): Promise<EventPerformersResponse> {\r\n try {\r\n if (!eventId) {\r\n logger.warn('fetchEventPerformers called without eventId');\r\n return { performers: [], showPerformers: false };\r\n }\r\n\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/events/${eventId}/performers`\r\n );\r\n\r\n if (!response.ok) {\r\n logger.error(\r\n `Failed to fetch performers: ${response.status} ${response.statusText}`\r\n );\r\n return { performers: [], showPerformers: false };\r\n }\r\n\r\n const data = await response.json();\r\n return {\r\n performers: Array.isArray(data.performers) ? data.performers : [],\r\n showPerformers: data.showPerformers === true,\r\n };\r\n } catch (error) {\r\n logger.error('Error fetching event performers:', error);\r\n return { performers: [], showPerformers: false };\r\n }\r\n}\r\n\r\n/**\r\n * Fetch all venues for an organization\r\n *\r\n * @param orgId - The organization ID\r\n * @returns Array of venues\r\n */\r\nexport async function fetchAllVenues(orgId: string | number): Promise<any[]> {\r\n try {\r\n if (!orgId) {\r\n logger.warn('fetchAllVenues called without orgId');\r\n return [];\r\n }\r\n\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/venues/organization/${orgId}`\r\n );\r\n\r\n if (!response.ok) {\r\n logger.error(\r\n `Failed to fetch venues: ${response.status} ${response.statusText}`\r\n );\r\n return [];\r\n }\r\n\r\n const venues = await response.json();\r\n return Array.isArray(venues) ? venues : [];\r\n } catch (error) {\r\n logger.error('Error fetching venues:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Fetch events for a venue\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Array of events\r\n */\r\nexport async function fetchVenueEvents(venueId: string | number): Promise<Event[]> {\r\n try {\r\n if (!venueId) {\r\n logger.warn('fetchVenueEvents called without venueId');\r\n return [];\r\n }\r\n\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/events/venue/${venueId}`\r\n );\r\n\r\n if (!response.ok) {\r\n logger.error(\r\n `Failed to fetch venue events: ${response.status} ${response.statusText}`\r\n );\r\n return [];\r\n }\r\n\r\n const events = await response.json();\r\n return Array.isArray(events) ? events : [];\r\n } catch (error) {\r\n logger.error('Error fetching venue events:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Get events for a specific month\r\n *\r\n * Used for calendar views to efficiently load events.\r\n *\r\n * @param venueId - The venue ID\r\n * @param year - The year (e.g., 2024)\r\n * @param month - The month (1-12)\r\n * @returns Array of events for the month\r\n */\r\nexport async function getMonthEvents(\r\n venueId: string | number,\r\n year: number,\r\n month: number\r\n): Promise<Event[]> {\r\n try {\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/events/venue/${venueId}/month/${year}/${month}`\r\n );\r\n\r\n if (!response.ok) {\r\n logger.error(`Failed to fetch month events: ${response.status}`);\r\n return [];\r\n }\r\n\r\n const data = await response.json();\r\n return Array.isArray(data.events) ? data.events : Array.isArray(data) ? data : [];\r\n } catch (error) {\r\n logger.error('Error fetching month events:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Get events for an organization for a specific month\r\n *\r\n * @param orgId - The organization ID\r\n * @param year - The year (e.g., 2024)\r\n * @param month - The month (1-12)\r\n * @returns Array of events for the month\r\n */\r\nexport async function getOrgMonthEvents(\r\n orgId: string | number,\r\n year: number,\r\n month: number\r\n): Promise<Event[]> {\r\n try {\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/events/organization/${orgId}/month/${year}/${month}`\r\n );\r\n\r\n if (!response.ok) {\r\n logger.error(`Failed to fetch org month events: ${response.status}`);\r\n return [];\r\n }\r\n\r\n const data = await response.json();\r\n return Array.isArray(data.events) ? data.events : Array.isArray(data) ? data : [];\r\n } catch (error) {\r\n logger.error('Error fetching org month events:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Get series occurrences for date selector\r\n *\r\n * Returns all instances of a recurring event series.\r\n *\r\n * @param eventSeriesId - The series ID\r\n * @returns Series occurrences\r\n */\r\nexport async function getSeriesOccurrences(\r\n eventSeriesId: number\r\n): Promise<SeriesOccurrencesResponse | null> {\r\n try {\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/series/${eventSeriesId}/occurrences`\r\n );\r\n\r\n if (!response.ok) {\r\n logger.error(`Failed to fetch series occurrences: ${response.status}`);\r\n return null;\r\n }\r\n\r\n return response.json();\r\n } catch (error) {\r\n logger.error('Error fetching series occurrences:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Fetch series occurrences with CTA state\r\n *\r\n * Returns full series data including availability status.\r\n *\r\n * @param eventSeriesId - The series ID\r\n * @param venueId - The venue ID\r\n * @returns Series occurrences with CTA state\r\n */\r\nexport async function fetchSeriesOccurrences(\r\n eventSeriesId: number,\r\n venueId: string | number\r\n): Promise<SeriesOccurrencesResponse | null> {\r\n try {\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/series/${eventSeriesId}/occurrences?venueId=${venueId}`\r\n );\r\n\r\n if (!response.ok) {\r\n logger.error(`Failed to fetch series with CTA: ${response.status}`);\r\n return null;\r\n }\r\n\r\n return response.json();\r\n } catch (error) {\r\n logger.error('Error fetching series occurrences:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Check event password\r\n *\r\n * Validates password for password-protected events.\r\n *\r\n * @param eventId - The event ID\r\n * @param password - The password to check\r\n * @returns Whether the password is valid\r\n */\r\nexport async function checkEventPassword(\r\n eventId: string | number,\r\n password: string\r\n): Promise<boolean> {\r\n try {\r\n const encodedPassword = encodeURIComponent(password);\r\n const response = await fetch(\r\n `${getPublicBaseUrl()}/events/${eventId}/check-password/${encodedPassword}`\r\n );\r\n\r\n if (!response.ok) {\r\n return false;\r\n }\r\n\r\n const result = await response.json();\r\n return result.valid === true;\r\n } catch (error) {\r\n logger.error('Error checking event password:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Test network connection\r\n *\r\n * Health check endpoint for connectivity testing.\r\n *\r\n * @param orgId - Optional org ID\r\n * @param venueId - Optional venue ID\r\n * @returns Whether the connection is working\r\n */\r\nexport async function testNetworkConnection(\r\n orgId?: string | number,\r\n venueId?: string | number\r\n): Promise<boolean> {\r\n try {\r\n // Use a simple endpoint to test connectivity\r\n const url = venueId\r\n ? `${getPublicBaseUrl()}/events/venue/${venueId}`\r\n : orgId\r\n ? `${getPublicBaseUrl()}/venues/organization/${orgId}`\r\n : `${getPublicBaseUrl()}/health`;\r\n\r\n const response = await fetch(url, {\r\n method: 'HEAD',\r\n });\r\n\r\n return response.ok;\r\n } catch (error) {\r\n logger.error('Network connection test failed:', error);\r\n return false;\r\n }\r\n}\r\n","/**\r\n * Venues API\r\n *\r\n * Functions for fetching venue data including\r\n * service fees and tax configuration.\r\n */\r\n\r\nimport { logger } from '../utils/logger.js';\r\nimport { getPublicBaseUrl, getLegacyPublicUrl, simpleFetch } from './client.js';\r\nimport type { Venue } from './types.js';\r\n\r\n/**\r\n * Get venue details (public, no auth required)\r\n *\r\n * Fetches venue information including service fees and taxes\r\n * needed for checkout calculations.\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Venue details or null on error\r\n */\r\nexport async function getVenue(venueId: string | number): Promise<Venue | null> {\r\n try {\r\n if (!venueId) {\r\n logger.warn('getVenue called without venueId');\r\n return null;\r\n }\r\n\r\n // Uses /api/public/getVenue/:id (same as micdrop-frontend)\r\n const response = await fetch(`${getLegacyPublicUrl()}/getVenue/${venueId}`);\r\n\r\n if (!response.ok) {\r\n logger.error(`Failed to fetch venue: ${response.status}`);\r\n return null;\r\n }\r\n\r\n return response.json();\r\n } catch (error) {\r\n logger.error('Error fetching venue:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get venue service fee configuration\r\n *\r\n * Returns just the fee-related fields for checkout calculations.\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Fee configuration or null on error\r\n */\r\nexport async function getVenueFees(\r\n venueId: string | number\r\n): Promise<{\r\n serviceFeePercentage: number;\r\n serviceFeeCents: number;\r\n taxPercentage: number;\r\n} | null> {\r\n const venue = await getVenue(venueId);\r\n\r\n if (!venue) {\r\n return null;\r\n }\r\n\r\n return {\r\n serviceFeePercentage: venue.serviceFeePercentage ?? 0,\r\n serviceFeeCents: venue.serviceFeeCents ?? 0,\r\n taxPercentage: venue.taxPercentage ?? 0,\r\n };\r\n}\r\n\r\n/**\r\n * Get venue by slug\r\n *\r\n * Fetches venue using its URL-friendly slug.\r\n *\r\n * @param slug - The venue slug\r\n * @returns Venue details or null on error\r\n */\r\nexport async function getVenueBySlug(slug: string): Promise<Venue | null> {\r\n try {\r\n if (!slug) {\r\n logger.warn('getVenueBySlug called without slug');\r\n return null;\r\n }\r\n\r\n const encodedSlug = encodeURIComponent(slug);\r\n // Uses /api/public/venue/:slug (same as micdrop-frontend)\r\n const response = await fetch(`${getLegacyPublicUrl()}/venue/${encodedSlug}`);\r\n\r\n if (!response.ok) {\r\n logger.error(`Failed to fetch venue by slug: ${response.status}`);\r\n return null;\r\n }\r\n\r\n return response.json();\r\n } catch (error) {\r\n logger.error('Error fetching venue by slug:', error);\r\n return null;\r\n }\r\n}\r\n","/**\r\n * Order Transformer\r\n *\r\n * Normalizes API order responses to a consistent format.\r\n * Handles variations in field names between different API versions.\r\n */\r\n\r\nimport type { Order, PurchasedTicket } from '../types.js';\r\n\r\n/**\r\n * Raw API order response (may have varying field names)\r\n */\r\ninterface ApiOrder {\r\n uuid?: string;\r\n id?: number;\r\n ID?: number;\r\n customerEmail?: string;\r\n email?: string;\r\n customer_email?: string;\r\n customerFirstName?: string;\r\n firstName?: string;\r\n first_name?: string;\r\n customerLastName?: string;\r\n lastName?: string;\r\n last_name?: string;\r\n status?: string;\r\n totalAmount?: number;\r\n total?: number;\r\n total_amount?: number;\r\n subtotal?: number;\r\n serviceFeesAmount?: number;\r\n serviceFee?: number;\r\n service_fee?: number;\r\n service_fees_amount?: number;\r\n taxAmount?: number;\r\n tax?: number;\r\n tax_amount?: number;\r\n discount?: number;\r\n paymentIntentId?: string;\r\n payment_intent_id?: string;\r\n paymentMethod?: string;\r\n payment_method?: string;\r\n purchasedTickets?: any[];\r\n tickets?: any[];\r\n purchased_tickets?: any[];\r\n createdAt?: string;\r\n created_at?: string;\r\n updatedAt?: string;\r\n updated_at?: string;\r\n}\r\n\r\n/**\r\n * Raw API ticket response\r\n */\r\ninterface ApiTicket {\r\n uuid?: string;\r\n id?: number;\r\n ID?: number;\r\n ticketNumber?: string;\r\n ticket_number?: string;\r\n orderId?: string | number;\r\n order_id?: string | number;\r\n attendeeFirstName?: string;\r\n attendee_first_name?: string;\r\n firstName?: string;\r\n attendeeLastName?: string;\r\n attendee_last_name?: string;\r\n lastName?: string;\r\n attendeeEmail?: string;\r\n attendee_email?: string;\r\n email?: string;\r\n ticketName?: string;\r\n ticket_name?: string;\r\n name?: string;\r\n ticketTypeId?: number;\r\n ticket_type_id?: number;\r\n purchasePrice?: number;\r\n purchase_price?: number;\r\n price?: number;\r\n status?: string;\r\n checkedIn?: boolean;\r\n checked_in?: boolean;\r\n checkedInAt?: string;\r\n checked_in_at?: string;\r\n}\r\n\r\n/**\r\n * Transform a raw API ticket to normalized PurchasedTicket\r\n */\r\nexport function transformTicket(apiTicket: ApiTicket): PurchasedTicket {\r\n return {\r\n uuid: apiTicket.uuid || String(apiTicket.id || apiTicket.ID || ''),\r\n id: apiTicket.id || apiTicket.ID,\r\n ticketNumber: apiTicket.ticketNumber || apiTicket.ticket_number,\r\n orderId: apiTicket.orderId || apiTicket.order_id,\r\n attendeeFirstName:\r\n apiTicket.attendeeFirstName ||\r\n apiTicket.attendee_first_name ||\r\n apiTicket.firstName,\r\n attendeeLastName:\r\n apiTicket.attendeeLastName ||\r\n apiTicket.attendee_last_name ||\r\n apiTicket.lastName,\r\n attendeeEmail:\r\n apiTicket.attendeeEmail || apiTicket.attendee_email || apiTicket.email,\r\n ticketName:\r\n apiTicket.ticketName || apiTicket.ticket_name || apiTicket.name || '',\r\n ticketTypeId: apiTicket.ticketTypeId || apiTicket.ticket_type_id,\r\n purchasePrice:\r\n apiTicket.purchasePrice ||\r\n apiTicket.purchase_price ||\r\n apiTicket.price ||\r\n 0,\r\n status: apiTicket.status,\r\n checkedIn: apiTicket.checkedIn || apiTicket.checked_in,\r\n checkedInAt: apiTicket.checkedInAt || apiTicket.checked_in_at,\r\n };\r\n}\r\n\r\n/**\r\n * Transform a raw API order to normalized Order\r\n *\r\n * Handles various field name patterns:\r\n * - camelCase (customerEmail)\r\n * - snake_case (customer_email)\r\n * - Shortened names (email)\r\n */\r\nexport function transformOrder(apiOrder: ApiOrder): Order {\r\n // Extract tickets array from various possible field names\r\n const rawTickets =\r\n apiOrder.purchasedTickets ||\r\n apiOrder.tickets ||\r\n apiOrder.purchased_tickets ||\r\n [];\r\n\r\n return {\r\n uuid: apiOrder.uuid || String(apiOrder.id || apiOrder.ID || ''),\r\n id: apiOrder.id || apiOrder.ID,\r\n customerEmail:\r\n apiOrder.customerEmail ||\r\n apiOrder.email ||\r\n apiOrder.customer_email ||\r\n '',\r\n customerFirstName:\r\n apiOrder.customerFirstName ||\r\n apiOrder.firstName ||\r\n apiOrder.first_name,\r\n customerLastName:\r\n apiOrder.customerLastName ||\r\n apiOrder.lastName ||\r\n apiOrder.last_name,\r\n status: apiOrder.status || 'unknown',\r\n totalAmount:\r\n apiOrder.totalAmount ||\r\n apiOrder.total ||\r\n apiOrder.total_amount ||\r\n 0,\r\n subtotal: apiOrder.subtotal,\r\n serviceFeesAmount:\r\n apiOrder.serviceFeesAmount ||\r\n apiOrder.serviceFee ||\r\n apiOrder.service_fee ||\r\n apiOrder.service_fees_amount ||\r\n 0,\r\n taxAmount:\r\n apiOrder.taxAmount || apiOrder.tax || apiOrder.tax_amount || 0,\r\n discount: apiOrder.discount || 0,\r\n paymentIntentId:\r\n apiOrder.paymentIntentId || apiOrder.payment_intent_id,\r\n paymentMethod: apiOrder.paymentMethod || apiOrder.payment_method,\r\n purchasedTickets: rawTickets.map(transformTicket),\r\n createdAt: apiOrder.createdAt || apiOrder.created_at,\r\n updatedAt: apiOrder.updatedAt || apiOrder.updated_at,\r\n };\r\n}\r\n\r\n/**\r\n * Transform order for display on success page\r\n *\r\n * Returns a simplified object with display-ready values.\r\n */\r\nexport function transformOrderForDisplay(apiOrder: ApiOrder): {\r\n orderId: string;\r\n displayOrderId: string;\r\n email: string;\r\n customerName: string;\r\n total: number;\r\n formattedTotal: string;\r\n ticketCount: number;\r\n status: string;\r\n} {\r\n const order = transformOrder(apiOrder);\r\n const displayId = order.uuid.split('-')[0] || order.uuid;\r\n\r\n return {\r\n orderId: order.uuid,\r\n displayOrderId: displayId,\r\n email: order.customerEmail,\r\n customerName: [order.customerFirstName, order.customerLastName]\r\n .filter(Boolean)\r\n .join(' '),\r\n total: order.totalAmount,\r\n formattedTotal: `$${(order.totalAmount / 100).toFixed(2)}`,\r\n ticketCount: order.purchasedTickets.length,\r\n status: order.status,\r\n };\r\n}\r\n","/**\r\n * Event Transformer\r\n *\r\n * Normalizes API event responses to a consistent format.\r\n * Handles image URL resolution and CTA state calculation.\r\n */\r\n\r\nimport type { Event, AvailableTicket } from '../types.js';\r\n\r\n// CDN base URL for images\r\nconst CDN_BASE_URL = 'https://micdrop-images.sfo3.digitaloceanspaces.com';\r\n\r\n/**\r\n * Raw API event response (may have varying field names)\r\n */\r\ninterface ApiEvent {\r\n eventID?: number;\r\n id?: number;\r\n ID?: number;\r\n name?: string;\r\n title?: string;\r\n slug?: string;\r\n description?: string;\r\n date?: string;\r\n startDateTime?: string;\r\n start_date_time?: string;\r\n endDateTime?: string;\r\n end_date_time?: string;\r\n doorsOpenTime?: string;\r\n doors_open_time?: string;\r\n timezone?: string;\r\n time_zone?: string;\r\n venueId?: number;\r\n venue_id?: number;\r\n venueName?: string;\r\n venue_name?: string;\r\n venueAddress?: string;\r\n venue_address?: string;\r\n location?: string;\r\n imageUrl?: string;\r\n imageURL?: string;\r\n image_url?: string;\r\n image?: string;\r\n status?: string;\r\n isPublished?: boolean;\r\n is_published?: boolean;\r\n isCancelled?: boolean;\r\n is_cancelled?: boolean;\r\n availableTickets?: any[];\r\n available_tickets?: any[];\r\n tickets?: any[];\r\n ticketsAvailable?: number;\r\n tickets_available?: number;\r\n ticketsSold?: number;\r\n tickets_sold?: number;\r\n minPrice?: number;\r\n min_price?: number;\r\n maxPrice?: number;\r\n max_price?: number;\r\n ctaText?: string;\r\n cta_text?: string;\r\n ctaState?: string;\r\n cta_state?: string;\r\n showPerformers?: boolean;\r\n show_performers?: boolean;\r\n eventSeriesId?: number;\r\n event_series_id?: number;\r\n seriesInstanceNumber?: number;\r\n series_instance_number?: number;\r\n}\r\n\r\n/**\r\n * Get CDN image URL\r\n *\r\n * Prepends the CDN base URL if the path is relative.\r\n */\r\nexport function getCDNImageUrl(path: string | undefined): string {\r\n if (!path) return '';\r\n if (path.startsWith('http')) return path;\r\n return `${CDN_BASE_URL}/${path.replace(/^\\//, '')}`;\r\n}\r\n\r\n/**\r\n * Extract image URL from event with fallbacks\r\n */\r\nexport function getEventImageUrl(apiEvent: ApiEvent): string {\r\n const rawUrl =\r\n apiEvent.imageUrl ||\r\n apiEvent.imageURL ||\r\n apiEvent.image_url ||\r\n apiEvent.image ||\r\n '';\r\n\r\n return getCDNImageUrl(rawUrl);\r\n}\r\n\r\n/**\r\n * Calculate CTA state based on ticket availability\r\n */\r\nexport function calculateCtaState(\r\n apiEvent: ApiEvent\r\n): 'available' | 'sold_out' | 'coming_soon' | 'ended' {\r\n // Check explicit CTA state first\r\n const explicitState = apiEvent.ctaState || apiEvent.cta_state;\r\n if (explicitState) {\r\n return explicitState as any;\r\n }\r\n\r\n // Check if event is cancelled or ended\r\n if (apiEvent.isCancelled || apiEvent.is_cancelled) {\r\n return 'ended';\r\n }\r\n\r\n // Check event date\r\n const eventDate = apiEvent.startDateTime || apiEvent.start_date_time || apiEvent.date;\r\n if (eventDate) {\r\n const eventTime = new Date(eventDate).getTime();\r\n const now = Date.now();\r\n\r\n if (eventTime < now) {\r\n return 'ended';\r\n }\r\n }\r\n\r\n // Check ticket availability\r\n const availableCount =\r\n apiEvent.ticketsAvailable ?? apiEvent.tickets_available;\r\n\r\n if (availableCount !== undefined) {\r\n if (availableCount <= 0) {\r\n return 'sold_out';\r\n }\r\n return 'available';\r\n }\r\n\r\n // Check tickets array\r\n const tickets =\r\n apiEvent.availableTickets ||\r\n apiEvent.available_tickets ||\r\n apiEvent.tickets ||\r\n [];\r\n\r\n if (tickets.length === 0) {\r\n return 'coming_soon';\r\n }\r\n\r\n const totalAvailable = tickets.reduce((sum: number, t: any) => {\r\n const qty =\r\n t.quantityAvailable ?? t.quantity_available ?? t.quantity ?? 0;\r\n const sold = t.quantitySold ?? t.quantity_sold ?? 0;\r\n return sum + Math.max(0, qty - sold);\r\n }, 0);\r\n\r\n if (totalAvailable <= 0) {\r\n return 'sold_out';\r\n }\r\n\r\n return 'available';\r\n}\r\n\r\n/**\r\n * Transform a raw API ticket to normalized AvailableTicket\r\n */\r\nexport function transformTicket(apiTicket: any): AvailableTicket {\r\n return {\r\n id: apiTicket.id || apiTicket.ID,\r\n name: apiTicket.name || apiTicket.ticketName || '',\r\n description: apiTicket.description,\r\n price: apiTicket.price || 0,\r\n quantity: apiTicket.quantity || apiTicket.totalQuantity || 0,\r\n quantitySold: apiTicket.quantitySold || apiTicket.quantity_sold || 0,\r\n quantityAvailable:\r\n apiTicket.quantityAvailable ||\r\n apiTicket.quantity_available ||\r\n (apiTicket.quantity || 0) - (apiTicket.quantitySold || 0),\r\n minPerOrder: apiTicket.minPerOrder || apiTicket.min_per_order || 1,\r\n maxPerOrder: apiTicket.maxPerOrder || apiTicket.max_per_order || 10,\r\n saleStartDate: apiTicket.saleStartDate || apiTicket.sale_start_date,\r\n saleEndDate: apiTicket.saleEndDate || apiTicket.sale_end_date,\r\n isHidden: apiTicket.isHidden || apiTicket.is_hidden || false,\r\n revealWithPromoCode:\r\n apiTicket.revealWithPromoCode || apiTicket.reveal_with_promo_code,\r\n ticketType: apiTicket.ticketType || apiTicket.ticket_type || 0,\r\n sectionId: apiTicket.sectionId || apiTicket.section_id,\r\n sortOrder: apiTicket.sortOrder || apiTicket.sort_order || 0,\r\n };\r\n}\r\n\r\n/**\r\n * Transform a raw API event to normalized Event\r\n */\r\nexport function transformEvent(apiEvent: ApiEvent): Event {\r\n // Extract tickets array from various possible field names\r\n const rawTickets =\r\n apiEvent.availableTickets ||\r\n apiEvent.available_tickets ||\r\n apiEvent.tickets ||\r\n [];\r\n\r\n const tickets = rawTickets.map(transformTicket);\r\n\r\n // Calculate min/max prices from tickets\r\n const prices = tickets.map((t) => t.price).filter((p) => p > 0);\r\n const minPrice = prices.length > 0 ? Math.min(...prices) : undefined;\r\n const maxPrice = prices.length > 0 ? Math.max(...prices) : undefined;\r\n\r\n return {\r\n eventID: apiEvent.eventID || apiEvent.id || apiEvent.ID || 0,\r\n id: apiEvent.id || apiEvent.ID,\r\n name: apiEvent.name || apiEvent.title || '',\r\n title: apiEvent.title || apiEvent.name,\r\n slug: apiEvent.slug,\r\n description: apiEvent.description,\r\n date: apiEvent.date || apiEvent.startDateTime || apiEvent.start_date_time || '',\r\n startDateTime: apiEvent.startDateTime || apiEvent.start_date_time,\r\n endDateTime: apiEvent.endDateTime || apiEvent.end_date_time,\r\n doorsOpenTime: apiEvent.doorsOpenTime || apiEvent.doors_open_time,\r\n timezone: apiEvent.timezone || apiEvent.time_zone,\r\n venueId: apiEvent.venueId || apiEvent.venue_id,\r\n venueName: apiEvent.venueName || apiEvent.venue_name,\r\n venueAddress: apiEvent.venueAddress || apiEvent.venue_address,\r\n location: apiEvent.location || apiEvent.venueAddress || apiEvent.venue_address,\r\n imageUrl: getEventImageUrl(apiEvent),\r\n imageURL: getEventImageUrl(apiEvent),\r\n status: apiEvent.status,\r\n isPublished: apiEvent.isPublished ?? apiEvent.is_published,\r\n isCancelled: apiEvent.isCancelled ?? apiEvent.is_cancelled,\r\n availableTickets: tickets,\r\n ticketsAvailable:\r\n apiEvent.ticketsAvailable ??\r\n apiEvent.tickets_available ??\r\n tickets.reduce((sum, t) => sum + (t.quantityAvailable || 0), 0),\r\n ticketsSold: apiEvent.ticketsSold ?? apiEvent.tickets_sold,\r\n minPrice: apiEvent.minPrice ?? apiEvent.min_price ?? minPrice,\r\n maxPrice: apiEvent.maxPrice ?? apiEvent.max_price ?? maxPrice,\r\n ctaText: apiEvent.ctaText || apiEvent.cta_text,\r\n ctaState: calculateCtaState(apiEvent),\r\n showPerformers: apiEvent.showPerformers ?? apiEvent.show_performers,\r\n eventSeriesId: apiEvent.eventSeriesId || apiEvent.event_series_id,\r\n seriesInstanceNumber:\r\n apiEvent.seriesInstanceNumber || apiEvent.series_instance_number,\r\n };\r\n}\r\n\r\n/**\r\n * Legacy transformer name for backwards compatibility\r\n */\r\nexport const transformEventData = transformEvent;\r\n","/**\r\n * Venue Transformer\r\n *\r\n * Normalizes API venue responses to a consistent format.\r\n */\r\n\r\nimport type { Venue } from '../types.js';\r\n\r\n// CDN base URL for images\r\nconst CDN_BASE_URL = 'https://micdrop-images.sfo3.digitaloceanspaces.com';\r\n\r\n/**\r\n * Raw API venue response (may have varying field names)\r\n */\r\ninterface ApiVenue {\r\n id?: number;\r\n ID?: number;\r\n name?: string;\r\n slug?: string;\r\n address?: string;\r\n googleLocationNameCache?: string;\r\n google_location_name_cache?: string;\r\n city?: string;\r\n state?: string;\r\n zipCode?: string;\r\n zip_code?: string;\r\n country?: string;\r\n timezone?: string;\r\n time_zone?: string;\r\n logoUrl?: string;\r\n logo_url?: string;\r\n logo?: string;\r\n serviceFeePercentage?: number;\r\n service_fee_percentage?: number;\r\n serviceFeeCents?: number;\r\n service_fee_cents?: number;\r\n taxPercentage?: number;\r\n tax_percentage?: number;\r\n organizationId?: number;\r\n organization_id?: number;\r\n}\r\n\r\n/**\r\n * Get CDN image URL for venue logo\r\n */\r\nfunction getLogoUrl(path: string | undefined): string {\r\n if (!path) return '';\r\n if (path.startsWith('http')) return path;\r\n return `${CDN_BASE_URL}/${path.replace(/^\\//, '')}`;\r\n}\r\n\r\n/**\r\n * Transform a raw API venue to normalized Venue\r\n */\r\nexport function transformVenue(apiVenue: ApiVenue): Venue {\r\n const logoPath =\r\n apiVenue.logoUrl || apiVenue.logo_url || apiVenue.logo;\r\n\r\n return {\r\n id: apiVenue.id || apiVenue.ID || 0,\r\n name: apiVenue.name || '',\r\n slug: apiVenue.slug,\r\n address: apiVenue.address,\r\n googleLocationNameCache:\r\n apiVenue.googleLocationNameCache ||\r\n apiVenue.google_location_name_cache,\r\n city: apiVenue.city,\r\n state: apiVenue.state,\r\n zipCode: apiVenue.zipCode || apiVenue.zip_code,\r\n country: apiVenue.country,\r\n timezone: apiVenue.timezone || apiVenue.time_zone,\r\n logoUrl: getLogoUrl(logoPath),\r\n serviceFeePercentage:\r\n apiVenue.serviceFeePercentage ??\r\n apiVenue.service_fee_percentage ??\r\n 0,\r\n serviceFeeCents:\r\n apiVenue.serviceFeeCents ?? apiVenue.service_fee_cents ?? 0,\r\n taxPercentage:\r\n apiVenue.taxPercentage ?? apiVenue.tax_percentage ?? 0,\r\n organizationId:\r\n apiVenue.organizationId || apiVenue.organization_id,\r\n };\r\n}\r\n\r\n/**\r\n * Extract fee configuration from venue\r\n */\r\nexport function extractVenueFees(apiVenue: ApiVenue): {\r\n serviceFeePercentage: number;\r\n serviceFeeCents: number;\r\n taxPercentage: number;\r\n} {\r\n return {\r\n serviceFeePercentage:\r\n apiVenue.serviceFeePercentage ??\r\n apiVenue.service_fee_percentage ??\r\n 0,\r\n serviceFeeCents:\r\n apiVenue.serviceFeeCents ?? apiVenue.service_fee_cents ?? 0,\r\n taxPercentage:\r\n apiVenue.taxPercentage ?? apiVenue.tax_percentage ?? 0,\r\n };\r\n}\r\n\r\n/**\r\n * Get formatted venue address\r\n */\r\nexport function formatVenueAddress(venue: Venue): string {\r\n const parts = [\r\n venue.address,\r\n venue.city,\r\n venue.state,\r\n venue.zipCode,\r\n ].filter(Boolean);\r\n\r\n return parts.join(', ');\r\n}\r\n"],"names":["logger","message","args","DEFAULT_CONFIG","error","globalConfig","configureApi","config","getApiConfig","getPublicBaseUrl","getLegacyPublicUrl","getOrdersPublicUrl","getClientIP","apiGet","endpoint","options","apiRequest","apiPost","body","apiPut","apiDelete","method","url","controller","timeoutId","response","errorData","errorMessage","simpleFetch","createPaymentIntent","cartId","quantities","data","completeReservation","orderUuid","cancelReservation","createOrder","eventId","promoCode","getOrder","orderId","validatePaymentIntent","payload","result","extendCheckoutSession","getSessionStatus","initiateOrder","cartData","trackUTMSource","venueId","utmSource","validatePromoCode","code","encodedCode","hasPromoCodes","applyPromoCode","removePromoCode","fetchEventDetails","customFetch","fetchEventTickets","tickets","fetchEventPerformers","fetchAllVenues","orgId","venues","fetchVenueEvents","events","getMonthEvents","year","month","getOrgMonthEvents","getSeriesOccurrences","eventSeriesId","fetchSeriesOccurrences","checkEventPassword","password","encodedPassword","testNetworkConnection","getVenue","getVenueFees","venue","getVenueBySlug","slug","encodedSlug","transformTicket","apiTicket","transformOrder","apiOrder","rawTickets","transformOrderForDisplay","order","displayId","CDN_BASE_URL","getCDNImageUrl","path","getEventImageUrl","apiEvent","rawUrl","calculateCtaState","explicitState","eventDate","eventTime","now","availableCount","sum","t","qty","sold","transformEvent","prices","p","minPrice","maxPrice","transformEventData","getLogoUrl","transformVenue","apiVenue","logoPath","extractVenueFees","formatVenueAddress"],"mappings":"AA0DO,MAAMA,IAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpB,OAAO,CAACC,MAAYC,MAAS;AAAA,EAI7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,CAACD,MAAYC,MAAS;AAAA,EAI5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,CAACD,MAAYC,MAAS;AAAA,EAI5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,CAACD,MAAYC,MAAS;AAAA,EAI7B;AACF,GCxFMC,IAAsC;AAAA,EAC1C,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS,CAACC,MAAiBJ,EAAO,MAAM,cAAcI,CAAK;AAC7D;AAGA,IAAIC,IAAoC,EAAE,GAAGF,EAAA;AAKtC,SAASG,EAAaC,GAAkC;AAC7D,EAAAF,IAAe,EAAE,GAAGA,GAAc,GAAGE,EAAA;AACvC;AAKO,SAASC,IAAoC;AAClD,SAAO,EAAE,GAAGH,EAAA;AACd;AAKO,SAASI,IAA2B;AACzC,SAAO,GAAGJ,EAAa,OAAO;AAChC;AAKO,SAASK,IAA6B;AAC3C,SAAO,GAAGL,EAAa,OAAO;AAChC;AAKO,SAASM,IAA6B;AAC3C,SAAO,GAAGN,EAAa,OAAO;AAChC;AAKA,eAAsBO,IAA+B;AACnD,MAAI;AAGF,YADa,OADI,MAAM,MAAM,mCAAmC,GACpC,KAAA,GAChB,MAAM;AAAA,EACpB,SAASR,GAAO;AACd,WAAAJ,EAAO,KAAK,8BAA8BI,CAAK,GACxC;AAAA,EACT;AACF;AAKA,eAAsBS,EACpBC,GACAC,GACyB;AACzB,SAAOC,EAAc,OAAOF,GAAU,QAAWC,CAAO;AAC1D;AAKA,eAAsBE,EACpBH,GACAI,GACAH,GACyB;AACzB,SAAOC,EAAc,QAAQF,GAAUI,GAAMH,CAAO;AACtD;AAKA,eAAsBI,EACpBL,GACAI,GACAH,GACyB;AACzB,SAAOC,EAAc,OAAOF,GAAUI,GAAMH,CAAO;AACrD;AAKA,eAAsBK,EACpBN,GACAC,GACyB;AACzB,SAAOC,EAAc,UAAUF,GAAU,QAAWC,CAAO;AAC7D;AAKA,eAAeC,EACbK,GACAP,GACAI,GACAH,GACyB;AACzB,QAAMO,IAAMR,EAAS,WAAW,MAAM,IAClCA,IACA,GAAGL,EAAA,CAAkB,GAAGK,CAAQ,IAE9BS,IAAa,IAAI,gBAAA,GACjBC,IAAY,WAAW,MAAMD,EAAW,MAAA,GAASlB,EAAa,OAAO;AAE3E,MAAI;AACF,UAAMoB,IAAW,MAAM,MAAMH,GAAK;AAAA,MAChC,QAAAD;AAAA,MACA,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAGN,GAAS;AAAA,MAAA;AAAA,MAEd,MAAMG,IAAO,KAAK,UAAUA,CAAI,IAAI;AAAA,MACpC,aAAa;AAAA,MACb,QAAQK,EAAW;AAAA,MACnB,GAAGR;AAAA,IAAA,CACJ;AAID,QAFA,aAAaS,CAAS,GAElB,CAACC,EAAS,IAAI;AAChB,YAAMC,IAAY,MAAMD,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG,GAClDrB,IAAQ,IAAI;AAAA,QAChBsB,EAAU,SAASA,EAAU,WAAW,QAAQD,EAAS,MAAM;AAAA,MAAA;AAEjE,aAAApB,EAAa,QAAQD,CAAK,GAEnB;AAAA,QACL,SAAS;AAAA,QACT,OAAOsB,EAAU,SAASA,EAAU,WAAW,QAAQD,EAAS,MAAM;AAAA,QACtE,YAAYA,EAAS;AAAA,MAAA;AAAA,IAEzB;AAGA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAHW,MAAMA,EAAS,KAAA;AAAA,MAI1B,YAAYA,EAAS;AAAA,IAAA;AAAA,EAEzB,SAASrB,GAAO;AACd,iBAAaoB,CAAS;AAEtB,UAAMG,IACJvB,aAAiB,QACbA,EAAM,SAAS,eACb,sBACAA,EAAM,UACR;AAEN,WAAAC,EAAa,QAAQD,aAAiB,QAAQA,IAAQ,IAAI,MAAMuB,CAAY,CAAC,GAEtE;AAAA,MACL,SAAS;AAAA,MACT,OAAOA;AAAA,IAAA;AAAA,EAEX;AACF;AAMA,eAAsBC,EACpBN,GACAP,GACmB;AACnB,MAAI;AACF,UAAMU,IAAW,MAAM,MAAMH,GAAK;AAAA,MAChC,aAAa;AAAA,MACb,GAAGP;AAAA,IAAA,CACJ;AAED,QAAI,CAACU,EAAS,IAAI;AAChB,YAAMC,IAAY,MAAMD,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACxD,aAAAzB,EAAO,MAAM,uBAAuByB,EAAS,MAAM,IAAIC,CAAS,GACzD;AAAA,IACT;AAEA,WAAOD,EAAS,KAAA;AAAA,EAClB,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,sBAAsBI,CAAK,GACjC;AAAA,EACT;AACF;AC3KA,eAAsByB,EACpBC,GACAC,GACuC;AACvC,MAAI;AAEF,UAAMN,IAAW,MAAM;AAAA,MACrB,GAAGd,EAAA,CAAoB,SAASmB,CAAM;AAAA,MACtC;AAAA,QACE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAAA;AAAA,QAElB,aAAa;AAAA,QACb,MAAM,KAAK,UAAU;AAAA,UACnB,mBAAmBC;AAAA,QAAA,CACpB;AAAA,MAAA;AAAA,IACH;AAGF,QAAI,CAACN,EAAS,IAAI;AAChB,YAAMC,IAAY,MAAMD,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACxD,YAAAzB,EAAO,MAAM,mCAAmC0B,CAAS,GACnD,IAAI,MAAMA,EAAU,SAAS,iCAAiC;AAAA,IACtE;AAEA,UAAMM,IAAO,MAAMP,EAAS,KAAA;AAC5B,WAAAzB,EAAO,MAAM,2BAA2BgC,CAAI,GACrCA;AAAA,EACT,SAAS5B,GAAO;AACd,WAAAJ,EAAO,MAAM,8BAA8BI,CAAK,GACzC;AAAA,EACT;AACF;AAWA,eAAsB6B,EACpBC,GACsC;AACtC,MAAI;AACF,UAAMT,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,oBAAoByB,CAAS;AAAA,MAClD;AAAA,QACE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAAA;AAAA,MAClB;AAAA,IACF;AAGF,WAAKT,EAAS,KASP;AAAA,MACL,SAAS;AAAA,MACT,UAHa,MAAMA,EAAS,KAAA,GAGZ;AAAA,IAAA,IATT;AAAA,MACL,SAAS;AAAA,MACT,QAHgB,MAAMA,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG,GAGrC,SAAS;AAAA,IAAA;AAAA,EAShC,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,iCAAiCI,CAAK,GAC5C,EAAE,SAAS,IAAO,OAAO,uCAAA;AAAA,EAClC;AACF;AAUA,eAAsB+B,EACpBD,GACoC;AACpC,MAAI;AACF,UAAMT,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,kBAAkByB,CAAS;AAAA,MAChD;AAAA,QACE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAAA;AAAA,MAClB;AAAA,IACF;AAGF,WAAKT,EAAS,KASP;AAAA,MACL,SAAS;AAAA,MACT,UAHa,MAAMA,EAAS,KAAA,GAGZ;AAAA,IAAA,IATT;AAAA,MACL,SAAS;AAAA,MACT,QAHgB,MAAMA,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG,GAGrC,SAAS;AAAA,IAAA;AAAA,EAShC,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,iCAAiCI,CAAK,GAC5C,EAAE,SAAS,IAAO,OAAO,uCAAA;AAAA,EAClC;AACF;AAYA,eAAsBgC,EACpBC,GACAC,GACqC;AACrC,MAAI;AAEF,UAAMb,IAAW,MAAM,MAAM,GAAGf,EAAA,CAAoB,gBAAgB;AAAA,MAClE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAAA;AAAA,MAElB,MAAM,KAAK,UAAU;AAAA,QACnB,SAAS2B;AAAA,QACT,WAAAC;AAAA,MAAA,CACD;AAAA,IAAA,CACF;AAED,QAAI,CAACb,EAAS,IAAI;AAChB,YAAMC,IAAY,MAAMD,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACxD,aAAAzB,EAAO,MAAM,wBAAwB0B,CAAS,GACvC;AAAA,IACT;AAEA,WAAOD,EAAS,KAAA;AAAA,EAClB,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,sBAAsBI,CAAK,GACjC;AAAA,EACT;AACF;AAUA,eAAsBmC,EAASC,GAAwC;AAErE,SAAOZ,EAAmB,GAAGlB,EAAA,CAAoB,aAAa8B,CAAO,EAAE;AACzE;AAYA,eAAsBC,EACpBX,GACAY,GACyC;AACzC,MAAI;AAEF,UAAMjB,IAAW,MAAM;AAAA,MACrB,GAAGf,EAAA,CAAoB,0BAA0BoB,CAAM;AAAA,MACvD;AAAA,QACE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAAA;AAAA,QAElB,MAAM,KAAK,UAAUY,CAAO;AAAA,MAAA;AAAA,IAC9B;AAGF,QAAI,CAACjB,EAAS,IAAI;AAChB,YAAMC,IAAY,MAAMD,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACxD,aAAAzB,EAAO,MAAM,8BAA8B0B,CAAS,GAC7C;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,OAAOA,EAAU,SAAS;AAAA,MAAA;AAAA,IAE9B;AAEA,UAAMiB,IAAS,MAAMlB,EAAS,KAAA;AAC9B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQkB,EAAO,UAAU;AAAA,MACzB,WAAWA,EAAO,aAAaA,EAAO;AAAA,IAAA;AAAA,EAE1C,SAASvC,GAAO;AACd,WAAAJ,EAAO,MAAM,gCAAgCI,CAAK,GAC3C;AAAA,EACT;AACF;AAUA,eAAsBwC,EACpBV,GACgC;AAChC,MAAI;AACF,UAAMT,IAAW,MAAM,MAAM,GAAGhB,EAAA,CAAkB,0BAA0B;AAAA,MAC1E,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAAA;AAAA,MAElB,MAAM,KAAK,UAAU,EAAE,WAAAyB,GAAW;AAAA,IAAA,CACnC;AAED,QAAI,CAACT,EAAS;AAEZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAHgB,MAAMA,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG,GAGrC,SAAS;AAAA,MAAA;AAI9B,UAAMkB,IAAS,MAAMlB,EAAS,KAAA;AAC9B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAekB,EAAO;AAAA,MACtB,qBAAqBA,EAAO;AAAA,IAAA;AAAA,EAEhC,SAASvC,GAAO;AACd,WAAAJ,EAAO,MAAM,qCAAqCI,CAAK,GAChD,EAAE,SAAS,IAAO,OAAO,kCAAA;AAAA,EAClC;AACF;AAUA,eAAsByC,EAAiBX,GAA2C;AAChF,MAAI;AACF,UAAMT,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,mBAAmByB,CAAS;AAAA,IAAA;AAGnD,QAAI,CAACT,EAAS;AAEZ,aAAO,EAAE,QADS,MAAMA,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG,GAC9B,SAAS,0BAAA;AAGrC,UAAMkB,IAAS,MAAMlB,EAAS,KAAA;AAC9B,WAAO;AAAA,MACL,WAAWkB,EAAO;AAAA,MAClB,gBAAgBA,EAAO;AAAA,MACvB,qBAAqBA,EAAO;AAAA,MAC5B,WAAWA,EAAO;AAAA,MAClB,kBAAkBA,EAAO;AAAA,IAAA;AAAA,EAE7B,SAASvC,GAAO;AACd,WAAAJ,EAAO,MAAM,iCAAiCI,CAAK,GAC5C,EAAE,OAAO,uCAAA;AAAA,EAClB;AACF;AAWA,eAAsB0C,EACpBC,IAA2G,IACnF;AACxB,MAAI;AAEF,UAAMtB,IAAW,MAAM,MAAM,GAAGf,EAAA,CAAoB,gBAAgB;AAAA,MAClE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAAA;AAAA,MAElB,MAAM,KAAK,UAAUqC,CAAQ;AAAA,IAAA,CAC9B;AAED,QAAI,CAACtB,EAAS,IAAI;AAChB,YAAMC,IAAY,MAAMD,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACxD,aAAAzB,EAAO,MAAM,4BAA4B0B,CAAS,GAC3C;AAAA,IACT;AAGA,YADa,MAAMD,EAAS,KAAA,GAChB;AAAA,EACd,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,wBAAwBI,CAAK,GACnC;AAAA,EACT;AACF;AAUA,eAAsB4C,EAAeC,GAAyC;AAC5E,MAAI,OAAO,SAAW,IAAa;AAGnC,QAAMC,IADY,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAChC,IAAI,YAAY,KAAK;AAEjD,MAAI;AAEF,UAAM;AAAA,MACJ,GAAGxC,GAAoB,cAAcuC,CAAO,IAAI,mBAAmBC,CAAS,CAAC;AAAA,IAAA;AAAA,EAEjF,SAAS9C,GAAO;AACd,IAAAJ,EAAO,MAAM,wBAAwBI,CAAK;AAAA,EAC5C;AACF;AC/WA,eAAsB+C,EACpBd,GACAe,GACkC;AAClC,MAAI;AACF,QAAI,CAACA,KAAQ,CAACA,EAAK;AACjB,aAAO,EAAE,OAAO,IAAO,OAAO,yBAAA;AAIhC,UAAMC,IAAc,mBAAmBD,EAAK,KAAA,CAAM,GAC5C3B,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,yBAAyB4B,CAAO,IAAIgB,CAAW;AAAA,IAAA;AAGtE,QAAI,CAAC5B,EAAS;AAEZ,aAAIA,EAAS,WAAW,MACf,EAAE,OAAO,IAAO,OAAO,qBAAA,IAGzB,EAAE,OAAO,IAAO,QADL,MAAMA,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG,GAChB,SAAS,0BAAA;AAGnD,UAAMkB,IAAS,MAAMlB,EAAS,KAAA;AAC9B,WAAO;AAAA,MACL,OAAOkB,EAAO,SAAS;AAAA,MACvB,qBAAqBA,EAAO;AAAA,MAC5B,iBAAiBA,EAAO;AAAA,MACxB,iBAAiBA,EAAO;AAAA,MACxB,cAAcA,EAAO;AAAA,MACrB,QAAQA,EAAO;AAAA,MACf,MAAMA,EAAO,QAAQS;AAAA,IAAA;AAAA,EAEzB,SAAShD,GAAO;AACd,WAAAJ,EAAO,MAAM,gCAAgCI,CAAK,GAC3C,EAAE,OAAO,IAAO,OAAO,gCAAA;AAAA,EAChC;AACF;AAUA,eAAsBkD,EAAcjB,GAA4C;AAC9E,MAAI;AACF,UAAMZ,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,sBAAsB4B,CAAO;AAAA,IAAA;AAGpD,WAAKZ,EAAS,MAKwB,MAAMA,EAAS,KAAA,GACvC,kBAAkB,KAJvB;AAAA,EAKX,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,4CAA4CI,CAAK,GAEvD;AAAA,EACT;AACF;AAWA,eAAsBmD,EACpBzB,GACAsB,GAC+C;AAC/C,MAAI;AACF,UAAM3B,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,WAAWqB,CAAM;AAAA,MACtC;AAAA,QACE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAAA;AAAA,QAElB,MAAM,KAAK,UAAU,EAAE,MAAAsB,GAAM;AAAA,MAAA;AAAA,IAC/B;AAGF,WAAK3B,EAAS,KAQP,EAAE,SAAS,GAAA,IANT;AAAA,MACL,SAAS;AAAA,MACT,QAHgB,MAAMA,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG,GAGrC,SAAS;AAAA,IAAA;AAAA,EAKhC,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,8BAA8BI,CAAK,GACzC,EAAE,SAAS,IAAO,OAAO,8BAAA;AAAA,EAClC;AACF;AAQA,eAAsBoD,EACpB1B,GAC+C;AAC/C,MAAI;AACF,UAAML,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,WAAWqB,CAAM;AAAA,MACtC;AAAA,QACE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAAA;AAAA,MAClB;AAAA,IACF;AAGF,WAAKL,EAAS,KAQP,EAAE,SAAS,GAAA,IANT;AAAA,MACL,SAAS;AAAA,MACT,QAHgB,MAAMA,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG,GAGrC,SAAS;AAAA,IAAA;AAAA,EAKhC,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,8BAA8BI,CAAK,GACzC,EAAE,SAAS,IAAO,OAAO,8BAAA;AAAA,EAClC;AACF;AC1IA,eAAsBqD,EACpBpB,GACAqB,IAA4B,OACL;AACvB,MAAI;AACF,UAAMjC,IAAW,MAAMiC,EAAY,GAAGjD,GAAkB,WAAW4B,CAAO,EAAE;AAE5E,QAAI,CAACZ,EAAS;AACZ,YAAM,IAAI,MAAM,kCAAkCA,EAAS,MAAM,EAAE;AAGrE,WAAOA,EAAS,KAAA;AAAA,EAClB,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,iCAAiCI,CAAK,GAC5C;AAAA,EACT;AACF;AAUA,eAAsBuD,EACpBtB,GAC4B;AAC5B,MAAI;AACF,UAAMZ,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,kBAAkB4B,CAAO;AAAA,IAAA;AAGhD,QAAI,CAACZ,EAAS;AACZ,YAAM,IAAI,MAAM,4BAA4BA,EAAS,MAAM,EAAE;AAG/D,UAAMmC,IAAU,MAAMnC,EAAS,KAAA;AAC/B,WAAO,MAAM,QAAQmC,CAAO,IAAIA,IAAU,CAAA;AAAA,EAC5C,SAASxD,GAAO;AACd,WAAAJ,EAAO,MAAM,2BAA2BI,CAAK,GACtC,CAAA;AAAA,EACT;AACF;AAUA,eAAsByD,EACpBxB,GACkC;AAClC,MAAI;AACF,QAAI,CAACA;AACH,aAAArC,EAAO,KAAK,6CAA6C,GAClD,EAAE,YAAY,IAAI,gBAAgB,GAAA;AAG3C,UAAMyB,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,WAAW4B,CAAO;AAAA,IAAA;AAGzC,QAAI,CAACZ,EAAS;AACZ,aAAAzB,EAAO;AAAA,QACL,+BAA+ByB,EAAS,MAAM,IAAIA,EAAS,UAAU;AAAA,MAAA,GAEhE,EAAE,YAAY,IAAI,gBAAgB,GAAA;AAG3C,UAAMO,IAAO,MAAMP,EAAS,KAAA;AAC5B,WAAO;AAAA,MACL,YAAY,MAAM,QAAQO,EAAK,UAAU,IAAIA,EAAK,aAAa,CAAA;AAAA,MAC/D,gBAAgBA,EAAK,mBAAmB;AAAA,IAAA;AAAA,EAE5C,SAAS5B,GAAO;AACd,WAAAJ,EAAO,MAAM,oCAAoCI,CAAK,GAC/C,EAAE,YAAY,IAAI,gBAAgB,GAAA;AAAA,EAC3C;AACF;AAQA,eAAsB0D,GAAeC,GAAwC;AAC3E,MAAI;AACF,QAAI,CAACA;AACH,aAAA/D,EAAO,KAAK,qCAAqC,GAC1C,CAAA;AAGT,UAAMyB,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,wBAAwBsD,CAAK;AAAA,IAAA;AAGpD,QAAI,CAACtC,EAAS;AACZ,aAAAzB,EAAO;AAAA,QACL,2BAA2ByB,EAAS,MAAM,IAAIA,EAAS,UAAU;AAAA,MAAA,GAE5D,CAAA;AAGT,UAAMuC,IAAS,MAAMvC,EAAS,KAAA;AAC9B,WAAO,MAAM,QAAQuC,CAAM,IAAIA,IAAS,CAAA;AAAA,EAC1C,SAAS5D,GAAO;AACd,WAAAJ,EAAO,MAAM,0BAA0BI,CAAK,GACrC,CAAA;AAAA,EACT;AACF;AAQA,eAAsB6D,GAAiBhB,GAA4C;AACjF,MAAI;AACF,QAAI,CAACA;AACH,aAAAjD,EAAO,KAAK,yCAAyC,GAC9C,CAAA;AAGT,UAAMyB,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,iBAAiBwC,CAAO;AAAA,IAAA;AAG/C,QAAI,CAACxB,EAAS;AACZ,aAAAzB,EAAO;AAAA,QACL,iCAAiCyB,EAAS,MAAM,IAAIA,EAAS,UAAU;AAAA,MAAA,GAElE,CAAA;AAGT,UAAMyC,IAAS,MAAMzC,EAAS,KAAA;AAC9B,WAAO,MAAM,QAAQyC,CAAM,IAAIA,IAAS,CAAA;AAAA,EAC1C,SAAS9D,GAAO;AACd,WAAAJ,EAAO,MAAM,gCAAgCI,CAAK,GAC3C,CAAA;AAAA,EACT;AACF;AAYA,eAAsB+D,GACpBlB,GACAmB,GACAC,GACkB;AAClB,MAAI;AACF,UAAM5C,IAAW,MAAM;AAAA,MACrB,GAAGhB,GAAkB,iBAAiBwC,CAAO,UAAUmB,CAAI,IAAIC,CAAK;AAAA,IAAA;AAGtE,QAAI,CAAC5C,EAAS;AACZ,aAAAzB,EAAO,MAAM,iCAAiCyB,EAAS,MAAM,EAAE,GACxD,CAAA;AAGT,UAAMO,IAAO,MAAMP,EAAS,KAAA;AAC5B,WAAO,MAAM,QAAQO,EAAK,MAAM,IAAIA,EAAK,SAAS,MAAM,QAAQA,CAAI,IAAIA,IAAO,CAAA;AAAA,EACjF,SAAS5B,GAAO;AACd,WAAAJ,EAAO,MAAM,gCAAgCI,CAAK,GAC3C,CAAA;AAAA,EACT;AACF;AAUA,eAAsBkE,GACpBP,GACAK,GACAC,GACkB;AAClB,MAAI;AACF,UAAM5C,IAAW,MAAM;AAAA,MACrB,GAAGhB,GAAkB,wBAAwBsD,CAAK,UAAUK,CAAI,IAAIC,CAAK;AAAA,IAAA;AAG3E,QAAI,CAAC5C,EAAS;AACZ,aAAAzB,EAAO,MAAM,qCAAqCyB,EAAS,MAAM,EAAE,GAC5D,CAAA;AAGT,UAAMO,IAAO,MAAMP,EAAS,KAAA;AAC5B,WAAO,MAAM,QAAQO,EAAK,MAAM,IAAIA,EAAK,SAAS,MAAM,QAAQA,CAAI,IAAIA,IAAO,CAAA;AAAA,EACjF,SAAS5B,GAAO;AACd,WAAAJ,EAAO,MAAM,oCAAoCI,CAAK,GAC/C,CAAA;AAAA,EACT;AACF;AAUA,eAAsBmE,GACpBC,GAC2C;AAC3C,MAAI;AACF,UAAM/C,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,WAAW+D,CAAa;AAAA,IAAA;AAG/C,WAAK/C,EAAS,KAKPA,EAAS,KAAA,KAJdzB,EAAO,MAAM,uCAAuCyB,EAAS,MAAM,EAAE,GAC9D;AAAA,EAIX,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,sCAAsCI,CAAK,GACjD;AAAA,EACT;AACF;AAWA,eAAsBqE,GACpBD,GACAvB,GAC2C;AAC3C,MAAI;AACF,UAAMxB,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,WAAW+D,CAAa,wBAAwBvB,CAAO;AAAA,IAAA;AAG9E,WAAKxB,EAAS,KAKPA,EAAS,KAAA,KAJdzB,EAAO,MAAM,oCAAoCyB,EAAS,MAAM,EAAE,GAC3D;AAAA,EAIX,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,sCAAsCI,CAAK,GACjD;AAAA,EACT;AACF;AAWA,eAAsBsE,GACpBrC,GACAsC,GACkB;AAClB,MAAI;AACF,UAAMC,IAAkB,mBAAmBD,CAAQ,GAC7ClD,IAAW,MAAM;AAAA,MACrB,GAAGhB,EAAA,CAAkB,WAAW4B,CAAO,mBAAmBuC,CAAe;AAAA,IAAA;AAG3E,WAAKnD,EAAS,MAIC,MAAMA,EAAS,KAAA,GAChB,UAAU,KAJf;AAAA,EAKX,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,kCAAkCI,CAAK,GAC7C;AAAA,EACT;AACF;AAWA,eAAsByE,GACpBd,GACAd,GACkB;AAClB,MAAI;AAEF,UAAM3B,IAAM2B,IACR,GAAGxC,EAAA,CAAkB,iBAAiBwC,CAAO,KAC7Cc,IACA,GAAGtD,GAAkB,wBAAwBsD,CAAK,KAClD,GAAGtD,GAAkB;AAMzB,YAJiB,MAAM,MAAMa,GAAK;AAAA,MAChC,QAAQ;AAAA,IAAA,CACT,GAEe;AAAA,EAClB,SAASlB,GAAO;AACd,WAAAJ,EAAO,MAAM,mCAAmCI,CAAK,GAC9C;AAAA,EACT;AACF;ACjVA,eAAsB0E,EAAS7B,GAAiD;AAC9E,MAAI;AACF,QAAI,CAACA;AACH,aAAAjD,EAAO,KAAK,iCAAiC,GACtC;AAIT,UAAMyB,IAAW,MAAM,MAAM,GAAGf,GAAoB,aAAauC,CAAO,EAAE;AAE1E,WAAKxB,EAAS,KAKPA,EAAS,KAAA,KAJdzB,EAAO,MAAM,0BAA0ByB,EAAS,MAAM,EAAE,GACjD;AAAA,EAIX,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,yBAAyBI,CAAK,GACpC;AAAA,EACT;AACF;AAUA,eAAsB2E,GACpB9B,GAKQ;AACR,QAAM+B,IAAQ,MAAMF,EAAS7B,CAAO;AAEpC,SAAK+B,IAIE;AAAA,IACL,sBAAsBA,EAAM,wBAAwB;AAAA,IACpD,iBAAiBA,EAAM,mBAAmB;AAAA,IAC1C,eAAeA,EAAM,iBAAiB;AAAA,EAAA,IAN/B;AAQX;AAUA,eAAsBC,GAAeC,GAAqC;AACxE,MAAI;AACF,QAAI,CAACA;AACH,aAAAlF,EAAO,KAAK,oCAAoC,GACzC;AAGT,UAAMmF,IAAc,mBAAmBD,CAAI,GAErCzD,IAAW,MAAM,MAAM,GAAGf,GAAoB,UAAUyE,CAAW,EAAE;AAE3E,WAAK1D,EAAS,KAKPA,EAAS,KAAA,KAJdzB,EAAO,MAAM,kCAAkCyB,EAAS,MAAM,EAAE,GACzD;AAAA,EAIX,SAASrB,GAAO;AACd,WAAAJ,EAAO,MAAM,iCAAiCI,CAAK,GAC5C;AAAA,EACT;AACF;ACVO,SAASgF,EAAgBC,GAAuC;AACrE,SAAO;AAAA,IACL,MAAMA,EAAU,QAAQ,OAAOA,EAAU,MAAMA,EAAU,MAAM,EAAE;AAAA,IACjE,IAAIA,EAAU,MAAMA,EAAU;AAAA,IAC9B,cAAcA,EAAU,gBAAgBA,EAAU;AAAA,IAClD,SAASA,EAAU,WAAWA,EAAU;AAAA,IACxC,mBACEA,EAAU,qBACVA,EAAU,uBACVA,EAAU;AAAA,IACZ,kBACEA,EAAU,oBACVA,EAAU,sBACVA,EAAU;AAAA,IACZ,eACEA,EAAU,iBAAiBA,EAAU,kBAAkBA,EAAU;AAAA,IACnE,YACEA,EAAU,cAAcA,EAAU,eAAeA,EAAU,QAAQ;AAAA,IACrE,cAAcA,EAAU,gBAAgBA,EAAU;AAAA,IAClD,eACEA,EAAU,iBACVA,EAAU,kBACVA,EAAU,SACV;AAAA,IACF,QAAQA,EAAU;AAAA,IAClB,WAAWA,EAAU,aAAaA,EAAU;AAAA,IAC5C,aAAaA,EAAU,eAAeA,EAAU;AAAA,EAAA;AAEpD;AAUO,SAASC,EAAeC,GAA2B;AAExD,QAAMC,IACJD,EAAS,oBACTA,EAAS,WACTA,EAAS,qBACT,CAAA;AAEF,SAAO;AAAA,IACL,MAAMA,EAAS,QAAQ,OAAOA,EAAS,MAAMA,EAAS,MAAM,EAAE;AAAA,IAC9D,IAAIA,EAAS,MAAMA,EAAS;AAAA,IAC5B,eACEA,EAAS,iBACTA,EAAS,SACTA,EAAS,kBACT;AAAA,IACF,mBACEA,EAAS,qBACTA,EAAS,aACTA,EAAS;AAAA,IACX,kBACEA,EAAS,oBACTA,EAAS,YACTA,EAAS;AAAA,IACX,QAAQA,EAAS,UAAU;AAAA,IAC3B,aACEA,EAAS,eACTA,EAAS,SACTA,EAAS,gBACT;AAAA,IACF,UAAUA,EAAS;AAAA,IACnB,mBACEA,EAAS,qBACTA,EAAS,cACTA,EAAS,eACTA,EAAS,uBACT;AAAA,IACF,WACEA,EAAS,aAAaA,EAAS,OAAOA,EAAS,cAAc;AAAA,IAC/D,UAAUA,EAAS,YAAY;AAAA,IAC/B,iBACEA,EAAS,mBAAmBA,EAAS;AAAA,IACvC,eAAeA,EAAS,iBAAiBA,EAAS;AAAA,IAClD,kBAAkBC,EAAW,IAAIJ,CAAe;AAAA,IAChD,WAAWG,EAAS,aAAaA,EAAS;AAAA,IAC1C,WAAWA,EAAS,aAAaA,EAAS;AAAA,EAAA;AAE9C;AAOO,SAASE,GAAyBF,GASvC;AACA,QAAMG,IAAQJ,EAAeC,CAAQ,GAC/BI,IAAYD,EAAM,KAAK,MAAM,GAAG,EAAE,CAAC,KAAKA,EAAM;AAEpD,SAAO;AAAA,IACL,SAASA,EAAM;AAAA,IACf,gBAAgBC;AAAA,IAChB,OAAOD,EAAM;AAAA,IACb,cAAc,CAACA,EAAM,mBAAmBA,EAAM,gBAAgB,EAC3D,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,IACX,OAAOA,EAAM;AAAA,IACb,gBAAgB,KAAKA,EAAM,cAAc,KAAK,QAAQ,CAAC,CAAC;AAAA,IACxD,aAAaA,EAAM,iBAAiB;AAAA,IACpC,QAAQA,EAAM;AAAA,EAAA;AAElB;ACpMA,MAAME,IAAe;AAkEd,SAASC,EAAeC,GAAkC;AAC/D,SAAKA,IACDA,EAAK,WAAW,MAAM,IAAUA,IAC7B,GAAGF,CAAY,IAAIE,EAAK,QAAQ,OAAO,EAAE,CAAC,KAF/B;AAGpB;AAKO,SAASC,EAAiBC,GAA4B;AAC3D,QAAMC,IACJD,EAAS,YACTA,EAAS,YACTA,EAAS,aACTA,EAAS,SACT;AAEF,SAAOH,EAAeI,CAAM;AAC9B;AAKO,SAASC,EACdF,GACoD;AAEpD,QAAMG,IAAgBH,EAAS,YAAYA,EAAS;AACpD,MAAIG;AACF,WAAOA;AAIT,MAAIH,EAAS,eAAeA,EAAS;AACnC,WAAO;AAIT,QAAMI,IAAYJ,EAAS,iBAAiBA,EAAS,mBAAmBA,EAAS;AACjF,MAAII,GAAW;AACb,UAAMC,IAAY,IAAI,KAAKD,CAAS,EAAE,QAAA,GAChCE,IAAM,KAAK,IAAA;AAEjB,QAAID,IAAYC;AACd,aAAO;AAAA,EAEX;AAGA,QAAMC,IACJP,EAAS,oBAAoBA,EAAS;AAExC,MAAIO,MAAmB;AACrB,WAAIA,KAAkB,IACb,aAEF;AAIT,QAAM3C,IACJoC,EAAS,oBACTA,EAAS,qBACTA,EAAS,WACT,CAAA;AAEF,SAAIpC,EAAQ,WAAW,IACd,gBAGcA,EAAQ,OAAO,CAAC4C,GAAaC,MAAW;AAC7D,UAAMC,IACJD,EAAE,qBAAqBA,EAAE,sBAAsBA,EAAE,YAAY,GACzDE,IAAOF,EAAE,gBAAgBA,EAAE,iBAAiB;AAClD,WAAOD,IAAM,KAAK,IAAI,GAAGE,IAAMC,CAAI;AAAA,EACrC,GAAG,CAAC,KAEkB,IACb,aAGF;AACT;AAKO,SAASvB,EAAgBC,GAAiC;AAC/D,SAAO;AAAA,IACL,IAAIA,EAAU,MAAMA,EAAU;AAAA,IAC9B,MAAMA,EAAU,QAAQA,EAAU,cAAc;AAAA,IAChD,aAAaA,EAAU;AAAA,IACvB,OAAOA,EAAU,SAAS;AAAA,IAC1B,UAAUA,EAAU,YAAYA,EAAU,iBAAiB;AAAA,IAC3D,cAAcA,EAAU,gBAAgBA,EAAU,iBAAiB;AAAA,IACnE,mBACEA,EAAU,qBACVA,EAAU,uBACTA,EAAU,YAAY,MAAMA,EAAU,gBAAgB;AAAA,IACzD,aAAaA,EAAU,eAAeA,EAAU,iBAAiB;AAAA,IACjE,aAAaA,EAAU,eAAeA,EAAU,iBAAiB;AAAA,IACjE,eAAeA,EAAU,iBAAiBA,EAAU;AAAA,IACpD,aAAaA,EAAU,eAAeA,EAAU;AAAA,IAChD,UAAUA,EAAU,YAAYA,EAAU,aAAa;AAAA,IACvD,qBACEA,EAAU,uBAAuBA,EAAU;AAAA,IAC7C,YAAYA,EAAU,cAAcA,EAAU,eAAe;AAAA,IAC7D,WAAWA,EAAU,aAAaA,EAAU;AAAA,IAC5C,WAAWA,EAAU,aAAaA,EAAU,cAAc;AAAA,EAAA;AAE9D;AAKO,SAASuB,EAAeZ,GAA2B;AAQxD,QAAMpC,KALJoC,EAAS,oBACTA,EAAS,qBACTA,EAAS,WACT,CAAA,GAEyB,IAAIZ,CAAe,GAGxCyB,IAASjD,EAAQ,IAAI,CAAC6C,MAAMA,EAAE,KAAK,EAAE,OAAO,CAACK,MAAMA,IAAI,CAAC,GACxDC,IAAWF,EAAO,SAAS,IAAI,KAAK,IAAI,GAAGA,CAAM,IAAI,QACrDG,IAAWH,EAAO,SAAS,IAAI,KAAK,IAAI,GAAGA,CAAM,IAAI;AAE3D,SAAO;AAAA,IACL,SAASb,EAAS,WAAWA,EAAS,MAAMA,EAAS,MAAM;AAAA,IAC3D,IAAIA,EAAS,MAAMA,EAAS;AAAA,IAC5B,MAAMA,EAAS,QAAQA,EAAS,SAAS;AAAA,IACzC,OAAOA,EAAS,SAASA,EAAS;AAAA,IAClC,MAAMA,EAAS;AAAA,IACf,aAAaA,EAAS;AAAA,IACtB,MAAMA,EAAS,QAAQA,EAAS,iBAAiBA,EAAS,mBAAmB;AAAA,IAC7E,eAAeA,EAAS,iBAAiBA,EAAS;AAAA,IAClD,aAAaA,EAAS,eAAeA,EAAS;AAAA,IAC9C,eAAeA,EAAS,iBAAiBA,EAAS;AAAA,IAClD,UAAUA,EAAS,YAAYA,EAAS;AAAA,IACxC,SAASA,EAAS,WAAWA,EAAS;AAAA,IACtC,WAAWA,EAAS,aAAaA,EAAS;AAAA,IAC1C,cAAcA,EAAS,gBAAgBA,EAAS;AAAA,IAChD,UAAUA,EAAS,YAAYA,EAAS,gBAAgBA,EAAS;AAAA,IACjE,UAAUD,EAAiBC,CAAQ;AAAA,IACnC,UAAUD,EAAiBC,CAAQ;AAAA,IACnC,QAAQA,EAAS;AAAA,IACjB,aAAaA,EAAS,eAAeA,EAAS;AAAA,IAC9C,aAAaA,EAAS,eAAeA,EAAS;AAAA,IAC9C,kBAAkBpC;AAAA,IAClB,kBACEoC,EAAS,oBACTA,EAAS,qBACTpC,EAAQ,OAAO,CAAC4C,GAAKC,MAAMD,KAAOC,EAAE,qBAAqB,IAAI,CAAC;AAAA,IAChE,aAAaT,EAAS,eAAeA,EAAS;AAAA,IAC9C,UAAUA,EAAS,YAAYA,EAAS,aAAae;AAAA,IACrD,UAAUf,EAAS,YAAYA,EAAS,aAAagB;AAAA,IACrD,SAAShB,EAAS,WAAWA,EAAS;AAAA,IACtC,UAAUE,EAAkBF,CAAQ;AAAA,IACpC,gBAAgBA,EAAS,kBAAkBA,EAAS;AAAA,IACpD,eAAeA,EAAS,iBAAiBA,EAAS;AAAA,IAClD,sBACEA,EAAS,wBAAwBA,EAAS;AAAA,EAAA;AAEhD;AAKO,MAAMiB,KAAqBL,GC9O5BhB,IAAe;AAoCrB,SAASsB,EAAWpB,GAAkC;AACpD,SAAKA,IACDA,EAAK,WAAW,MAAM,IAAUA,IAC7B,GAAGF,CAAY,IAAIE,EAAK,QAAQ,OAAO,EAAE,CAAC,KAF/B;AAGpB;AAKO,SAASqB,GAAeC,GAA2B;AACxD,QAAMC,IACJD,EAAS,WAAWA,EAAS,YAAYA,EAAS;AAEpD,SAAO;AAAA,IACL,IAAIA,EAAS,MAAMA,EAAS,MAAM;AAAA,IAClC,MAAMA,EAAS,QAAQ;AAAA,IACvB,MAAMA,EAAS;AAAA,IACf,SAASA,EAAS;AAAA,IAClB,yBACEA,EAAS,2BACTA,EAAS;AAAA,IACX,MAAMA,EAAS;AAAA,IACf,OAAOA,EAAS;AAAA,IAChB,SAASA,EAAS,WAAWA,EAAS;AAAA,IACtC,SAASA,EAAS;AAAA,IAClB,UAAUA,EAAS,YAAYA,EAAS;AAAA,IACxC,SAASF,EAAWG,CAAQ;AAAA,IAC5B,sBACED,EAAS,wBACTA,EAAS,0BACT;AAAA,IACF,iBACEA,EAAS,mBAAmBA,EAAS,qBAAqB;AAAA,IAC5D,eACEA,EAAS,iBAAiBA,EAAS,kBAAkB;AAAA,IACvD,gBACEA,EAAS,kBAAkBA,EAAS;AAAA,EAAA;AAE1C;AAKO,SAASE,GAAiBF,GAI/B;AACA,SAAO;AAAA,IACL,sBACEA,EAAS,wBACTA,EAAS,0BACT;AAAA,IACF,iBACEA,EAAS,mBAAmBA,EAAS,qBAAqB;AAAA,IAC5D,eACEA,EAAS,iBAAiBA,EAAS,kBAAkB;AAAA,EAAA;AAE3D;AAKO,SAASG,GAAmBvC,GAAsB;AAQvD,SAPc;AAAA,IACZA,EAAM;AAAA,IACNA,EAAM;AAAA,IACNA,EAAM;AAAA,IACNA,EAAM;AAAA,EAAA,EACN,OAAO,OAAO,EAEH,KAAK,IAAI;AACxB;"}
|