{"version":3,"file":"index-C3FrXjz5.js","sources":["../../../../src/ts/constants.ts","../../../../src/ts/filters/main.ts","../../../../src/ts/languages/main.ts","../../../../src/ts/tab/main.ts","../../../../src/ts/projects/packages/repository.ts","../../../../src/ts/scans/repository.ts","../../../../src/ts/findings/repository.ts","../../../../src/ts/projects/repository.ts","../../../../src/ts/policies/main.ts","../../../../src/ts/toast/main.ts","../../../../src/ts/modals/main.ts","../../../../src/ts/onboarding/main.ts","../../../../src/ts/websockets/ws-handlers.ts","../../../../src/ts/websockets/ws.ts","../../../../src/ts/firewall/main.ts","../../../../src/ts/firewall/components/FirewallIndicator.ts","../../../../src/ts/theme.ts","../../../../src/ts/users/repository.ts","../../../../src/ts/projects/risk_score_inputs/repository.ts","../../../../src/ts/index.ts"],"sourcesContent":["export const availableFilters = {\n type: [\n {\n label: 'License',\n value: 'License',\n checked: false\n }, {\n label: 'Vulnerability',\n value: 'Dep. Vulnerability',\n checked: false\n }\n ],\n risk_score: [\n {\n label: 'Critical',\n value: 'critical',\n checked: false\n }, {\n label: 'High',\n value: 'high',\n checked: false\n }, {\n label: 'Moderate',\n value: 'moderate',\n checked: false\n }, {\n label: 'Low',\n value: 'low',\n checked: false\n }, {\n label: 'Nominal',\n value: 'nominal',\n checked: false\n }\n ],\n status: [\n {\n label: 'Unassigned',\n value: 'New',\n checked: false\n }, {\n label: 'Assigned',\n value: 'High',\n checked: false\n }, {\n label: 'Resolved',\n value: 'resolved',\n checked: false\n }, {\n label: 'Archived',\n value: 'archived',\n checked: false\n }\n ],\n scan_type: [\n {\n label: 'Project Scan',\n value: 'Project',\n checked: false\n }, {\n label: 'Machine Scan',\n value: 'Machine',\n checked: false\n }, {\n label: 'System Scan',\n value: 'System',\n checked: false\n },\n ],\n stage: [\n {\n label: 'Development',\n value: 'development',\n checked: false\n }, {\n label: 'CI/CD',\n value: 'cicd',\n checked: false\n }, {\n label: 'Production',\n value: 'production',\n checked: false\n },\n ],\n findings: [\n {\n label: 'Has Critical',\n value: 'critical',\n checked: false\n }, {\n label: 'Has High',\n value: 'high',\n checked: false\n }, {\n label: 'Has Low',\n value: 'low',\n checked: false\n }, {\n label: 'Has Moderate',\n value: 'moderate',\n checked: false\n }, {\n label: 'Has Nominal',\n value: 'nominal',\n checked: false\n },\n ],\n date: [\n {\n label: 'Past hour',\n value: 'Past hour',\n from: new Date(Date.now() - 3600 * 1000).setMilliseconds(0), // 1 hour ago\n to: new Date().setMilliseconds(0),\n checked: false\n },\n {\n label: 'Past 24 hours',\n value: 'Past 24 hours',\n from: new Date(Date.now() - 86400 * 1000).setMilliseconds(0),\n to: new Date().setMilliseconds(0),\n checked: false\n }, {\n label: 'Past 7 days',\n value: 'Past 7 days',\n from: new Date(Date.now() - 7 * 86400 * 1000).setMilliseconds(0),\n to: new Date().setMilliseconds(0),\n checked: false\n }, {\n label: 'Past 30 days',\n value: 'Past 30 days',\n from: new Date(Date.now() - 30 * 86400 * 1000).setMilliseconds(0),\n to: new Date().setMilliseconds(0),\n checked: true\n }, {\n label: 'Select from calendar',\n value: 'Custom Range',\n from: undefined,\n to: undefined,\n checked: false\n }\n ],\n ecosystems: [\n {\n label: 'Pypi',\n value: 'PyPi',\n checked: false,\n }, {\n label: 'NPM',\n value: 'npm',\n checked: false,\n },\n ]\n}\n\nexport const storeFilterData = {\n findingsTableFilters: {\n table: 'Findings',\n filters: [\n { title: 'Project', col: 'project', type: 'Common' },\n { title: 'Status', col: 'status', type: 'Common' }\n ]\n },\n projectFindingsTableFilters: {\n table: 'Findings',\n filters: [\n { title: 'Status', col: 'status', type: 'Common' }\n ]\n },\n scansTableFilters: {\n table: 'Scans',\n filters: [\n { title: 'Date Range', col: 'date', type: 'Date Range' },\n { title: 'Project', col: 'project', type: 'Common' },\n { title: 'Stage', col: 'stage', type: 'Common' },\n { title: 'Findings', col: 'findings', type: 'Common' },\n { title: 'Branch', col: 'branch_name', type: 'Common' },\n ]\n },\n packagesTableFilters: {\n table: 'Project Packages',\n filters: [\n { title: 'Language', col: 'ecosystems', type: 'Common' },\n ],\n },\n projectScansTableFilters: {\n table: 'Project Scans',\n filters: [\n { title: 'Date Range', col: 'date', type: 'Date Range' },\n { title: 'Stage', col: 'stage', type: 'Common' },\n { title: 'Findings', col: 'findings', type: 'Common' }\n ]\n }\n}\n","import flatpickr from \"flatpickr\";\n\nimport {\n FindingsTableItem,\n ScanTableData,\n ProjectTableData,\n PackageTableData,\n FindingsGroup\n} from \"../../models/tables\";\nimport {\n FilterData,\n FilterItem,\n OptionItem,\n CommonFilterData,\n} from \"../../models/filters\";\nimport { availableFilters } from \"../constants\";\n\nexport class FilterTable {\n filterData: CommonFilterData[] = [];\n filters: FilterData;\n\n constructor(filters: FilterData) {\n this.filters = filters;\n }\n\n // Set filter options from fetched table data\n setFilterData(\n tableData: (\n | FindingsTableItem\n | ScanTableData\n | ProjectTableData\n | PackageTableData\n )[]\n ) {\n this.filterData = this.filters.filters.map((item: FilterItem) => {\n let availableFiltersCopy = { ...availableFilters };\n if (\n this.filters.table === \"Scans\" ||\n this.filters.table === \"Project Scans\"\n ) {\n availableFiltersCopy = {\n ...availableFiltersCopy,\n type: availableFiltersCopy.scan_type,\n };\n }\n if (this.filters.table === \"Project Packages\") {\n availableFiltersCopy = {\n ...availableFiltersCopy,\n [\"risk\" as keyof typeof availableFilters]:\n availableFiltersCopy.risk_score,\n };\n }\n return {\n ...item,\n options:\n item.col === \"project\" || item.col === \"branch_name\"\n ? [\n ...new Set(\n tableData.map((dataItem) => {\n if (item.col === \"project\") {\n return \"project\" in dataItem && dataItem.project\n ? dataItem.project.name\n : \"\";\n } else if (item.col === \"branch_name\") {\n return \"branch_name\" in dataItem ? dataItem.branch_name : \"\";\n }\n return \"\";\n })\n ),\n ]\n .filter((item) => item !== \"\")\n .sort((a: string, b: string) => (a < b ? -1 : 1))\n .map((item) => {\n return {\n label: item,\n value: item,\n checked: false,\n };\n })\n : item.col === \"date\"\n ? availableFiltersCopy[\n item.col as keyof typeof availableFiltersCopy\n ]\n : availableFiltersCopy[\n item.col as keyof typeof availableFiltersCopy\n ].filter((filterItem) =>\n !!tableData.find((row) => {\n if (\"risk_score\" in row && item.col === \"risk_score\") {\n return (\n row.risk_score &&\n row.risk_score.label.toLowerCase() ===\n filterItem.value.toLowerCase()\n );\n }\n if (\"risk\" in row && row.risk && item.col === \"risk\") {\n return (\n row.risk.category?.toLowerCase() ===\n filterItem.value.toLowerCase()\n );\n }\n if (\"ecosystems\" in row && item.col === \"ecosystems\") {\n return row.ecosystems.includes(filterItem.value);\n }\n if (\"findings\" in row && item.col === \"findings\") {\n return (\n (row.findings.groups[\n filterItem.value as keyof FindingsGroup\n ] || 0) > 0\n );\n }\n return (\n row[item.col as keyof typeof row] === filterItem.value\n );\n })\n ),\n };\n });\n }\n\n // When option is selected as Only\n selectOnlyOneOption(col: string, option: OptionItem) {\n return (this.filterData = this.filterData.map((filter) => {\n if (filter.col === col) {\n return {\n ...filter,\n options: filter.options.map((item) => {\n const checkboxElement: HTMLInputElement | null =\n document.getElementById(item.value) as HTMLInputElement;\n if (checkboxElement)\n checkboxElement.checked =\n item.value === option.value ? true : false;\n return {\n ...item,\n checked: item.label === option.label ? true : false,\n from:\n item.label === \"Select from calendar\" ? option.from : item.from,\n to: item.label === \"Select from calendar\" ? option.to : item.to,\n };\n }),\n };\n } else return filter;\n }));\n }\n\n // Reset all filters\n clearFilters(col: string) {\n this.filterData = this.filterData.map((item: CommonFilterData) => {\n if (item.col === col) {\n item.options.forEach((option) => {\n const targetCheckbox = document.getElementById(\n option.value\n ) as HTMLInputElement;\n if (targetCheckbox) {\n targetCheckbox.checked = false;\n }\n });\n return {\n ...item,\n options: item.options.map((option: OptionItem) => {\n return { ...option, checked: false };\n }),\n };\n }\n return item;\n });\n }\n}\n\nexport class IndividualFilter {\n open: boolean = false;\n $refs: any;\n selectedFilters: OptionItem[] = [];\n\n // Toggle dropdown\n toggle() {\n if (this.open) {\n return this.close();\n }\n this.$refs.button.focus();\n\n this.open = true;\n }\n\n // Close dropdown\n close(focusAfter?: HTMLButtonElement) {\n if (!this.open) return;\n\n this.open = false;\n\n focusAfter && focusAfter.focus();\n }\n\n handleAddFilter(option: OptionItem, method: string) {\n if (method === \"Toggle\") {\n this.selectedFilters = option.checked\n ? [...this.selectedFilters, option]\n : this.selectedFilters.filter(\n (item: OptionItem) => item.value !== option.value\n );\n } else if (method === \"Only\") {\n this.selectedFilters = [option];\n this.close();\n } else this.selectedFilters = [];\n }\n\n rangePicker() {\n const picker = flatpickr(this.$refs.button, {\n mode: \"range\",\n dateFormat: \"Y/m/d\",\n onChange: (date: Date[]) => {\n const startDate = date[1] ? new Date(date[0]) : null;\n const endDate = date[1] ? new Date(date[1]) : null;\n const formatDate = (date: Date | null) => {\n if (!date) return '';\n return date.toLocaleDateString(undefined, { day: 'numeric', month: 'short' });\n };\n const dateLabel = `${formatDate(startDate)} - ${formatDate(endDate)}`;\n if (startDate && endDate) {\n const option = {\n label: \"Select from calendar\",\n value: dateLabel,\n checked: true,\n from: startDate,\n to: endDate,\n };\n this.selectedFilters = [option];\n this.close();\n picker.destroy();\n }\n },\n onClose: (date: Date[]) => {\n if (\n date.length < 2 ||\n (new Date(date[0]) === new Date(this.selectedFilters[0].from || \"\") &&\n new Date(date[1]) === new Date(this.selectedFilters[0].to || \"\"))\n )\n picker.destroy();\n },\n });\n this.close();\n picker.open();\n }\n}\n","import { LanguageItem } from '../../models/components';\n\nexport class LanguageSelector {\n open: boolean = false;\n $refs: any;\n availableLanguages: LanguageItem[] = [{\n title: \"EN\",\n name: 'English',\n }, {\n title: \"FR\",\n name: 'French',\n }];\n selectedLanguage: LanguageItem;\n\n constructor(defaultOnly: boolean = true, currentLangCode: string) {\n if (defaultOnly === true) {\n this.availableLanguages = [this.availableLanguages[0]]\n }\n\n let lang = this.availableLanguages[0];\n const matched = this.availableLanguages.filter(obj => obj.title.toLowerCase() === currentLangCode)\n\n if (matched.length === 1) {\n lang = matched[0]\n }\n\n this.selectedLanguage = lang;\n }\n\n toggle() {\n if (this.open) {\n return this.close()\n }\n\n this.$refs.button.focus()\n\n this.open = true\n }\n\n close(focusAfter?: HTMLButtonElement) {\n if (!this.open) return\n\n this.open = false\n\n focusAfter && focusAfter.focus()\n }\n\n selectLanguage(langItem: LanguageItem) {\n this.close();\n\n const previousSelectedLang = this.selectedLanguage;\n\n if (previousSelectedLang.name == langItem.name) {\n return\n }\n\n const pathname = window.location.pathname;\n let cleanPathname = `${langItem.title.toLowerCase()}${pathname}`;\n\n const startsWithLangCode = pathname.startsWith(`/${previousSelectedLang.title.toLowerCase()}/`)\n\n if (startsWithLangCode) {\n cleanPathname = pathname.replace(`/${previousSelectedLang.title.toLowerCase()}/`, \"\");\n }\n\n this.selectedLanguage = langItem;\n window.location.href = `/${cleanPathname}`;\n }\n}\n","export class ButtonsTab {\n currentTab: string = 'Production';\n\n constructor() { }\n\n setCurrentTab(tabName: string) {\n this.currentTab = tabName;\n }\n}\n","import { RepositoryProjectBranch } from \"../../utils\";\n\nexport class PackageRepository extends RepositoryProjectBranch {\n apiUrl = '/api/v1/packages/';\n}\n","import { ScanTableData } from \"../../models/tables\";\nimport { RepositoryProjectBranch } from \"../utils\";\n\n\nexport class ScanRepository extends RepositoryProjectBranch {\n apiUrl = '/api/v1/scans/';\n\n async getByFinding(findingId: number): Promise {\n const response = await fetch(this.apiUrl + \"?finding_id=\" + findingId);\n return response.status === 200 ? await response.json().then(data => data) as ScanTableData[]:[];\n }\n}\n","import { FindingsTableItem } from \"../../models/tables\";\nimport { RepositoryProjectBranch } from \"../utils\";\n\nexport class FindingRepository extends RepositoryProjectBranch {\n apiUrl = '/api/v1/findings/';\n\n private compareVersions(v1: string | null, v2: string | null): number {\n if (v1 === null) return -1;\n if (v2 === null) return 1;\n\n try {\n const v1Parts = v1.split('.').map(part => {\n // Extract numeric portion for comparison, handling pre-release suffixes\n const match = part.match(/^\\d+/);\n return match ? parseInt(match[0], 10) : 0;\n });\n const v2Parts = v2.split('.').map(part => {\n const match = part.match(/^\\d+/);\n return match ? parseInt(match[0], 10) : 0;\n });\n\n // Compare each part of the version\n for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {\n const v1Part = v1Parts[i] || 0;\n const v2Part = v2Parts[i] || 0;\n if (v1Part > v2Part) return 1;\n if (v1Part < v2Part) return -1;\n }\n return 0;\n } catch (error) {\n console.error(`Error comparing versions ${v1} and ${v2}:`, error);\n // If there's an error in comparison, treat the existing highest version as higher\n return -1;\n }\n }\n\n async getByScan(scanId: number): Promise {\n const response = await fetch(this.apiUrl + \"?scan_id=\" + scanId);\n return response.status === 200 ? await response.json().then(data => data) as FindingsTableItem[] : [];\n }\n\n async getMetaData(): Promise {\n const response = await fetch(this.apiUrl, { method: \"OPTIONS\" });\n return response.status === 200 ? await response.json().then(data => data) as object : {};\n }\n\n async updateStatus(findingId: number, newStatus: string, csrfToken: string): Promise {\n return await fetch(\n this.apiUrl + findingId + \"/\",\n {\n method: \"PATCH\",\n body: JSON.stringify({ status: newStatus }),\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n\n async ignore(findingUUID: string, reason: string, expires: string, csrfToken: string): Promise {\n return await fetch(\n this.apiUrl + findingUUID + \"/ignore/\",\n {\n method: \"POST\",\n body: JSON.stringify({ reason: reason, expires: expires }),\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n\n private createPackageLocationKey(packageId: string, location: string): string {\n // Create a safe identifier that can be used as an object key and in the UI\n return `${packageId}:${encodeURIComponent(location)}`;\n }\n\n groupByPackage(data: FindingsTableItem[]) {\n if (!data || !Array.isArray(data)) {\n return [];\n }\n\n const groups = data.reduce((acc, finding) => {\n if (!finding?.details?.package_id) {\n console.warn('Invalid finding data:', finding);\n return acc;\n }\n const packageId = finding.details.package_id;\n const location = finding.details.location || '';\n const groupKey = this.createPackageLocationKey(packageId, location);\n\n if (!acc[groupKey]) {\n // Initialize group with the exact structure we need\n acc[groupKey] = {\n package_id: packageId,\n location: location,\n findings: [],\n highest_epss: 0,\n highest_cvss: 0,\n latest_seen: 0,\n highest_secure_version: null,\n stages: new Set(),\n group_id: groupKey,\n total_risk_score: 0\n };\n }\n\n // Add the finding to the group\n acc[groupKey].findings.push({\n ...finding,\n risk_score: finding.risk_score || { score: 0, label: 'none' },\n cvss_score: finding.cvss_score || null,\n exploitability_score: finding.exploitability_score || null,\n archived_at: finding.archived_at || null,\n branches: finding.branches || [],\n stages: finding.stages || [],\n remediation: finding.remediation || '',\n highest_secure_version: finding.highest_secure_version || ''\n });\n\n // Update group level aggregations\n acc[groupKey].highest_epss = Math.max(acc[groupKey].highest_epss, finding.exploitability_score || 0);\n acc[groupKey].highest_cvss = Math.max(acc[groupKey].highest_cvss, finding.cvss_score || 0);\n acc[groupKey].latest_seen = Math.max(acc[groupKey].latest_seen, finding.date_last_seen || 0);\n\n // Update highest secure version\n if (finding.highest_secure_version &&\n (acc[groupKey].highest_secure_version === null ||\n this.compareVersions(finding.highest_secure_version, acc[groupKey].highest_secure_version) > 0)) {\n acc[groupKey].highest_secure_version = finding.highest_secure_version;\n }\n\n // Add stages\n if (Array.isArray(finding.stages)) {\n finding.stages.forEach(stage => acc[groupKey].stages.add(stage));\n }\n\n // Update total risk score\n acc[groupKey].total_risk_score = Math.max(\n acc[groupKey].total_risk_score,\n finding.risk_score?.score || 0\n );\n\n return acc;\n }, {} as Record);\n\n // Convert to array and ensure consistent structure\n return Object.values(groups).map(group => ({\n ...group,\n stages: Array.from(group.stages),\n findings: group.findings.map((finding: any) => ({\n ...finding,\n branches: finding.branches || [],\n stages: finding.stages || [],\n risk_score: finding.risk_score || { score: 0, label: 'none' },\n project: finding.project || {},\n details: {\n ...finding.details,\n vulnerability_id: finding.details.vulnerability_id || ''\n },\n type_shorthand: finding.type_shorthand || '📦 Package Vulnerability'\n }))\n }));\n }\n}\n","import { Repository } from \"../utils\";\n\nexport class ProjectRepository extends Repository {\n apiUrl = '/api/v1/projects/';\n\n async branches(projectId: number): Promise> {\n const response = await fetch(\n this.apiUrl + projectId + \"/branches/\"\n );\n return response.status === 200 ? await response.json().then(data => data):[];\n }\n\n async confirmName(projectId: number, projectName: string, csrfToken: string): Promise {\n return await fetch(\n this.apiUrl + projectId + \"/confirm_name/\",\n {\n method: \"POST\",\n body: JSON.stringify({name: projectName}),\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n\n async delete(projectId: number, csrfToken: string): Promise {\n return await fetch(\n this.apiUrl + projectId + \"/\",\n {\n method: \"DELETE\",\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n\n async reset(projectId: number, csrfToken: string): Promise {\n return await fetch(\n this.apiUrl + projectId + \"/reset/\",\n {\n method: \"POST\",\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n}\n","import { TabItem } from \"../../models/components\";\nimport { AlpineContext, ExcludePatternsManagerState, IgnoredVulnerabilitiesFormsetState, IgnoreSeveritiesManagerState, PolicyWizardFormState } from \"./interfaces\";\n\n/**\n * Manages the state and interaction of policy tabs.\n *\n * @returns An object with tab management functionality\n * @remarks\n * Provides a reactive tab system with three predefined tabs: Production, CI/CD, and Development.\n * Allows switching between tabs by updating their active state.\n *\n * @example\n * const tabs = policiesTab();\n * tabs.switchTabs('CI/CD'); // Activates the CI/CD tab\n */\n export function policiesTab() {\n return {\n tabItems: [\n { label: \"Production\", isActive: true },\n { label: \"CI/CD\", isActive: false },\n { label: \"Development\", isActive: false },\n ],\n switchTabs(tabItem: string) {\n this.tabItems = this.tabItems.map((item: TabItem) => {\n return { ...item, isActive: item.label === tabItem };\n });\n },\n };\n }\n\n/**\n * Creates a policy wizard state management object for handling multi-step form interactions.\n *\n * @remarks\n * Manages form state, tracks changes, handles form submission, and provides step navigation\n * with change tracking and confirmation.\n *\n * @param currentStep - The initial step of the policy wizard\n * @returns An object with methods and properties for managing the policy wizard form state\n *\n * @alpha\n */\nexport function policyWizard(currentStep: string): PolicyWizardFormState {\n return {\n currentStep: currentStep,\n formChanged: false,\n saving: false,\n initialFormState: null,\n\n checkFormChanged(this: PolicyWizardFormState & AlpineContext) {\n const form = this.$refs.wizardForm as HTMLFormElement;\n const currentFormData = new FormData(form);\n const entries: [string, FormDataEntryValue][] = [];\n currentFormData.forEach((value, key) => {\n entries.push([key, value]);\n });\n const normalizedEntries: [string, string][] = [];\n const seenForms = new Set();\n\n // First pass: count non-empty forms\n (entries as [string, FormDataEntryValue][]).forEach(([name, value]) => {\n if (name.includes('vulnerability_id') && value) {\n seenForms.add(name.split('-')[1]);\n }\n });\n\n // Second pass: collect non-management form fields\n (entries as [string, FormDataEntryValue][]).forEach(([name, value]) => {\n // Skip management form fields\n if (\n name.includes('TOTAL_FORMS') ||\n name.includes('INITIAL_FORMS') ||\n name.includes('MIN_NUM_FORMS') ||\n name.includes('MAX_NUM_FORMS')\n ) {\n return;\n }\n\n // Handle DELETE fields\n if (name.includes('-DELETE')) {\n return;\n }\n\n // Only include non-empty forms\n if (name.includes('vulnerability_id')) {\n if (value) {\n seenForms.add(name.split('-')[1]);\n }\n return;\n }\n\n // Include fields only from forms with non-empty vulnerability_ids\n const formIndex = name.split('-')[1];\n if (formIndex && seenForms.has(formIndex)) {\n normalizedEntries.push([name, value as string]);\n }\n });\n\n // Sort entries for consistent comparison\n const currentState = normalizedEntries\n .sort((a, b) => a[0].localeCompare(b[0]))\n .map(entry => entry.join('='))\n .join('&');\n\n if (!this.initialFormState) {\n return false;\n }\n\n return currentState !== this.initialFormState;\n },\n\n saveInitialState(this: PolicyWizardFormState & AlpineContext) {\n const form = this.$refs.wizardForm as HTMLFormElement;\n const formData = new FormData(form);\n const entries: [string, FormDataEntryValue][] = [];\n formData.forEach((value, key) => {\n entries.push([key, value]);\n });\n const normalizedEntries = entries\n .filter(([name]) =>\n !name.includes('TOTAL_FORMS') &&\n !name.includes('INITIAL_FORMS') &&\n !name.includes('MIN_NUM_FORMS') &&\n !name.includes('MAX_NUM_FORMS')\n )\n .sort((a, b) => a[0].localeCompare(b[0]))\n .map(entry => entry.join('='))\n .join('&');\n\n this.initialFormState = normalizedEntries;\n },\n\n async handleSubmit(this: PolicyWizardFormState & AlpineContext, event: SubmitEvent) {\n const submitButton = (event.submitter as HTMLButtonElement) || null;\n\n if (submitButton && submitButton.name === 'save') {\n event.preventDefault();\n this.saving = true;\n\n const form = event.target as HTMLFormElement;\n const formData = new FormData(form);\n formData.append('save', 'true');\n\n try {\n const response = await fetch(form.action, {\n method: 'POST',\n body: formData,\n headers: {\n 'X-Requested-With': 'XMLHttpRequest'\n }\n });\n\n const data = await response.json();\n\n if (response.ok) {\n this.$dispatch('notify', {\n content: data.message || 'Changes saved successfully',\n type: 'success'\n });\n this.saveInitialState();\n this.formChanged = false;\n } else {\n throw new Error(data.message || 'Save failed');\n }\n } catch (error: any) {\n this.$dispatch('notify', {\n content: error.message || 'Failed to save changes',\n type: 'error'\n });\n } finally {\n this.saving = false;\n }\n }\n },\n\n handleStepChange(this: PolicyWizardFormState & AlpineContext, step: string) {\n if (!this.formChanged || confirm('You have unsaved changes that will be lost. Continue?')) {\n (this.$refs.gotoInput as HTMLInputElement).value = step;\n this.formChanged = false;\n (this.$refs.wizardForm as HTMLFormElement).submit();\n }\n },\n\n init(this: PolicyWizardFormState & AlpineContext) {\n this.saveInitialState();\n\n this.$watch('formChanged', (value: boolean) => {\n window.onbeforeunload = value ? () => '' : null;\n });\n\n (this.$refs.wizardForm as HTMLFormElement).addEventListener('input', () => {\n this.formChanged = this.checkFormChanged();\n });\n\n this.$el.addEventListener('form-changed', () => {\n this.formChanged = this.checkFormChanged();\n });\n\n this.$el.addEventListener('formset-changed', () => {\n this.formChanged = this.checkFormChanged();\n });\n }\n };\n}\n\n/**\n * Creates a manager for handling exclude patterns in a policy configuration.\n *\n * @param excludePatternsFieldId - The ID of the hidden input field storing exclude patterns\n * @param defaultMaxDepth - The default maximum depth for pattern exclusions, defaults to 4\n * @returns An Alpine.js compatible state object for managing exclude patterns\n *\n * @remarks\n * This function provides a comprehensive interface for managing a set of patterns to exclude from processing.\n * It supports adding, removing, and tracking patterns, with built-in validation and hidden input synchronization.\n *\n * @example\n * ```typescript\n * const manager = excludePatternsManager('exclude-patterns-field');\n * manager.addPattern('*.log');\n * manager.addCommonPattern('node_modules');\n * ```\n */\nexport function excludePatternsManager(\n excludePatternsFieldId: string,\n defaultMaxDepth = 4\n): ExcludePatternsManagerState {\n\n return {\n selectedPatterns: new Set(),\n newPattern: '',\n depthValue: defaultMaxDepth,\n commonPatterns: [\n { name: '.git', description: 'Git version control files and folders' },\n { name: '*.html', description: 'All HTML files' },\n { name: '*.js', description: 'All JavaScript files' },\n { name: '__pycache__', description: 'Python compiler cache files' },\n { name: 'node_modules', description: 'Node.js package dependencies' },\n { name: '.env', description: 'Environment configuration files (may contain secrets)' }\n ],\n\n init(this: ExcludePatternsManagerState & AlpineContext) {\n const excludeField = document.getElementById(excludePatternsFieldId) as HTMLInputElement;\n if (excludeField && excludeField.value) {\n try {\n const patterns = JSON.parse(excludeField.value);\n if (Array.isArray(patterns)) {\n patterns.forEach((p: string) => this.selectedPatterns.add(p));\n }\n } catch (e) {\n console.error('Error parsing exclude_patterns:', e);\n }\n }\n this.updateHiddenInput();\n },\n\n addPattern(this: ExcludePatternsManagerState & AlpineContext) {\n const pattern = this.newPattern.trim();\n if (pattern && !this.selectedPatterns.has(pattern)) {\n this.selectedPatterns.add(pattern);\n this.updateHiddenInput();\n this.newPattern = '';\n this.$dispatch('form-changed', true);\n }\n },\n\n removePattern(this: ExcludePatternsManagerState & AlpineContext, pattern: string) {\n this.selectedPatterns.delete(pattern);\n this.updateHiddenInput();\n this.$dispatch('form-changed', true);\n },\n\n addCommonPattern(this: ExcludePatternsManagerState & AlpineContext, pattern: string) {\n if (!this.selectedPatterns.has(pattern)) {\n this.selectedPatterns.add(pattern);\n this.updateHiddenInput();\n this.$dispatch('form-changed', true);\n }\n },\n\n isPatternSelected(this: ExcludePatternsManagerState & AlpineContext, pattern: string) {\n return this.selectedPatterns.has(pattern);\n },\n\n getSelectedPatterns(this: ExcludePatternsManagerState & AlpineContext) {\n return Array.from(this.selectedPatterns);\n },\n\n updateHiddenInput(this: ExcludePatternsManagerState & AlpineContext) {\n const excludeField = document.getElementById(excludePatternsFieldId) as HTMLInputElement;\n if (excludeField) {\n excludeField.value = JSON.stringify(this.getSelectedPatterns());\n }\n },\n\n validateDepth(this: ExcludePatternsManagerState & AlpineContext, value: string) {\n if (value === '') return value; // Allow empty so user can easily adjust\n const numValue = parseInt(value, 10) || 1;\n return Math.min(Math.max(numValue, 1), 10);\n }\n };\n}\n\n/**\n * Creates a manager for handling severity level checkbox selections.\n *\n * @remarks\n * This function provides state management for a group of severity checkboxes,\n * allowing for select all, partial selection, and individual checkbox interactions.\n *\n * @returns An object with methods and properties for managing severity checkbox selections\n *\n * @property selectAll - Indicates whether all checkboxes should be selected\n * @property isIndeterminate - Represents a partial selection state\n * @property checkboxes - Collection of checkbox input elements\n * @property allSelected - Indicates if all checkboxes are currently selected\n *\n * @method init - Initializes the severity checkbox manager by setting up references and event listeners\n * @method toggleSelectAll - Toggles the selection state of all checkboxes\n * @method updateSelectAllState - Updates the select all and indeterminate states based on current checkbox selections\n * @method checkAllSelected - Checks if all checkboxes are currently selected\n */\nexport function ignoreSeveritiesManager(): IgnoreSeveritiesManagerState {\n return {\n selectAll: false,\n isIndeterminate: false,\n checkboxes: [],\n allSelected: false,\n\n init(this: IgnoreSeveritiesManagerState & AlpineContext) {\n // Wait until the DOM elements are fully rendered\n this.$nextTick(() => {\n const severityOptions = this.$refs.severityOptions as HTMLElement;\n if (!severityOptions) return;\n\n this.checkboxes = Array.from(severityOptions.querySelectorAll('input[type=checkbox]')) as HTMLInputElement[];\n\n // Set initial state based on pre-checked boxes\n this.updateSelectAllState();\n\n // Add event listeners to individual checkboxes\n this.checkboxes.forEach(checkbox => {\n checkbox.addEventListener('change', () => {\n this.updateSelectAllState();\n this.checkAllSelected();\n });\n });\n\n // Initial check for all selected\n this.checkAllSelected();\n });\n },\n\n toggleSelectAll(this: IgnoreSeveritiesManagerState & AlpineContext) {\n this.checkboxes.forEach(checkbox => {\n checkbox.checked = this.selectAll;\n });\n this.isIndeterminate = false;\n this.checkAllSelected();\n },\n\n updateSelectAllState(this: IgnoreSeveritiesManagerState & AlpineContext) {\n const total = this.checkboxes.length;\n const checked = this.checkboxes.filter(cb => cb.checked).length;\n\n if (checked === total) {\n this.selectAll = true;\n this.isIndeterminate = false;\n } else if (checked === 0) {\n this.selectAll = false;\n this.isIndeterminate = false;\n } else {\n this.selectAll = false;\n this.isIndeterminate = true;\n }\n },\n\n checkAllSelected(this: IgnoreSeveritiesManagerState & AlpineContext) {\n this.allSelected = this.checkboxes.every(cb => cb.checked);\n }\n };\n}\n\n\n/**\n * Manages a formset for ignored vulnerabilities with dynamic form manipulation.\n *\n * @remarks\n * This function provides state management and methods for adding, deleting, and tracking forms\n * related to ignored vulnerabilities in a Django-style formset.\n *\n * @returns An object with methods and properties for managing the ignored vulnerabilities formset\n *\n * @property totalForms - Total number of forms in the formset\n * @property initialForms - Initial number of forms when the page loads\n *\n * @method init - Initializes the formset by reading total and initial form counts from hidden inputs\n * @method addForm - Dynamically adds a new form to the formset with updated indices\n * @method deleteForm - Marks a specific form for deletion and hides it from the UI\n */\nexport function ignoredVulnerabilitiesFormsetManager(): IgnoredVulnerabilitiesFormsetState {\n return {\n totalForms: 0,\n initialForms: 0,\n\n init(this: IgnoredVulnerabilitiesFormsetState & AlpineContext) {\n this.$nextTick(() => {\n const totalFormsInput = document.querySelector(`[name=\"ignored_vulnerabilities-TOTAL_FORMS\"]`);\n const initialFormsInput = document.querySelector(`[name=\"ignored_vulnerabilities-INITIAL_FORMS\"]`);\n\n if (totalFormsInput) {\n this.totalForms = parseInt(totalFormsInput.value, 10);\n }\n if (initialFormsInput) {\n this.initialForms = parseInt(initialFormsInput.value, 10);\n }\n\n this.$watch('totalForms', value => {\n const totalFormsInput = document.querySelector(`[name=\"ignored_vulnerabilities-TOTAL_FORMS\"]`) as HTMLInputElement;\n if (totalFormsInput) {\n totalFormsInput.value = String(value);\n }\n });\n });\n },\n\n addForm(this: IgnoredVulnerabilitiesFormsetState & AlpineContext) {\n const template = document.querySelector('#empty-form-template');\n if (!template) return;\n\n const newForm = template.content.cloneNode(true) as DocumentFragment;\n const newIndex = this.totalForms;\n\n // Update IDs and names in the new form\n newForm.querySelectorAll('[name]').forEach(el => {\n if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {\n el.name = el.name.replace(`__prefix__`, String(newIndex));\n if (el.id) {\n el.id = el.id.replace(`__prefix__`, String(newIndex));\n }\n }\n });\n\n // Update the root div ID\n const rootDiv = newForm.querySelector('div');\n if (rootDiv) {\n rootDiv.id = `form-${newIndex}`;\n }\n\n // Set up the remove button\n const removeButton = newForm.querySelector('[data-delete-form]');\n if (removeButton) {\n removeButton.setAttribute('x-on:click', `deleteForm(${newIndex})`);\n }\n\n document.querySelector('#formset-container')?.appendChild(newForm);\n this.totalForms++;\n this.$dispatch('form-changed');\n },\n\n deleteForm(this: IgnoredVulnerabilitiesFormsetState & AlpineContext, index: number) {\n const deleteInput = document.querySelector(`[name=\"ignored_vulnerabilities-${index}-DELETE\"]`);\n if (deleteInput) {\n deleteInput.value = 'on';\n }\n\n const formElement = document.querySelector(`#form-${index}`);\n if (formElement) {\n (formElement as HTMLElement).style.display = 'none';\n }\n\n this.$dispatch('form-changed');\n }\n };\n}\n","export class Notifications {\n notifications: any[] = [];\n\n constructor() { }\n\n add(e: any) {\n this.notifications.push({\n id: e.timeStamp,\n type: e.detail.type,\n content: e.detail.content,\n action: e.detail.action,\n actionText: e.detail.actionText,\n displayDuration: e.detail.displayDuration,\n secondaryAction: e.detail.secondaryAction,\n secondaryActionText: e.detail.secondaryActionText,\n });\n }\n\n remove(notification: any) {\n this.notifications = this.notifications.filter(i => i.id !== notification.id);\n }\n}\n","export class Modal {\n isModalOpen: boolean = false;\n\n constructor() { }\n\n openModal() {\n this.isModalOpen = true;\n }\n\n closeModal() {\n this.isModalOpen = false;\n }\n}\n","/**\n * @fileoverview Main TypeScript file for managing the onboarding process.\n * This file defines the onboarding state and methods used to handle step transitions,\n * UI state updates, and redirection during onboarding.\n */\n\n/* ================================\n Interfaces & Types\n================================ */\n\n/**\n * Represents a project (or codebase) with a unique ID and name.\n */\ninterface Project {\n id: number;\n name: string;\n uuid?: string;\n}\n\n/**\n * Describes the onboarding state and its associated methods.\n */\ninterface OnboardingData {\n step: string;\n completed: boolean;\n activeModal: string | null;\n loading: boolean;\n copied: string;\n hasExistingProjects: boolean;\n projects: Project[];\n installComplete: boolean;\n email: string;\n redirectCountdown: number;\n redirectStarted: boolean;\n scanComplete: boolean;\n cliLastAuth: string;\n github_api_key: string;\n\n // Utility methods\n formatDate(dateString: string): string;\n getStep(): number;\n\n // UI state update methods\n setStep(step: string | number): Promise;\n setActiveModal(modal: string): void;\n closeModal(): void;\n copyCommand(command: string): void;\n nextStep(): Promise;\n restart(): Promise;\n skipOnboarding(): Promise;\n\n // Step-specific methods\n initStep3(): Promise;\n markInstallComplete(): void;\n\n // Finalization / Redirection methods\n finalizeOnboarding(): Promise;\n startRedirectCountdown(): void;\n\n // Initialization\n init(): void;\n}\n\n/* ================================\n Constants\n================================ */\n\n/**\n * Mapping between step names and step numbers.\n */\nconst stepMap: { [key: string]: number } = {\n 'learn': 1,\n 'install': 2,\n 'secure': 3,\n};\n\n/* ================================\n Onboarding State Factory\n================================ */\n\n/**\n * Creates and returns the onboarding data, initializing state\n * from the server-provided data present in the DOM.\n *\n * @returns {OnboardingData} The onboarding state and its methods.\n */\nexport default (): OnboardingData => {\n // Get initial data from the Django template (this JSON comes from the /get-started response)\n const onboardingData = JSON.parse(\n document.getElementById('onboarding-data')?.textContent || '{}'\n );\n\n return {\n /* ---------------------------\n State Properties\n ---------------------------- */\n step: onboardingData.current_step || 'learn',\n completed: onboardingData.completed || false,\n github_api_key: onboardingData.github_api_key || '',\n activeModal: null as string | null,\n loading: true,\n copied: '',\n hasExistingProjects: onboardingData.has_projects || false,\n projects: onboardingData.projects || [],\n installComplete: false,\n email: onboardingData.email || '',\n redirectCountdown: 0,\n redirectStarted: false,\n scanComplete: false,\n cliLastAuth: onboardingData.cliLastAuth || '',\n\n /* ---------------------------\n Utility Methods\n ---------------------------- */\n /**\n * Formats a given date string into a human-friendly relative date.\n *\n * @param {string} dateString - The date string to format.\n * @returns {string} A human-friendly date representation.\n */\n formatDate(dateString: string): string {\n if (!dateString) {\n return '';\n }\n const date = new Date(dateString);\n const now = new Date();\n\n // Get the start (midnight) of today.\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n // Get the start (midnight) of the authentication date.\n const authDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());\n\n // Calculate the difference in whole days.\n const diffInTime = today.getTime() - authDate.getTime();\n const diffInDays = Math.floor(diffInTime / (1000 * 60 * 60 * 24));\n\n if (diffInDays === 0) {\n return \"Today at \" + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n } else if (diffInDays === 1) {\n return \"Yesterday at \" + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n } else {\n return `${diffInDays} days ago`;\n }\n },\n\n /**\n * Retrieves the current numeric step based on the stepMap.\n *\n * @returns {number} The current step number.\n */\n getStep(): number {\n return stepMap[this.step] || 1;\n },\n\n /* ---------------------------\n UI State Update Methods\n ---------------------------- */\n /**\n * Sets the current onboarding step and notifies the backend.\n *\n * @param {string | number} step - The new step (either a step name or a number).\n */\n async setStep(step: string | number): Promise {\n // Store the previous step before making any changes\n const previousStep = this.step;\n\n try {\n // Optimistically update UI immediately.\n let newStep: string;\n if (typeof step === 'number') {\n const reverseMap = Object.entries(stepMap).find(([_, val]) => val === step);\n newStep = reverseMap ? reverseMap[0] : String(step);\n } else {\n newStep = String(step);\n }\n this.step = newStep;\n\n // If moving to the secure step, load additional data in the background.\n if (newStep === 'secure') {\n await this.initStep3();\n }\n\n // Turn off the loading state immediately.\n this.loading = false;\n\n // Post the update to the backend asynchronously.\n const csrfToken = document.cookie\n .split('; ')\n .find(row => row.startsWith('csrftoken='))\n ?.split('=')[1];\n\n const response = await fetch('/get-started/', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-CSRFToken': csrfToken || '',\n },\n body: JSON.stringify({ step: newStep })\n });\n\n if (!response.ok) {\n throw new Error('Failed to update step');\n }\n } catch (error) {\n // Check if the error is from a cancelled transition\n if (error && typeof error === 'object' && 'isFromCancelledTransition' in error) {\n // Silently ignore cancelled transition errors\n return;\n }\n console.error('Error updating step:', error);\n // Revert the optimistic UI update\n this.step = previousStep;\n }\n },\n\n /**\n * Sets the active modal in the UI.\n *\n * @param {string} modal - The modal identifier to set as active.\n */\n setActiveModal(modal: string): void {\n this.activeModal = modal;\n },\n\n /**\n * Closes any active modal.\n */\n closeModal(): void {\n this.activeModal = null;\n },\n\n /**\n * Copies a given command to the clipboard.\n * Sets the 'copied' state based on the content type.\n *\n * @param {string} command - The command to copy.\n */\n async copyCommand(command: string): Promise {\n await navigator.clipboard.writeText(command);\n // Determine which command was copied.\n this.copied = command.includes('safety scan') ? 'scan' : 'install';\n // Reset copied state after 2 seconds.\n setTimeout(() => {\n this.copied = '';\n }, 2000);\n },\n\n /**\n * Advances the onboarding to the next step.\n */\n async nextStep(): Promise {\n const currentStep = this.getStep();\n const nextStepMap: { [key: number]: string } = {\n 1: 'install',\n 2: 'secure'\n };\n\n if (currentStep === 3) {\n console.log(\"Secure step reached. Please use finalizeOnboarding() button.\");\n return;\n }\n\n await this.setStep(nextStepMap[currentStep] || 'learn');\n },\n\n /**\n * Resets the onboarding process to its initial state.\n */\n async restart(): Promise {\n try {\n const csrfToken = document.cookie\n .split('; ')\n .find(row => row.startsWith('csrftoken='))\n ?.split('=')[1];\n\n const response = await fetch('/get-started/', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-CSRFToken': csrfToken || '',\n },\n body: JSON.stringify({ action: 'reset' })\n });\n\n if (!response.ok) {\n console.error('Failed to reset onboarding');\n }\n\n // Reset local UI state.\n this.step = 'learn';\n this.completed = false;\n this.activeModal = null;\n this.installComplete = false;\n this.redirectCountdown = 0;\n this.redirectStarted = false;\n this.scanComplete = false;\n\n } catch (error) {\n console.error('Error during restart:', error);\n this.step = 'learn';\n this.completed = false;\n this.activeModal = null;\n this.installComplete = false;\n this.redirectCountdown = 0;\n this.redirectStarted = false;\n this.scanComplete = false;\n }\n },\n\n async skipOnboarding(): Promise {\n // Retrieve CSRF token from cookies\n const csrfToken = document.cookie\n .split('; ')\n .find(row => row.startsWith('csrftoken='))\n ?.split('=')[1];\n try {\n const response = await fetch('/get-started/', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-CSRFToken': csrfToken || '',\n },\n body: JSON.stringify({ action: 'skip' })\n });\n if (!response.ok) {\n console.error('Failed to skip onboarding');\n } else {\n console.log(\"Onboarding skipped successfully.\");\n // Mark onboarding as complete locally and redirect (if desired)\n this.completed = true;\n window.location.href = '/';\n }\n } catch (error) {\n console.error('Error while skipping onboarding:', error);\n }\n },\n\n /* ---------------------------\n Step-Specific Methods\n ---------------------------- */\n /**\n * Initializes additional data for the secure (step 3) onboarding step.\n */\n async initStep3(): Promise {\n if (this.getStep() === 3) {\n // Use already loaded data from the onboarding context.\n this.hasExistingProjects = this.projects.length > 0;\n }\n },\n\n /**\n * Marks the installation step as complete.\n */\n markInstallComplete(): void {\n this.installComplete = true;\n },\n\n /* ---------------------------\n Finalization & Redirection\n ---------------------------- */\n /**\n * Finalizes the onboarding process by marking it as complete with the backend.\n */\n async finalizeOnboarding(): Promise {\n // First mark onboarding as complete before any redirects\n try {\n const csrfToken = document.cookie\n .split('; ')\n .find(row => row.startsWith('csrftoken='))\n ?.split('=')[1];\n\n const response = await fetch('/get-started/', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-CSRFToken': csrfToken || '',\n },\n body: JSON.stringify({ step: 'secure', completed: true })\n });\n\n if (!response.ok) {\n throw new Error('Failed to mark onboarding as completed');\n }\n\n this.completed = true;\n console.log(\"Onboarding marked as complete.\");\n\n // Get the latest projects data before deciding redirect\n const projectsResponse = await fetch('/api/v1/projects/');\n if (!projectsResponse.ok) {\n throw new Error('Failed to fetch projects data');\n }\n const projects = await projectsResponse.json();\n\n // Determine redirect URL based on latest projects data\n if (projects.length === 1) {\n // If there's exactly one project, redirect to its findings page\n window.location.href = `/projects/${projects[0].id}/findings`;\n } else if (projects.length > 1) {\n // If there are multiple projects, redirect to dashboard\n window.location.href = '/';\n } else {\n // If there are no projects, stay on current page\n console.log('No projects found, staying on current page');\n }\n\n } catch (error) {\n console.error('Error during onboarding finalization:', error);\n // On error, stay on current page instead of redirecting\n this.completed = false;\n }\n },\n\n /**\n * Starts the redirect countdown timer.\n * Once the countdown reaches zero, proceeds to the next step or finalizes onboarding.\n */\n startRedirectCountdown(): void {\n this.redirectStarted = true;\n this.redirectCountdown = 10;\n const timer = setInterval(() => {\n this.redirectCountdown -= 1;\n if (this.redirectCountdown <= 0) {\n clearInterval(timer);\n this.redirectStarted = false;\n if (this.getStep() < 3) {\n // If not yet on secure (step 3), move to the next step.\n this.nextStep().catch(err => console.error(err));\n } else {\n // If on secure step, finalize onboarding.\n this.finalizeOnboarding();\n }\n }\n }, 1000);\n },\n\n /* ---------------------------\n Initialization\n ---------------------------- */\n /**\n * Initializes event listeners for onboarding events.\n * Listens for events such as installation completion and scan creation.\n */\n init(): void {\n window.addEventListener('onboarding:install-complete', () => {\n this.markInstallComplete();\n // Wait until the user's window is focused before starting the countdown.\n if (document.hasFocus()) {\n this.startRedirectCountdown();\n } else {\n window.addEventListener('focus', () => {\n this.startRedirectCountdown();\n }, { once: true });\n }\n });\n window.addEventListener('onboarding:scan-created', () => {\n // Only update on secure step if scan isn't already complete.\n if (this.getStep() === 3 && !this.scanComplete) {\n this.scanComplete = true;\n // Start the redirect countdown only if there are no existing projects\n if (!this.redirectStarted && !this.hasExistingProjects) {\n this.startRedirectCountdown();\n }\n }\n });\n }\n }\n}\n","import { AppSyncMessage, CloudEvent, NotificationPayload } from './ws-types';\n\n// Track processed event IDs to prevent duplicates\nconst processedEventIds = new Set();\n// Limit the size of the cache to prevent memory leaks\nconst MAX_CACHE_SIZE = 1000;\n\n/**\n * Processes WebSocket messages and handles different CloudEvent types.\n * Assumes the \"event\" field on the message contains a CloudEvent.\n * @param message The raw message received from AppSync\n */\nexport function handleWebSocketMessage(message: AppSyncMessage): void {\n // Proceed only if this is a \"data\" type message and an event exists\n if (message.type !== 'data' || !message.event) {\n return;\n }\n\n try {\n // Parse the incoming event as a CloudEvent\n const event: CloudEvent = JSON.parse(message.event);\n\n // Check for event ID and skip if we've already processed this event\n if (event.id && processedEventIds.has(event.id)) {\n console.log(`Skipping duplicate event with ID: ${event.id}`);\n return;\n }\n\n // Store the event ID in our set to prevent reprocessing\n if (event.id) {\n // If we're nearing the max cache size, remove oldest elements (10% of cache)\n if (processedEventIds.size >= MAX_CACHE_SIZE) {\n const idsToRemove = Array.from(processedEventIds).slice(0, MAX_CACHE_SIZE / 10);\n idsToRemove.forEach(id => processedEventIds.delete(id));\n }\n processedEventIds.add(event.id);\n }\n\n // Handle events by type\n switch (event.type) {\n // All firewall-related events trigger a complete UI refresh\n // This ensures all data stays up-to-date for the user\n case 'com.safetycli.telemetry.refresh':\n case 'com.safetycli.firewall.configured':\n case 'com.safetycli.firewall.disabled':\n case 'com.safetycli.firewall.heartbeat':\n console.log(`[Firewall] ${event.type.split('.').pop()} event received`);\n dispatchFirewallEvent('firewall:refresh-events', {\n timestamp: new Date(event.time).toLocaleString(),\n eventType: event.type,\n eventId: event.id\n });\n break;\n\n // Data events (for test compatibility)\n case 'data':\n console.log('[Data Event]');\n break;\n\n // Auth events\n case 'auth':\n case 'com.safetycli.auth':\n handleAuthEvent(event.data as NotificationPayload);\n break;\n\n // Scan creation events also trigger a refresh to update relevant UI elements\n case 'com.safetycli.scan_created':\n handleNotification(event.data as NotificationPayload);\n dispatchFirewallEvent('firewall:refresh-events', {\n timestamp: new Date(event.time).toLocaleString(),\n eventType: event.type,\n eventId: event.id\n });\n break;\n\n // General notifications\n case 'notify':\n handleNotification(event.data as NotificationPayload);\n break;\n\n // Unknown event types\n default:\n console.log(`Unhandled event type: ${event.type}`);\n break;\n }\n } catch (error) {\n console.error('Error processing WebSocket message:', error);\n }\n}\n\n/**\n * Helper function to clear the processed events cache\n * Useful for testing or manual cache management\n * @param silent When true, doesn't log a message (useful for tests)\n */\nexport function clearProcessedEvents(silent: boolean = false): void {\n processedEventIds.clear();\n if (!silent) {\n console.log('Processed events cache cleared');\n }\n}\n\n/**\n * Dispatches a custom event for firewall components to handle.\n * Used to communicate from WebSocket handlers to Alpine.js UI components.\n * @param eventName Name of the event to dispatch (e.g., 'firewall:refresh-events')\n * @param detail Event details object containing relevant event information\n */\nfunction dispatchFirewallEvent(eventName: string, detail: any): void {\n window.dispatchEvent(new CustomEvent(eventName, { detail }));\n}\n\n/**\n * Handles notification events from the WebSocket.\n * Creates a standardized notification that can be displayed in the UI.\n * Also handles special event types like scan creation.\n * @param payload The notification data from the WebSocket event\n */\nfunction handleNotification(payload: NotificationPayload): void {\n console.log('[Notification]', {\n type: payload.type,\n message: payload.message,\n duration: payload.display_duration\n });\n const event = new CustomEvent('notify', {\n bubbles: true,\n detail: {\n type: payload.type,\n content: payload.message,\n displayDuration: payload.display_duration,\n action: payload.action,\n actionText: payload.action_text,\n secondaryAction: payload.secondary_action,\n secondaryActionText: payload.secondary_action_text\n }\n });\n window.dispatchEvent(event);\n\n if (payload.action === \"scan_created\") {\n console.log('[Onboarding] Scan created event received.');\n window.dispatchEvent(new CustomEvent('onboarding:scan-created'));\n }\n}\n\n/**\n * Handles authentication events from the WebSocket.\n * Processes CLI authentication and triggers onboarding completion when appropriate.\n * @param payload The authentication data from the WebSocket event\n */\nfunction handleAuthEvent(payload: NotificationPayload): void {\n if (payload.data) {\n console.log('[Auth Event]', {\n method: payload.data.method,\n email: payload.data.email,\n organization_name: payload.data.organization_name,\n organization_id: payload.data.organization_id\n });\n\n const userEmail = document.getElementById('content-wrapper')?.getAttribute('data-user-email');\n if (payload.data.method === \"cli\" && payload.data.email === userEmail) {\n console.log('[Onboarding] Safety CLI authenticated for current user.');\n window.dispatchEvent(new CustomEvent('onboarding:install-complete'));\n }\n }\n}\n","/**\n * This module provides a WebSocket client implementation for connecting to AppSync Events API.\n * It handles connection establishment, channel subscription, and message processing.\n */\n\nimport { AppSyncMessage } from \"./ws-types\";\nimport { handleWebSocketMessage } from \"./ws-handlers\";\nimport * as Sentry from \"@sentry/browser\";\n\n// Types\ntype WebSocketDetails = {\n ws: string;\n http: string;\n token: string;\n};\n\ntype AuthorizationHeaders = {\n host: string;\n Authorization: string;\n};\n\n// Connection state\nlet websocket: WebSocket | null = null;\nlet isConnectionAcked = false;\n\n// Add reconnection control\nlet reconnectAttempts = 0;\nconst MAX_RECONNECT_ATTEMPTS = 3;\nlet isReconnecting = false;\n\n/**\n * Encodes an object into a base64 URL-safe string.\n * Used for preparing WebSocket subprotocol headers.\n *\n * @param obj - Object containing key-value pairs to encode\n * @returns Base64 URL-safe encoded string\n */\nfunction base64UrlEncode(obj: Record): string {\n return btoa(JSON.stringify(obj))\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/**\n * Retrieves WebSocket connection details from the backend.\n *\n * @throws {Error} If the server request fails or authentication is invalid.\n * @returns Promise containing WebSocket URL, HTTP endpoint, and authentication token.\n */\nasync function getWebSocketDetails(): Promise {\n try {\n const response = await fetch('/websockets');\n\n if (response.status === 401) {\n console.log(\"[WebSocket] Session expired. Redirecting to login.\");\n window.location.href = \"/login\";\n }\n\n if (response.status === 403) {\n console.log(\"[WebSocket] User not logged in.\");\n return;\n }\n\n if (!response.ok) {\n console.error(\"[WebSocket] Failed to get details:\", {\n status: response.status,\n statusText: response.statusText\n });\n throw new Error(`Failed to get WebSocket details: ${response.status}`);\n }\n\n return await response.json();\n } catch (error) {\n console.error(\"[WebSocket] Error getting details:\", error);\n throw error;\n }\n}\n\n/**\n * Parses a JWT token and extracts its payload.\n *\n * @param token - JWT token string\n * @returns Decoded JWT payload as an object\n */\nfunction parseJwt(token: string): Record {\n const [, payloadBase64] = token.split('.');\n const payloadJson = atob(payloadBase64.replace(/_/g, '/').replace(/-/g, '+'));\n return JSON.parse(payloadJson);\n}\n\n/**\n * Subscribes to a specified channel after WebSocket connection is established.\n *\n * @param channelName - Name of the channel to subscribe to\n * @param authorization - Authorization headers for the subscription\n * @throws {Error} If WebSocket is not connected or not acknowledged\n */\nfunction subscribeToChannel(channelName: string, authorization: AuthorizationHeaders): void {\n if (!websocket || !isConnectionAcked) {\n console.warn(\"WebSocket not open or not acknowledged yet.\");\n return;\n }\n\n const subscriptionId = \"sub-\" + Math.random().toString(36).slice(2, 7);\n const subscribeMessage = {\n type: \"subscribe\",\n id: subscriptionId,\n channel: channelName,\n authorization,\n };\n\n console.log(`[WebSocket] Subscribing to channel: ${channelName}, id=${subscriptionId}`);\n websocket.send(JSON.stringify(subscribeMessage));\n}\n\n/**\n * Establishes a WebSocket connection to AppSync Events API and sets up message handlers.\n * Automatically subscribes to a user-specific channel upon successful connection.\n *\n * @throws {Error} If WebSocket details are invalid or connection fails\n */\nexport async function connectToChannel(): Promise {\n // Disable WebSocket connection for disabled connections\n const shouldDisableConnection = document.querySelector('[data-disable-connection=\"true\"]') !== null;\n\n if (shouldDisableConnection) {\n console.log(\"[WebSocket] Connection disabled:\", \"Disabled connection\");\n return;\n }\n\n const connection = await getWebSocketDetails();\n if (!connection) {\n return;\n }\n\n const { ws, http, token } = connection;\n\n if (!ws || !http || !token) {\n throw new Error('Invalid WebSocket details');\n }\n\n // Configure authorization headers\n const authorizationHeaders: AuthorizationHeaders = {\n host: http,\n Authorization: `Bearer ${token}`,\n };\n\n // Debug header\n const headerString = `header-${base64UrlEncode(authorizationHeaders)}`;\n\n // Initialize WebSocket connection\n websocket = new WebSocket(ws, [headerString, \"aws-appsync-event-ws\"]);\n\n // Set up event handlers\n websocket.onopen = () => {\n console.log(\"[WebSocket] onopen -> sending connection_init\");\n websocket?.send(JSON.stringify({ type: \"connection_init\" }));\n };\n\n // Configure message handler\n websocket.onmessage = (event) => {\n const data: AppSyncMessage = JSON.parse(event.data);\n\n switch (data.type) {\n case \"connection_ack\":\n console.log(\"[WebSocket] Received connection_ack\");\n isConnectionAcked = true;\n reconnectAttempts = 0;\n\n const claims = parseJwt(token);\n const userSub = claims.sub.replace('|', '-');\n const dynamicChannelPath = `/sub/${userSub}`;\n subscribeToChannel(dynamicChannelPath, authorizationHeaders);\n break;\n\n case \"ka\":\n // Keep alive - no action needed\n break;\n\n case \"subscribe_success\":\n console.log(`[WebSocket] Subscribe success, id=${data.id}`);\n break;\n\n case \"data\":\n handleWebSocketMessage(data);\n break;\n\n case \"connection_error\":\n case \"subscribe_error\":\n console.error(`[WebSocket] ${data.type}:`, data.errors);\n if (data.errors?.[0]?.errorType === \"UnauthorizedException\") {\n handleTokenRefresh();\n } else {\n Sentry.captureMessage(`WebSocket ${data.type}`, {\n level: \"error\",\n extra: { errors: data.errors }\n });\n }\n\n break;\n\n default:\n console.log(\"[WebSocket] Unknown message type:\", data);\n break;\n }\n };\n\n websocket.onerror = (event) => {\n console.error(\"[WebSocket] Error:\", event);\n Sentry.captureException(new Error(\"WebSocket connection error\"), {\n extra: {\n readyState: websocket?.readyState,\n url: websocket?.url\n }\n });\n };\n\n websocket.onclose = (evt) => {\n websocket = null;\n isConnectionAcked = false;\n\n // Attempt reconnection if closed unexpectedly (e.g., if no reason is provided)\n if (!isReconnecting && (!evt.reason || evt.reason === \"No reason\")) {\n console.log(\"[WebSocket] Connection closed unexpectedly, attempting to reconnect...\");\n handleTokenRefresh();\n } else {\n console.log(\"[WebSocket] Closed:\", evt.reason || \"No reason\");\n }\n };\n}\n\n/**\n * Gracefully terminates the WebSocket connection.\n */\nexport function closeChannel(): void {\n if (websocket) {\n console.log(\"[WebSocket] Closing...\");\n websocket.close();\n websocket = null;\n isConnectionAcked = false;\n }\n}\n\n// Modify the token refresh handler\nexport function handleTokenRefresh(): void {\n if (isReconnecting) {\n console.log(\"[WebSocket] Already attempting to reconnect\");\n return;\n }\n\n if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n console.error(\"[WebSocket] Max reconnection attempts reached\");\n Sentry.captureMessage(\"WebSocket max reconnection attempts reached\", {\n level: \"error\",\n extra: {\n attempts: reconnectAttempts,\n maxAttempts: MAX_RECONNECT_ATTEMPTS\n }\n });\n return;\n }\n\n isReconnecting = true;\n reconnectAttempts++;\n\n console.log(`[WebSocket] Attempting reconnect ${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS}`);\n\n // Close existing connection\n closeChannel();\n\n // Add delay before reconnecting\n setTimeout(() => {\n connectToChannel()\n .catch(error => {\n console.error(\"[WebSocket] Reconnection failed:\", error);\n })\n .finally(() => {\n isReconnecting = false;\n });\n }, 1000 * reconnectAttempts); // Exponential backoff\n}\n","import { FirewallUser, FirewallEvent, FirewallPackage, FirewallStatusResponse } from './types';\n\ninterface FirewallComponentState {\n isLoading: boolean;\n isLoadingUsers: boolean;\n isLoadingMetrics: boolean;\n isLoadingEvents: boolean;\n status: string;\n summaryData: {\n status: string;\n users_protected: number;\n total_users: number;\n last_updated: string;\n unprotected_users: string[];\n blocked_packages: number;\n analyzed_packages: number;\n };\n users: FirewallUser[];\n updates: FirewallEvent[];\n lastHeartbeat: string | null;\n eventsPage: number;\n eventsLimit: number;\n eventTypeFilters: {\n success: boolean;\n error: boolean;\n info: boolean;\n warning: boolean;\n blocked: boolean;\n };\n activeFilters: string[];\n packageMetrics: {\n packages_installed: number;\n unique_packages: number;\n vulnerable_packages: number;\n malicious_packages?: number;\n };\n processedEventIds: Set;\n packagesPerPage: number;\n currentPage: number;\n isLoadingMore: boolean;\n hasMorePackages: boolean;\n hasMoreEvents: boolean;\n searchDebounceTimer: number | null;\n searchCache: Map>;\n isProtectionEnabled: boolean;\n isFullyConfigured: boolean;\n lastUpdated: string;\n hasData: boolean;\n summary: any;\n configurationWarning: { title: string; message: string } | null;\n hasPendingRequests: boolean;\n timeUpdateInterval: number | null;\n expandedEvents: Set;\n}\n\n// Define Alpine.js magic properties\ninterface AlpineMagicProperties {\n $nextTick: (callback: () => void) => void;\n $data: FirewallComponentState;\n}\n\n// Combine our component interface with Alpine.js magic properties\ntype FirewallComponentType = FirewallComponentState & AlpineMagicProperties & {\n formatDate(dateInput: string | number | Date): string;\n getRelativeTime(timestamp: string | number | Date): string;\n init(): void;\n setupInfiniteScroll(): void;\n fetchFirewallData(): Promise;\n fetchPackageMetrics(): Promise;\n fetchTelemetryEvents(reset?: boolean): Promise;\n loadMoreEvents(): Promise;\n resetEventTypeFilters(): void;\n applyEventTypeFilters(): void;\n refreshTelemetryEvents(): Promise;\n getCsrfToken(): string;\n toggleUserDetails(userId: string): void;\n togglePackagesVisibility(userId: string): void;\n toggleEventDetails(eventIndex: number): void;\n filterUsers(): void;\n resetHighlights(): void;\n handleFirewallUpdate(update: Record): void;\n notifyNewEvent(): void;\n renderPackagesTable(user: FirewallUser): string;\n highlightMatchingPackages(userId: string, searchTerm: string): number | void;\n searchPackages(searchTerm: string): Promise>;\n processSearchResults(data: any[], searchTerm: string): void;\n loadMorePackages(userId: string): Promise;\n loadUserPackages(userEmail: string): Promise;\n processBlockedPackages(blockedPackages: Record[]): void;\n processInstalledPackages(installedPackages: Record[]): void;\n startTimeUpdateInterval(): void;\n $destroy(): void;\n escapeHtml(unsafe: string): string;\n};\n\nexport function firewallComponent(): FirewallComponentType {\n return {\n isLoading: true,\n isLoadingUsers: true,\n isLoadingMetrics: true,\n isLoadingEvents: true,\n status: 'Active',\n summaryData: {\n status: \"Loading...\",\n users_protected: 0,\n total_users: 0,\n last_updated: \"Loading...\",\n unprotected_users: [],\n blocked_packages: 0,\n analyzed_packages: 0\n },\n users: [] as FirewallUser[],\n updates: [] as FirewallEvent[],\n lastHeartbeat: null as string | null,\n eventsPage: 1,\n eventsLimit: 20,\n eventTypeFilters: {\n success: true,\n error: true,\n info: true,\n warning: true,\n blocked: true\n },\n activeFilters: [],\n packageMetrics: {\n packages_installed: 0,\n unique_packages: 0,\n vulnerable_packages: 0\n },\n processedEventIds: new Set(),\n packagesPerPage: 5,\n currentPage: 1,\n isLoadingMore: false,\n hasMorePackages: false,\n hasMoreEvents: true,\n searchDebounceTimer: null,\n searchCache: new Map>(),\n isProtectionEnabled: false,\n isFullyConfigured: false,\n lastUpdated: '',\n hasData: false,\n summary: null,\n configurationWarning: null,\n hasPendingRequests: false,\n timeUpdateInterval: null,\n expandedEvents: new Set(),\n\n $nextTick: (function(callback: () => void) {\n callback();\n }) as AlpineMagicProperties['$nextTick'],\n $data: {} as FirewallComponentState,\n\n formatDate(dateInput: string | number | Date): string {\n if (!dateInput) return '';\n\n const date = new Date(dateInput);\n if (isNaN(date.getTime())) return '';\n\n return date.toLocaleString('en-US', {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n });\n },\n\n getRelativeTime(timestamp: string | number | Date): string {\n if (!timestamp || timestamp === 'Never') return 'Never';\n\n const now = new Date();\n const date = new Date(timestamp);\n\n // Check if the date is valid\n if (isNaN(date.getTime())) return 'Never';\n\n const diffMs = now.getTime() - date.getTime();\n const diffSec = Math.floor(diffMs / 1000);\n const diffMin = Math.floor(diffSec / 60);\n const diffHr = Math.floor(diffMin / 60);\n const diffDays = Math.floor(diffHr / 24);\n const diffWeeks = Math.floor(diffDays / 7);\n\n // Calculate months by comparing year and month values\n const monthDiff = (now.getFullYear() - date.getFullYear()) * 12 + (now.getMonth() - date.getMonth());\n const diffMonths = Math.max(0, monthDiff); // Ensure we don't get negative months\n const diffYears = Math.floor(diffDays / 365);\n\n // For events less than a minute old, show seconds\n if (diffSec < 60) return `${diffSec} second${diffSec !== 1 ? 's' : ''} ago`;\n\n // For events less than an hour old, show minutes\n if (diffMin < 60) return `${diffMin} minute${diffMin !== 1 ? 's' : ''} ago`;\n\n // For events less than a day old, show hours\n if (diffHr < 24) return `${diffHr} hour${diffHr !== 1 ? 's' : ''} ago`;\n\n // For events less than a week old, show days\n if (diffDays < 7) return `${diffDays} day${diffDays !== 1 ? 's' : ''} ago`;\n\n // For events less than a month old, show weeks\n if (diffWeeks < 4) return `${diffWeeks} week${diffWeeks !== 1 ? 's' : ''} ago`;\n\n // For events less than a year old, show months\n if (diffMonths < 12) return `${diffMonths} month${diffMonths !== 1 ? 's' : ''} ago`;\n\n // For events older than a year, show years\n return `${diffYears} year${diffYears !== 1 ? 's' : ''} ago`;\n },\n\n init() {\n this.updates = [];\n this.activeFilters = this.activeFilters || [];\n this.isLoadingUsers = true;\n this.isLoadingMetrics = true;\n this.isLoadingEvents = true;\n this.packageMetrics = { packages_installed: 0, unique_packages: 0, vulnerable_packages: 0 };\n this.processedEventIds = new Set();\n this.hasPendingRequests = false;\n\n // Start the time update interval\n this.startTimeUpdateInterval();\n\n // Fetch data with proper error handling\n Promise.all([\n this.fetchFirewallData()\n .then(() => {\n this.isLoadingUsers = false;\n })\n .catch((error: Error) => {\n console.error('Error fetching firewall data:', error);\n this.isLoadingUsers = false;\n }),\n this.fetchPackageMetrics()\n .then(() => {\n this.isLoadingMetrics = false;\n })\n .catch((error: Error) => {\n console.error('Error fetching package metrics:', error);\n this.isLoadingMetrics = false;\n }),\n this.fetchTelemetryEvents()\n .then(() => {\n this.applyEventTypeFilters();\n this.isLoadingEvents = false;\n })\n .catch((error: any) => {\n console.error('Error fetching telemetry events:', error);\n this.isLoadingEvents = false;\n })\n ]).catch(error => {\n console.error('Error during initialization:', error);\n });\n\n // Set up periodic refresh of package metrics\n setInterval(() => {\n this.fetchPackageMetrics();\n }, 5 * 60 * 1000);\n\n // Handle legacy event for backwards compatibility\n window.addEventListener('firewall:update', ((event: Event) => {\n const customEvent = event as CustomEvent;\n this.handleFirewallUpdate(customEvent.detail);\n }) as EventListener);\n\n window.addEventListener('firewall:heartbeat', ((event: Event) => {\n const customEvent = event as CustomEvent;\n this.lastHeartbeat = customEvent.detail.timestamp;\n this.summaryData.last_updated = customEvent.detail.timestamp;\n }) as EventListener);\n\n // Handle legacy events for backwards compatibility\n window.addEventListener('firewall:configured', ((event: Event) => {\n const customEvent = event as CustomEvent;\n this.handleFirewallUpdate(customEvent.detail);\n this.status = 'Active';\n }) as EventListener);\n\n window.addEventListener('firewall:disabled', ((event: Event) => {\n const customEvent = event as CustomEvent;\n this.handleFirewallUpdate(customEvent.detail);\n this.status = 'Disabled';\n }) as EventListener);\n\n // Add polling mechanism to fetch fresh data every 10 seconds\n setInterval(() => {\n // Only create refresh event if there are no pending requests\n if (!this.hasPendingRequests) {\n // Create and dispatch a firewall:refresh-events event\n const refreshEvent = new CustomEvent('firewall:refresh-events', {\n detail: {\n eventId: `poll-${Date.now()}`,\n eventType: 'polling_refresh'\n }\n });\n window.dispatchEvent(refreshEvent);\n }\n }, 10000);\n\n // Add new event listeners for API refresh approach\n window.addEventListener('firewall:refresh-events', ((event: Event) => {\n const customEvent = event as CustomEvent;\n // Store the event ID to avoid duplicate processing\n if (customEvent.detail.eventId) {\n this.processedEventIds.add(customEvent.detail.eventId);\n }\n\n // Set pending requests flag\n this.hasPendingRequests = true;\n\n // Refresh all data from API\n Promise.all([\n // Refresh firewall status data\n this.fetchFirewallData().catch(error => {\n console.error('Error refreshing firewall data:', error);\n }),\n // Refresh package metrics\n this.fetchPackageMetrics().catch(error => {\n console.error('Error refreshing package metrics:', error);\n }),\n // Refresh events data from API\n this.fetchTelemetryEvents(false).then(() => {\n this.notifyNewEvent();\n }).catch(error => {\n console.error('Error refreshing events:', error);\n })\n ]).finally(() => {\n // Clear pending requests flag when all requests are complete\n this.hasPendingRequests = false;\n });\n }) as EventListener);\n\n this.$nextTick(() => {\n this.setupInfiniteScroll();\n });\n },\n\n startTimeUpdateInterval() {\n // Clear any existing interval to avoid multiple instances\n if (this.timeUpdateInterval) {\n clearInterval(this.timeUpdateInterval);\n }\n\n // Set up a new interval to update times every 30 seconds\n this.timeUpdateInterval = window.setInterval(() => {\n // Only update if there are events to refresh\n if (this.updates.length > 0) {\n // Create a new array reference to force Alpine.js to re-render\n this.updates = this.updates.map(update => ({\n ...update,\n // Keep the same data but force a re-render\n timestamp: update.timestamp\n }));\n }\n }, 30000); // Update every 30 seconds\n },\n\n async fetchPackageMetrics() {\n try {\n const response = await fetch('api/package-metrics/');\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data = await response.json();\n\n if (data) {\n this.packageMetrics = {\n packages_installed: data.packages_installed || 0,\n unique_packages: data.unique_packages || 0,\n vulnerable_packages: data.vulnerable_packages || 0,\n malicious_packages: data.malicious_packages || 0\n };\n }\n } catch (error) {\n console.error('Error fetching package metrics:', error);\n // Set default values on error\n this.packageMetrics = {\n packages_installed: 0,\n unique_packages: 0,\n vulnerable_packages: 0,\n malicious_packages: 0\n };\n } finally {\n this.isLoadingMetrics = false;\n }\n },\n\n setupInfiniteScroll() {\n const eventsContainer = document.querySelector('.firewall-events-scroll');\n if (!eventsContainer) return;\n\n const loadMoreButton = document.querySelector('[data-infinite-scroll=\"disabled\"]');\n if (loadMoreButton) {\n loadMoreButton.removeAttribute('data-infinite-scroll');\n loadMoreButton.setAttribute('hidden', 'true');\n }\n\n const scrollLoader = document.getElementById('infinite-scroll-loader');\n\n let isLoading = false;\n let scrollTimeout: number | null = null;\n let lastRequestTime = 0;\n const MIN_REQUEST_INTERVAL = 1000; // Minimum 1 second between requests\n\n eventsContainer.addEventListener('scroll', () => {\n if (scrollTimeout) {\n window.clearTimeout(scrollTimeout);\n }\n\n scrollTimeout = window.setTimeout(() => {\n if (isLoading || !this.$data.eventsLimit || this.updates.length < this.$data.eventsLimit || !this.hasMoreEvents) {\n return;\n }\n\n const { scrollTop, scrollHeight, clientHeight } = eventsContainer;\n // Calculate distance from bottom (percentage scrolled)\n const scrolledPercentage = (scrollTop + clientHeight) / scrollHeight;\n // Calculate threshold (80% of the way through)\n const threshold = 0.8;\n\n // Only load more if we've scrolled past the threshold\n if (scrolledPercentage > threshold) {\n const now = Date.now();\n if (now - lastRequestTime < MIN_REQUEST_INTERVAL) {\n return; // Skip if we're making requests too quickly\n }\n\n isLoading = true;\n lastRequestTime = now;\n\n if (scrollLoader) {\n scrollLoader.classList.remove('hidden');\n }\n\n this.loadMoreEvents().finally(() => {\n isLoading = false;\n\n if (scrollLoader) {\n scrollLoader.classList.add('hidden');\n }\n });\n }\n }, 150);\n });\n },\n\n async fetchFirewallData() {\n try {\n const response = await fetch('api/status/');\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data = await response.json();\n\n this.isProtectionEnabled = data.firewall_status.protection_enabled;\n this.isFullyConfigured = data.firewall_status.is_fully_configured;\n this.lastUpdated = data.last_updated_time || 'Never';\n\n // Create a map of existing users to preserve their expanded state\n const existingUsersMap = new Map(\n this.users.map(user => [user.id, {\n showAllPackages: user.showAllPackages,\n packages: user.packages,\n isLoadingPackages: user.isLoadingPackages\n }])\n );\n\n const users: FirewallUser[] = data.users.map((user: any) => {\n const existingUser = existingUsersMap.get(user.email);\n return {\n id: user.email,\n email: user.email,\n first_name: user.first_name || '',\n last_name: user.last_name || '',\n username: user.email.split('@')[0],\n is_protected: user.is_protected,\n package_managers: user.package_managers || [],\n package_manager_versions: user.package_manager_versions || {},\n last_seen: user.last_seen || 'Never',\n packages: existingUser?.packages || [],\n total_packages: user.total_count || 0,\n showAllPackages: existingUser?.showAllPackages || false,\n hasMorePackages: user.total_count > 0,\n isLoadingPackages: existingUser?.isLoadingPackages || false\n };\n });\n\n this.users = users;\n this.isLoadingUsers = false;\n this.isLoading = false;\n this.hasData = true;\n\n } catch (error) {\n console.error('Error fetching firewall data:', error);\n this.isLoadingUsers = false;\n this.isLoading = false;\n }\n },\n\n async fetchTelemetryEvents(reset = true) {\n try {\n if (reset) {\n this.eventsPage = 1;\n this.hasMoreEvents = true;\n }\n\n const scrollLoader = document.getElementById('infinite-scroll-loader');\n if (scrollLoader && reset) {\n scrollLoader.classList.remove('hidden');\n }\n\n const params = new URLSearchParams({\n limit: this.eventsLimit.toString(),\n offset: ((this.eventsPage - 1) * this.eventsLimit).toString()\n });\n\n if (this.activeFilters.length > 0) {\n params.append('event_types', this.activeFilters.join(','));\n }\n\n // For refreshes (not reset and not pagination), we want to get the most recent events\n // rather than loading the next page\n if (!reset && this.eventsPage === 1) {\n // When refreshing, we fetch the most recent events\n params.set('offset', '0');\n }\n\n const response = await fetch(`api/telemetry/events/?${params.toString()}`);\n\n if (!response.ok) {\n // Handle 429 (Too Many Requests) gracefully during infinite scroll\n if (response.status === 429 && !reset) {\n this.hasMoreEvents = false;\n const loadMoreButton = document.querySelector('[data-infinite-scroll=\"disabled\"]');\n if (loadMoreButton) {\n loadMoreButton.classList.add('hidden');\n }\n return;\n }\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data = await response.json();\n\n if (data && Array.isArray(data.results)) {\n // Group events by correlation ID for package.installed events\n const correlatedEvents = new Map>>();\n const nonCorrelatedEvents: Array> = [];\n\n // First pass: separate correlated events from non-correlated ones\n data.results.forEach((event: Record) => {\n // Only apply correlation grouping to package install/uninstall events\n if (event.event_type && (event.event_type.includes('package.installed') || event.event_type.includes('package.uninstalled'))) {\n const correlationId = event.correlation_id || event.context?.correlation_id;\n if (correlationId) {\n if (!correlatedEvents.has(correlationId)) {\n correlatedEvents.set(correlationId, []);\n }\n correlatedEvents.get(correlationId)?.push(event);\n } else {\n nonCorrelatedEvents.push(event);\n }\n } else {\n // Non-package install/uninstall events\n nonCorrelatedEvents.push(event);\n }\n });\n\n // Process correlated events first to create summary events\n const summaryEvents: Array> = [];\n\n correlatedEvents.forEach((events, correlationId) => {\n // Sort events by timestamp to show the most recent first\n events.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());\n\n if (events.length === 1) {\n // If there's only one event with this correlation ID, just add it to non-correlated\n nonCorrelatedEvents.push(events[0]);\n } else {\n // Create a summary event for multiple correlated events\n const firstEvent = events[0];\n\n // Determine the event type for the summary\n let summaryEventType: string;\n let summaryEventTypeDisplay: string;\n\n if (firstEvent.event_type.includes('package.installed')) {\n summaryEventType = 'package.installed.summary';\n summaryEventTypeDisplay = 'Package Installation Summary';\n } else if (firstEvent.event_type.includes('package.uninstalled')) {\n summaryEventType = 'package.uninstalled.summary';\n summaryEventTypeDisplay = 'Package Uninstallation Summary';\n } else {\n // Fallback - shouldn't reach here based on our filtering\n summaryEventType = 'summary';\n summaryEventTypeDisplay = 'Event Summary';\n }\n\n // Create a new summary event based on the first event\n const summaryEvent = {\n ...firstEvent,\n id: `summary-${correlationId}`,\n is_summary: true,\n summary_count: events.length,\n related_events: events,\n event_type: summaryEventType,\n event_type_display: summaryEventTypeDisplay\n };\n\n summaryEvents.push(summaryEvent);\n }\n });\n\n // Combine and sort all events by timestamp to preserve chronological order\n const allEvents = [...summaryEvents, ...nonCorrelatedEvents];\n allEvents.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());\n\n // Process all events to format them for display\n const formattedEvents = allEvents.map((event: Record): FirewallEvent | null => {\n const eventData = event.data || {};\n const eventContext = event.context || {};\n const eventType = event.event_type || '';\n const eventTypeDisplay = event.event_type_display || eventType.split('.').pop() || 'Event';\n\n // Use the user info directly from the serializer\n let userName = this.escapeHtml(event.user?.name || 'Unknown user');\n\n // Get device name from context\n const deviceName = this.escapeHtml(eventContext.runtime?.host?.name || '');\n\n // Get project info from context\n const projectId = this.escapeHtml(eventContext.project?.id || '');\n\n const eventId = event.id || `api-${event.event_time}-${Math.random().toString(36).substring(2, 9)}`;\n\n if (this.processedEventIds.has(eventId)) {\n return null;\n }\n\n this.processedEventIds.add(eventId);\n\n let message = '';\n let displayType = '';\n let expandable = false;\n let packages: FirewallPackage[] = [];\n\n if (eventType.includes('package.installed.summary')) {\n displayType = 'success';\n const relatedEvents = event.related_events || [];\n const count = event.summary_count || relatedEvents.length;\n expandable = count > 1; // Only expandable if there are multiple packages\n\n // Get the first event's package info for display\n const firstPackage = relatedEvents[0]?.package || {};\n const packageName = this.escapeHtml(firstPackage.name || 'Unknown package');\n const packageVersion = this.escapeHtml(firstPackage.version || 'Unknown version');\n const packageManager = this.escapeHtml(relatedEvents[0]?.data?.package_manager || firstPackage.package_manager || 'Unknown package manager');\n const project = this.escapeHtml(firstPackage.project || projectId || '');\n\n message = `${userName} installed ${packageName}@${packageVersion}`;\n\n // Add information about additional packages\n if (count > 1) {\n message += ` and ${count - 1} other package${count - 1 > 1 ? 's' : ''}`;\n }\n\n message += ` using ${packageManager}`;\n\n if (project) {\n message += ` in project ${project}`;\n }\n\n // Extract packages from related events\n packages = relatedEvents.map((e: any) => ({\n name: this.escapeHtml(e.package?.name || 'Unknown'),\n version: this.escapeHtml(e.package?.version || 'Unknown'),\n package_manager: this.escapeHtml(e.data?.package_manager || e.package?.package_manager || 'Unknown'),\n project: this.escapeHtml(e.package?.project || projectId || ''),\n install_path: this.escapeHtml(e.package?.install_path || ''),\n installed_at: e.timestamp\n }));\n }\n else if (eventType.includes('package.uninstalled.summary')) {\n displayType = 'info';\n const relatedEvents = event.related_events || [];\n const count = event.summary_count || relatedEvents.length;\n expandable = count > 1; // Only expandable if there are multiple packages\n\n // Get the first event's package info for display\n const firstPackage = relatedEvents[0]?.package || {};\n const packageName = this.escapeHtml(firstPackage.name || relatedEvents[0]?.data?.package_name || 'Unknown package');\n const packageVersion = this.escapeHtml(firstPackage.version || relatedEvents[0]?.data?.version || 'Unknown version');\n const packageManager = this.escapeHtml(relatedEvents[0]?.data?.tool || relatedEvents[0]?.data?.package_manager || firstPackage.package_manager || 'Unknown package manager');\n const project = this.escapeHtml(firstPackage.project || projectId || '');\n\n message = `${userName} uninstalled ${packageName}@${packageVersion}`;\n\n // Add information about additional packages\n if (count > 1) {\n message += ` and ${count - 1} other package${count - 1 > 1 ? 's' : ''}`;\n }\n\n message += ` using ${packageManager}`;\n\n if (project) {\n message += ` from project ${project}`;\n }\n\n // Extract packages from related events\n packages = relatedEvents.map((e: any) => ({\n name: this.escapeHtml(e.package?.name || e.data?.package_name || 'Unknown'),\n version: this.escapeHtml(e.package?.version || e.data?.version || 'Unknown'),\n package_manager: this.escapeHtml(e.data?.tool || e.data?.package_manager || e.package?.package_manager || 'Unknown'),\n project: this.escapeHtml(e.package?.project || projectId || ''),\n install_path: this.escapeHtml(e.package?.install_path || ''),\n installed_at: e.timestamp\n }));\n }\n else if (eventType.includes('package.installed')) {\n displayType = 'success';\n expandable = false; // Single package installations are not expandable\n // Use the package data directly from the API response\n const packageInfo = event.package || {};\n const packageName = this.escapeHtml(packageInfo.name || 'Unknown package');\n const packageVersion = this.escapeHtml(packageInfo.version || 'Unknown version');\n const packageManager = this.escapeHtml(event.data?.package_manager || packageInfo.package_manager || 'Unknown package manager');\n const project = this.escapeHtml(packageInfo.project || projectId || '');\n\n message = `${userName} installed ${packageName}@${packageVersion} using ${packageManager}`;\n\n if (project) {\n message += ` in project ${project}`;\n }\n\n // Add the package to the packages array\n packages = [{\n name: packageName,\n version: packageVersion,\n package_manager: packageManager,\n project: project,\n install_path: this.escapeHtml(packageInfo.install_path || ''),\n installed_at: event.timestamp\n }];\n }\n else if (eventType.includes('package.blocked')) {\n displayType = 'blocked';\n const packageInfo = event.package || {};\n const packageName = this.escapeHtml(packageInfo.name || event.data?.package_name || 'Unknown package');\n const packageVersion = this.escapeHtml(packageInfo.version || event.data?.version || 'Unknown version');\n const packageManager = this.escapeHtml(event.data?.package_manager || packageInfo.package_manager || 'Unknown package manager');\n const project = this.escapeHtml(packageInfo.project || projectId || '');\n const reason = this.escapeHtml(packageInfo.reason || event.data?.reason || '');\n\n message = `Safety blocked ${userName} from installing ${packageName}@${packageVersion} via ${packageManager}`;\n\n if (project) {\n message += ` in project ${project}`;\n }\n\n if (reason) {\n message += `
Reason: ${reason}`;\n }\n }\n else if (eventType.includes('package.uninstalled')) {\n displayType = 'info';\n // Use the package data directly from the API response\n const packageInfo = event.package || {};\n const packageName = this.escapeHtml(packageInfo.name || event.data?.package_name || 'Unknown package');\n const packageVersion = this.escapeHtml(packageInfo.version || event.data?.version || 'Unknown version');\n const packageManager = this.escapeHtml(event.data?.tool || event.data?.package_manager || packageInfo.package_manager || 'Unknown package manager');\n const project = this.escapeHtml(packageInfo.project || projectId || '');\n expandable = false; // Single package uninstallations are not expandable by default\n\n message = `${userName} uninstalled ${packageName}@${packageVersion} using ${packageManager}`;\n\n if (project) {\n message += ` from project ${project}`;\n }\n\n // Add the package to the packages array\n packages = [{\n name: packageName,\n version: packageVersion,\n package_manager: packageManager,\n project: project,\n install_path: this.escapeHtml(packageInfo.install_path || ''),\n installed_at: event.timestamp\n }];\n }\n else if (eventType.includes('package.updated')) {\n displayType = 'success';\n // Use the package data directly from the API response\n const packageInfo = event.package || {};\n const packageName = this.escapeHtml(packageInfo.name || event.data?.package_name || 'Unknown package');\n const packageVersion = this.escapeHtml(packageInfo.version || event.data?.current_version || event.data?.version || 'Unknown version');\n const previousVersion = this.escapeHtml(packageInfo.previous_version || event.data?.previous_version || '');\n const packageManager = this.escapeHtml(event.data?.package_manager || packageInfo.package_manager || 'Unknown package manager');\n const project = this.escapeHtml(packageInfo.project || projectId || '');\n\n message = `${userName} updated ${packageName}`;\n\n if (previousVersion) {\n message += ` from ${previousVersion}`;\n }\n\n message += ` to ${packageVersion} using ${packageManager}`;\n\n if (project) {\n message += ` in project ${project}`;\n }\n }\n else if (eventType.includes('firewall.configured')) {\n displayType = 'success';\n message = `${userName} configured Safety Firewall`;\n }\n else if (eventType.includes('firewall.disabled')) {\n displayType = 'error';\n const reason = this.escapeHtml(event.data?.reason || '');\n message = `${userName} disabled Safety Firewall`;\n if (reason) {\n message += `
Reason: ${reason}`;\n }\n }\n else if (eventType.includes('firewall.heartbeat')) {\n displayType = 'info';\n message = `Safety Firewall heartbeat from ${userName}`;\n if (deviceName) {\n message += ` on device ${deviceName}`;\n }\n }\n else if (eventType.includes('command.executed')) {\n displayType = 'success';\n const commandName = this.escapeHtml(event.data?.command_name || 'Unknown command');\n message = `${userName} executed command: safety ${commandName}`;\n }\n else if (eventType.includes('command.error')) {\n displayType = 'error';\n const commandName = this.escapeHtml(event.data?.command_name || 'Unknown command');\n const errorMessage = this.escapeHtml(event.data?.error_message);\n message = `${userName} encountered an error with command: safety ${commandName}`;\n if (errorMessage) {\n message += `
Error: ${errorMessage}`;\n }\n }\n else {\n // Generic event\n message = `${eventTypeDisplay} by ${userName}`;\n }\n\n return {\n type: displayType,\n message,\n timestamp: event.timestamp,\n eventId,\n isNew: !reset && this.eventsPage === 1 && !this.processedEventIds.has(eventId),\n expandable,\n expanded: false,\n packages,\n raw_event: {\n data: eventData,\n context: eventContext,\n event_type: eventType,\n event_type_display: eventTypeDisplay,\n source: event.source || 'unknown',\n timestamp: event.timestamp\n }\n } as FirewallEvent;\n }).filter((event): event is FirewallEvent => event !== null);\n\n // Make sure we're requesting more events from the API if needed to compensate for grouping\n // This ensures we still have enough events to trigger infinite scrolling\n const displayedEventCount = formattedEvents.length;\n const originalEventCount = data.results.length;\n\n // If we've filtered out more than 50% of the events due to grouping,\n // we might need to fetch additional events\n if (displayedEventCount < originalEventCount * 0.5 && originalEventCount === this.eventsLimit) {\n this.hasMoreEvents = true;\n } else {\n // Update hasMoreEvents flag based on whether we received a full page of results\n this.hasMoreEvents = data.results.length === this.eventsLimit;\n }\n\n if (reset) {\n // Complete reset - replace all events\n this.updates = formattedEvents;\n } else if (this.eventsPage === 1) {\n // We're refreshing - prepend new events to the existing list\n // Check for duplicates by eventId\n const existingEventIds = new Set(this.updates.map((event: FirewallEvent) => event.eventId));\n const uniqueNewEvents = formattedEvents.filter((event: FirewallEvent) => !existingEventIds.has(event.eventId));\n\n if (uniqueNewEvents.length > 0) {\n // Add new events with a slight delay to ensure smooth animation\n setTimeout(() => {\n this.updates = [...uniqueNewEvents, ...this.updates];\n this.notifyNewEvent();\n }, 50);\n }\n } else {\n // We're paginating - append events to the existing list\n this.updates = [...this.updates, ...formattedEvents];\n }\n\n this.applyEventTypeFilters();\n\n const loadMoreButton = document.querySelector('[data-infinite-scroll=\"disabled\"]');\n if (loadMoreButton) {\n if (!this.hasMoreEvents) {\n loadMoreButton.classList.add('hidden');\n } else {\n loadMoreButton.classList.remove('hidden');\n }\n }\n } else {\n this.hasMoreEvents = false;\n if (!reset) {\n const loadMoreButton = document.querySelector('[data-infinite-scroll=\"disabled\"]');\n if (loadMoreButton) {\n loadMoreButton.classList.add('hidden');\n }\n }\n }\n } catch (error: unknown) {\n console.error('Error fetching telemetry events:', error);\n this.hasMoreEvents = false;\n\n this.updates = [{\n type: 'error',\n message: `Error loading events: ${error instanceof Error ? error.message : 'Unknown error'}. Please try refreshing the page.`,\n timestamp: this.formatDate(new Date()),\n eventId: 'error-event',\n isNew: true\n }];\n\n const event = new CustomEvent('notify', {\n bubbles: true,\n detail: {\n type: 'error',\n content: 'Failed to load telemetry events',\n displayDuration: 5000\n }\n });\n window.dispatchEvent(event);\n } finally {\n this.isLoadingEvents = false;\n\n // Only hide the scroll loader if it was shown (during reset)\n const scrollLoader = document.getElementById('infinite-scroll-loader');\n if (scrollLoader && reset) {\n scrollLoader.classList.add('hidden');\n }\n }\n },\n\n async loadMoreEvents() {\n // Prevent concurrent requests\n if (this.isLoadingMore) {\n return;\n }\n\n try {\n const scrollLoader = document.getElementById('infinite-scroll-loader');\n if (scrollLoader) {\n scrollLoader.classList.remove('hidden');\n }\n\n this.eventsPage++;\n this.isLoadingMore = true;\n\n await this.fetchTelemetryEvents(false);\n } catch (error) {\n console.error('Error loading more events:', error);\n } finally {\n this.isLoadingMore = false;\n }\n },\n\n resetEventTypeFilters() {\n this.eventTypeFilters = {\n success: true,\n error: true,\n info: true,\n warning: true,\n blocked: true\n };\n },\n\n applyEventTypeFilters() {\n if (!Array.isArray(this.updates)) {\n this.updates = [];\n return;\n }\n\n const enabledTypes = Object.entries(this.eventTypeFilters || {})\n .filter(([_, enabled]) => enabled)\n .map(([type]) => type);\n\n const filteredUpdates = this.updates.filter((update: FirewallEvent) =>\n update && update.type && enabledTypes.includes(update.type)\n );\n\n if (filteredUpdates.length === 0 && this.updates.length > 0) {\n this.updates.forEach(update => {\n if (!update.type || !enabledTypes.includes(update.type)) {\n update.type = 'info';\n }\n });\n } else {\n this.updates = filteredUpdates;\n }\n\n this.activeFilters = enabledTypes;\n },\n\n async refreshTelemetryEvents() {\n await this.fetchTelemetryEvents(false);\n },\n\n getCsrfToken() {\n return document.cookie\n .split('; ')\n .find(row => row.startsWith('csrftoken='))\n ?.split('=')[1] || '';\n },\n\n toggleUserDetails(userId: string) {\n const user = this.users.find(u => u.id === userId);\n if (!user) return;\n\n const row = document.getElementById(`${userId}-details`);\n const chevron = document.getElementById(`${userId}-chevron`);\n\n if (!row) return;\n\n const isHidden = row.classList.contains('hidden');\n row.classList.toggle('hidden');\n\n if (chevron) {\n chevron.style.transform = isHidden ? 'rotate(90deg)' : '';\n }\n\n // Load packages for all users when expanding their details\n if (isHidden) {\n const tableBody = document.getElementById(`${userId}-packages-tbody`);\n\n if (tableBody) {\n tableBody.innerHTML = `\n \n
\n
\n
\n
\n
\n
\n \n \n
\n
\n
\n
\n
\n
\n \n \n
\n
\n
\n
\n
\n
\n \n `;\n }\n\n this.loadUserPackages(user.email);\n }\n },\n\n togglePackagesVisibility(userId: string) {\n const user = this.users.find((u: FirewallUser) => u.id === userId);\n if (!user) return;\n\n user.showAllPackages = !user.showAllPackages;\n\n const tableBody = document.getElementById(`${userId}-packages-tbody`);\n if (tableBody) {\n tableBody.style.opacity = '0';\n tableBody.style.transition = 'opacity 0.15s ease';\n\n const searchInput = document.getElementById('search-input') as HTMLInputElement;\n const searchTerm = searchInput?.value.toLowerCase() || '';\n\n setTimeout(() => {\n tableBody.innerHTML = this.renderPackagesTable(user);\n\n void tableBody.offsetHeight;\n\n tableBody.style.opacity = '1';\n\n setTimeout(() => {\n if (searchTerm) {\n this.highlightMatchingPackages(userId, searchTerm);\n\n setTimeout(() => {\n const hasHighlighting = tableBody.querySelector('.search-highlight');\n if (!hasHighlighting && searchTerm) {\n this.highlightMatchingPackages(userId, searchTerm);\n }\n }, 100);\n }\n }, 150);\n }, 50);\n }\n },\n\n processSearchResults(data: any[], searchTerm: string): void {\n const packagesByUser: Record = {};\n data.forEach((pkg: any) => {\n if (pkg.user_email) {\n if (!packagesByUser[pkg.user_email]) {\n packagesByUser[pkg.user_email] = [];\n }\n packagesByUser[pkg.user_email].push(pkg);\n }\n });\n\n this.users.forEach(user => {\n const userRow = document.querySelector(`[data-user-id=\"${user.id}\"]`);\n if (userRow) {\n userRow.classList.remove('loading');\n }\n\n const tableBody = document.getElementById(`${user.id}-packages-tbody`);\n if (!tableBody) return;\n\n const userPackages = packagesByUser[user.email] || [];\n\n if (userPackages.length > 0) {\n if (userRow) {\n const userRowElement = userRow as HTMLElement;\n userRowElement.style.display = '';\n userRowElement.style.opacity = '1';\n userRow.classList.add('row-with-match');\n }\n\n const detailsRow = document.getElementById(`${user.id}-details`);\n const chevron = document.getElementById(`${user.id}-chevron`);\n if (detailsRow) {\n detailsRow.classList.remove('hidden');\n detailsRow.classList.add('visible-with-transition');\n\n if (chevron) {\n chevron.style.transform = 'rotate(90deg)';\n }\n }\n\n // For search results, always show all packages without pagination\n const thisUser = this.users.find(u => u.id === user.id);\n if (thisUser) {\n thisUser.showAllPackages = true;\n }\n\n const packageRows = userPackages.map((pkg: any) => `\n \n ${this.escapeHtml(pkg.name || 'Unknown')}\n ${this.escapeHtml(pkg.version || 'Unknown')}\n ${this.escapeHtml(pkg.project || 'Unknown')}\n ${this.escapeHtml(pkg.package_manager || 'Unknown')}\n ${this.escapeHtml(pkg.install_path || 'Unknown')}\n ${this.getRelativeTime(pkg.installed_at) || 'Never'}\n \n `).join('');\n\n tableBody.innerHTML = packageRows;\n\n const nameCells = tableBody.querySelectorAll('.name-cell');\n nameCells.forEach(cell => {\n const content = cell.textContent || '';\n const lowerContent = content.toLowerCase();\n const lowerSearchTerm = searchTerm.toLowerCase();\n\n if (lowerContent.includes(lowerSearchTerm)) {\n const highlightedContent = content.replace(\n new RegExp(this.escapeHtml(searchTerm).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'),\n 'gi'),\n (match: string) => `${this.escapeHtml(match)}`\n );\n cell.innerHTML = highlightedContent;\n }\n });\n } else {\n const originalContent = tableBody.getAttribute('data-original-content');\n if (originalContent) {\n tableBody.innerHTML = originalContent;\n } else {\n tableBody.innerHTML = '';\n }\n }\n });\n },\n\n filterUsers() {\n // Don't proceed with search if users are still loading\n if (this.isLoadingUsers) {\n return;\n }\n\n const searchInput = document.querySelector('input[placeholder*=\"Search\"]');\n if (!searchInput) {\n console.warn('Search input not found');\n return;\n }\n\n const searchTerm = searchInput.value.trim().toLowerCase();\n\n // Reset search UI when the search term is empty\n if (!searchTerm) {\n this.resetHighlights();\n\n // Reset all user rows and make sure they're visible\n this.users.forEach(user => {\n // Mark packages as needing refresh when a user dropdown is expanded\n user.packages = [];\n\n const userRow = document.querySelector(`[data-user-id=\"${user.id}\"]`);\n if (userRow) {\n (userRow as HTMLElement).style.display = '';\n (userRow as HTMLElement).style.opacity = '1';\n userRow.classList.remove('row-with-match');\n }\n\n const detailsRow = document.getElementById(`${user.id}-details`);\n if (detailsRow) {\n detailsRow.classList.add('hidden');\n detailsRow.classList.remove('visible-with-transition');\n detailsRow.classList.remove('expanded-with-matches');\n }\n\n const chevron = document.getElementById(`${user.id}-chevron`);\n if (chevron) {\n chevron.style.transform = '';\n }\n });\n\n return;\n }\n\n // Show loading indicator\n const loadingIndicator = document.createElement('div');\n loadingIndicator.className = 'search-loading-indicator';\n loadingIndicator.innerHTML = `\n \n \n \n \n `;\n searchInput.parentElement?.appendChild(loadingIndicator);\n\n // Hide all user rows by default for search\n this.users.forEach(user => {\n const userRow = document.querySelector(`[data-user-id=\"${user.id}\"]`);\n if (userRow) {\n (userRow as HTMLElement).style.display = 'none';\n (userRow as HTMLElement).style.opacity = '0';\n userRow.classList.remove('row-with-match');\n }\n });\n\n // Track search stats\n const usersWithPackageMatches = new Set();\n\n // First check in the currently loaded data\n this.users.forEach(user => {\n const userId = user.id;\n const userRow = document.querySelector(`[data-user-id=\"${userId}\"]`);\n if (!userRow) return;\n\n // Check for matches in user info\n const userInfo = `${user.first_name} ${user.last_name} ${user.email}`.toLowerCase();\n const userMatches = userInfo.includes(searchTerm);\n\n if (userMatches) {\n (userRow as HTMLElement).style.display = '';\n (userRow as HTMLElement).style.opacity = '1';\n }\n\n if (user.packages && user.packages.length > 0) {\n let packageMatches = false;\n\n user.packages.forEach(pkg => {\n if (\n (pkg.name && pkg.name.toLowerCase().includes(searchTerm)) ||\n (pkg.version && pkg.version.toLowerCase().includes(searchTerm)) ||\n (pkg.project && pkg.project.toLowerCase().includes(searchTerm)) ||\n (pkg.package_manager && pkg.package_manager.toLowerCase().includes(searchTerm)) ||\n (pkg.install_path && pkg.install_path.toLowerCase().includes(searchTerm)) ||\n (pkg.installed_at && pkg.installed_at.toLowerCase().includes(searchTerm))\n ) {\n packageMatches = true;\n usersWithPackageMatches.add(userId);\n }\n });\n\n if (packageMatches) {\n (userRow as HTMLElement).style.display = '';\n (userRow as HTMLElement).style.opacity = '1';\n userRow.classList.add('row-with-match');\n\n const detailsRow = document.getElementById(`${userId}-details`);\n const chevron = document.getElementById(`${userId}-chevron`);\n\n if (detailsRow) {\n detailsRow.classList.remove('hidden');\n detailsRow.classList.remove('hidden-with-transition');\n detailsRow.classList.add('visible-with-transition');\n detailsRow.classList.add('expanded-with-matches');\n\n if (chevron) {\n chevron.style.transform = 'rotate(90deg)';\n }\n\n const packagesTable = detailsRow.querySelector('table');\n const packagesBody = document.getElementById(`${userId}-packages-tbody`);\n\n if (packagesTable && packagesBody) {\n (packagesTable as HTMLElement).style.display = 'table';\n (packagesBody as HTMLElement).style.display = 'table-row-group';\n\n this.highlightMatchingPackages(userId, searchTerm);\n }\n }\n }\n }\n });\n\n if (this.searchDebounceTimer) {\n window.clearTimeout(this.searchDebounceTimer);\n }\n\n this.searchDebounceTimer = window.setTimeout(async () => {\n try {\n // Only trigger API search if we have at least 3 characters\n if (searchTerm.length >= 3) {\n // Make API request without showing any loading skeletons\n const response = await fetch(`api/search-packages/?q=${encodeURIComponent(searchTerm)}`);\n\n if (response.status === 429) {\n throw new Error('Rate limit exceeded. Please wait a moment before searching again.');\n }\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data = await response.json();\n if (data && Array.isArray(data)) {\n const packagesByUser: Record = {};\n data.forEach((pkg: any) => {\n if (pkg.user_email) {\n if (!packagesByUser[pkg.user_email]) {\n packagesByUser[pkg.user_email] = [];\n }\n packagesByUser[pkg.user_email].push(pkg);\n }\n });\n\n const userPackagesMap = new Map>();\n\n this.users.forEach(user => {\n const packageKeys = new Set();\n\n user.packages.forEach(pkg => {\n const key = `${pkg.name}|${pkg.version}|${pkg.project}|${pkg.package_manager}|${pkg.install_path}`;\n packageKeys.add(key);\n });\n\n userPackagesMap.set(user.email, packageKeys);\n });\n\n let updatedUsers = false;\n this.users = this.users.map(user => {\n const packageKeys = userPackagesMap.get(user.email) || new Set();\n\n const userPackages = packagesByUser[user.email] || [];\n\n if (userPackages.length > 0) {\n const newPackages = userPackages.map((p: any) => ({\n name: p.name,\n version: p.version || 'Unknown',\n project: p.project || 'Unknown',\n package_manager: p.package_manager || 'Unknown',\n install_path: p.install_path || 'Unknown',\n installed_at: p.installed_at // Send raw timestamp\n }));\n\n const uniqueNewPackages = newPackages.filter((pkg: FirewallPackage) => {\n const key = `${pkg.name}|${pkg.version}|${pkg.project}|${pkg.package_manager}|${pkg.install_path}`;\n if (packageKeys.has(key)) {\n return false;\n }\n packageKeys.add(key);\n return true;\n });\n\n if (uniqueNewPackages.length > 0) {\n updatedUsers = true;\n return {\n ...user,\n packages: [...user.packages, ...uniqueNewPackages]\n };\n }\n }\n return user;\n });\n\n if (updatedUsers) {\n this.$nextTick(() => {\n this.users.forEach(user => {\n if (packagesByUser[user.email]?.length > 0) {\n const userRow = document.querySelector(`[data-user-id=\"${user.id}\"]`) as HTMLElement;\n if (userRow) {\n userRow.style.display = '';\n userRow.style.opacity = '1';\n userRow.classList.add('row-with-match');\n }\n\n const detailsRow = document.getElementById(`${user.id}-details`);\n const chevron = document.getElementById(`${user.id}-chevron`);\n\n if (detailsRow) {\n detailsRow.classList.remove('hidden');\n detailsRow.style.display = '';\n\n if (chevron) {\n chevron.style.transform = 'rotate(90deg)';\n }\n }\n\n const tableBody = document.getElementById(`${user.id}-packages-tbody`);\n if (tableBody) {\n tableBody.innerHTML = this.renderPackagesTable(user);\n\n if (searchTerm) {\n this.highlightMatchingPackages(user.id, searchTerm);\n }\n }\n }\n });\n });\n }\n }\n }\n } catch (error) {\n console.error('Error in search debounce:', error);\n // Show error message to user\n const errorMessage = document.createElement('div');\n errorMessage.className = 'search-error-message text-red-500 text-sm mt-1';\n errorMessage.textContent = error instanceof Error ? error.message : 'An error occurred during search';\n searchInput.parentElement?.appendChild(errorMessage);\n\n // Remove error message after 3 seconds\n setTimeout(() => {\n errorMessage.remove();\n }, 3000);\n } finally {\n // Remove loading indicator\n const loadingIndicator = searchInput.parentElement?.querySelector('.search-loading-indicator');\n if (loadingIndicator) {\n loadingIndicator.remove();\n }\n }\n }, 500); // Increased debounce time to 500ms\n },\n\n highlightMatchingPackages(userId: string, searchTerm: string) {\n if (!userId || !searchTerm) return;\n\n const tableBody = document.getElementById(`${userId}-packages-tbody`);\n if (!tableBody) {\n console.warn(`Cannot find packages table body for user ${userId}`);\n return;\n }\n\n tableBody.style.display = 'table-row-group';\n\n const existingNoMatchesRow = tableBody.querySelector('.no-matches-row');\n if (existingNoMatchesRow) {\n existingNoMatchesRow.remove();\n }\n\n const packageRows = tableBody.querySelectorAll('tr:not(.see-more-row):not(.no-matches-row)');\n let matchCount = 0;\n\n packageRows.forEach(row => {\n let rowHasMatch = false;\n\n row.querySelectorAll('td').forEach(cell => {\n const content = cell.textContent || '';\n\n if (content.toLowerCase().includes(searchTerm.toLowerCase())) {\n rowHasMatch = true;\n matchCount++;\n\n if (!cell.hasAttribute('data-original')) {\n cell.setAttribute('data-original', content);\n }\n\n const highlightedContent = content.replace(\n new RegExp(this.escapeHtml(searchTerm).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'gi'),\n (match: string) => `${this.escapeHtml(match)}`\n );\n\n cell.innerHTML = highlightedContent;\n }\n });\n\n if (rowHasMatch) {\n (row as HTMLElement).style.display = 'table-row';\n row.classList.add('flash-highlight');\n } else {\n (row as HTMLElement).style.display = 'none';\n }\n });\n\n if (matchCount === 0) {\n const noMatchesRow = document.createElement('tr');\n noMatchesRow.className = 'no-matches-row';\n noMatchesRow.innerHTML = `\n \n No matches found for \"${this.escapeHtml(searchTerm)}\" in this user's packages.\n \n `;\n tableBody.appendChild(noMatchesRow);\n }\n },\n\n async searchPackages(searchTerm: string): Promise> {\n return new Promise(async (resolve, reject) => {\n try {\n\n // Check if we have cached results for this exact search term\n if (this.searchCache.has(searchTerm)) {\n const cachedData = this.searchCache.get(searchTerm);\n if (!cachedData) {\n reject(new Error('Cached data is undefined'));\n return;\n }\n\n // If we have cached results, process them directly without showing loading indicators\n this.processSearchResults(cachedData, searchTerm);\n\n // Return the cached data\n resolve(cachedData.map((p: any) => ({\n user_email: p.user_email,\n package: {\n name: p.name,\n version: p.version || 'Unknown',\n project: p.project || 'Unknown',\n package_manager: p.package_manager || 'Unknown',\n install_path: p.install_path || 'Unknown',\n installed_at: p.installed_at // Send raw timestamp\n }\n })));\n return;\n }\n\n // Make API request without showing any loading skeletons\n const response = await fetch(`api/search-packages/?q=${encodeURIComponent(searchTerm)}`);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data = await response.json();\n\n // Cache the results\n this.searchCache.set(searchTerm, data);\n\n // Process the search results\n this.processSearchResults(data, searchTerm);\n\n resolve(data.map((p: any) => ({\n user_email: p.user_email,\n package: {\n name: p.name,\n version: p.version || 'Unknown',\n project: p.project || 'Unknown',\n package_manager: p.package_manager || 'Unknown',\n install_path: p.install_path || 'Unknown',\n installed_at: p.installed_at // Send raw timestamp\n }\n })));\n } catch (error) {\n console.error('Error searching packages:', error);\n\n this.users.forEach(user => {\n const userRow = document.querySelector(`[data-user-id=\"${user.id}\"]`);\n if (userRow) {\n userRow.classList.remove('loading');\n }\n\n const tableBody = document.getElementById(`${user.id}-packages-tbody`);\n if (tableBody) {\n const originalContent = tableBody.getAttribute('data-original-content');\n if (originalContent) {\n tableBody.innerHTML = originalContent;\n tableBody.removeAttribute('data-original-content');\n }\n }\n });\n\n reject(error);\n }\n });\n },\n\n handleFirewallUpdate(data: FirewallStatusResponse) {\n if (!data) return;\n\n if (data.firewall_status) {\n this.isProtectionEnabled = data.firewall_status.protection_enabled;\n this.isFullyConfigured = data.firewall_status.is_fully_configured;\n }\n\n if (data.last_updated_time) {\n this.lastUpdated = data.last_updated_time;\n }\n\n if (data.users) {\n const users: FirewallUser[] = data.users.map((user: any) => {\n const existingUser = this.users.find(u => u.email === user.email);\n return {\n id: user.email,\n email: user.email,\n first_name: user.first_name || '',\n last_name: user.last_name || '',\n username: user.email.split('@')[0],\n is_protected: user.is_protected,\n package_managers: user.package_managers || [],\n package_manager_versions: user.package_manager_versions || {},\n last_seen: user.last_seen || 'Never',\n packages: existingUser ? [...existingUser.packages].sort((a, b) => new Date(b.installed_at).getTime() - new Date(a.installed_at).getTime()) : [],\n total_packages: user.total_count || 0,\n showAllPackages: existingUser ? existingUser.showAllPackages : false,\n hasMorePackages: user.total_count > 0,\n isLoadingPackages: false\n };\n });\n\n this.users = users;\n }\n\n this.isLoading = false;\n this.hasData = true;\n\n // Add logic to process package installation events\n for (const event of this.updates) {\n // Check if this is a package installation event by looking for patterns in the message\n if (event.type === 'success' &&\n event.message.includes('installed') &&\n event.message.includes('using') &&\n (event.message.includes('and') || event.message.includes('other package'))) {\n\n event.expandable = true;\n event.expanded = false;\n\n // Try to extract package information from the raw event data\n if (event.raw_event?.data?.packages) {\n event.packages = Array.isArray(event.raw_event.data.packages)\n ? event.raw_event.data.packages\n : [event.raw_event.data.packages];\n }\n // If packages aren't explicitly provided, try to extract from the event data\n else if (event.raw_event?.data?.package_name && event.raw_event?.data?.package_version) {\n // Create a basic package entry from the available data\n const pkg: FirewallPackage = {\n name: event.raw_event.data.package_name,\n version: event.raw_event.data.package_version,\n package_manager: event.raw_event.data.package_manager || '',\n project: event.raw_event.data.project || '',\n install_path: event.raw_event.data.install_path || '',\n installed_at: event.timestamp\n };\n\n event.packages = [pkg];\n\n // Try to parse additional packages mentioned in the message\n if (event.message.includes('and')) {\n // This is a rough heuristic to extract the number of other packages\n const match = event.message.match(/and\\s+(\\d+)\\s+other\\s+packages?/i);\n if (match && match[1]) {\n const otherPackagesCount = parseInt(match[1], 10);\n // If there are other packages mentioned but not detailed, add placeholders\n if (otherPackagesCount > 0 && event.raw_event?.data?.other_packages) {\n event.packages = [...event.packages, ...event.raw_event.data.other_packages];\n }\n }\n }\n }\n // If we still don't have package info, try to extract from the message\n else if (event.message.includes('@')) {\n const packageMatch = event.message.match(/([^@\\s]+)@([^\\s]+)/);\n if (packageMatch) {\n const [, name, version] = packageMatch;\n const pkg: FirewallPackage = {\n name,\n version,\n package_manager: event.message.match(/using\\s+([^\\s]+)/)?.[1] || '',\n project: event.message.match(/project\\s+([^\\s]+)/)?.[1] || '',\n install_path: '',\n installed_at: event.timestamp\n };\n event.packages = [pkg];\n }\n }\n }\n }\n },\n\n processBlockedPackages(blockedPackages: Record[]) {\n if (!blockedPackages || !Array.isArray(blockedPackages)) return;\n\n this.summaryData.blocked_packages = blockedPackages.length;\n\n blockedPackages.forEach(pkg => {\n const userEmail = pkg.user_email || pkg.context?.runtime?.user?.name || pkg.user?.email;\n if (!userEmail) return;\n\n const user = this.users.find(u => u.email === userEmail);\n if (!user) return;\n\n // Use normalized package data from the backend if available\n if (pkg.package) {\n const blockedPackage = {\n name: pkg.package.name || 'Unknown',\n version: pkg.package.version || 'Unknown',\n project: pkg.package.project || pkg.context?.project?.id || 'Unknown',\n package_manager: pkg.package.package_manager || 'Unknown',\n install_path: pkg.package.install_path || 'Unknown',\n installed_at: pkg.installed_at,\n blocked: true\n };\n\n const existingIndex = user.packages.findIndex(p =>\n p.name === blockedPackage.name &&\n p.version === blockedPackage.version &&\n p.project === blockedPackage.project\n );\n\n if (existingIndex === -1) {\n user.packages.push(blockedPackage);\n user.total_packages++;\n } else {\n user.packages[existingIndex] = blockedPackage;\n }\n return;\n }\n\n // Fallback to legacy extraction logic\n // Extract package info from raw command if available\n let packageNameFromCommand = '';\n let packageVersionFromCommand = '';\n\n // Try to extract package from raw command\n if (pkg.raw_command && Array.isArray(pkg.raw_command) && pkg.raw_command.length > 0) {\n // Extract package info from command like \"safety install package==version\"\n const commandStr = pkg.raw_command.join(' ');\n const packagePattern = /\\s([\\w\\-_.]+)==([\\w\\-_.]+)/g;\n const match = packagePattern.exec(commandStr);\n\n if (match && match.length >= 3) {\n packageNameFromCommand = match[1];\n packageVersionFromCommand = match[2];\n } else {\n // Try to find just the package name\n const packageArgIndex = pkg.raw_command.findIndex((arg: string, i: number) =>\n i > 0 &&\n arg &&\n !arg.startsWith('-') &&\n (arg.includes('.') || arg.match(/^[\\w\\-_]+$/))\n );\n\n if (packageArgIndex > 0) {\n const pkgArg = pkg.raw_command[packageArgIndex];\n if (pkgArg.includes('==')) {\n const parts = pkgArg.split('==');\n packageNameFromCommand = parts[0];\n packageVersionFromCommand = parts[1];\n } else {\n packageNameFromCommand = pkgArg;\n }\n }\n }\n }\n\n const blockedPackage = {\n name: pkg.package_name || pkg.package?.name || pkg.name || pkg.dependency?.name || pkg.dependency?.package_name || packageNameFromCommand || 'Unknown',\n version: pkg.version || pkg.package?.version || pkg.package?.spec || pkg.dependency?.version || pkg.dependency?.spec || packageVersionFromCommand || pkg.raw_command?.[2]?.split('==')?.[1] || 'Unknown',\n project: pkg.project || pkg.context?.project?.id || pkg.context?.project?.name || 'Unknown',\n package_manager: pkg.ecosystem || pkg.package_manager || pkg.tool || pkg.package?.package_manager || pkg.dependency?.package_manager || pkg.manager || pkg.context?.runtime?.package_manager || 'Unknown',\n install_path: pkg.install_path || 'Unknown',\n installed_at: pkg.installed_at,\n blocked: true\n };\n\n const existingIndex = user.packages.findIndex(p =>\n p.name === blockedPackage.name &&\n p.version === blockedPackage.version &&\n p.project === blockedPackage.project\n );\n\n if (existingIndex === -1) {\n user.packages.push(blockedPackage);\n user.total_packages++;\n } else {\n user.packages[existingIndex] = blockedPackage;\n }\n });\n\n // Sort packages by installation date after processing all blocked packages\n this.users.forEach(user => {\n user.packages.sort((a, b) => new Date(b.installed_at).getTime() - new Date(a.installed_at).getTime());\n });\n },\n\n processInstalledPackages(installedPackages: Record[]) {\n if (!installedPackages || !Array.isArray(installedPackages)) return;\n\n this.summaryData.analyzed_packages = installedPackages.length;\n\n installedPackages.forEach(pkg => {\n const userEmail = pkg.user_email || pkg.context?.runtime?.user?.name;\n if (!userEmail) return;\n\n const user = this.users.find(u => u.email === userEmail);\n if (!user) return;\n\n // Use normalized package data from the backend if available\n if (pkg.package) {\n const installedPackage = {\n name: pkg.package.name || 'Unknown',\n version: pkg.package.version || 'Unknown',\n project: pkg.package.project || pkg.context?.project?.id || 'Unknown',\n package_manager: pkg.package.package_manager || 'Unknown',\n install_path: pkg.install_path || pkg.package.install_path || 'Unknown',\n installed_at: pkg.installed_at || pkg.event_time || 'Never'\n };\n\n const existingIndex = user.packages.findIndex(p =>\n p.name === installedPackage.name &&\n p.version === installedPackage.version &&\n p.project === installedPackage.project\n );\n\n if (existingIndex === -1) {\n user.packages.push(installedPackage);\n user.total_packages++;\n } else {\n user.packages[existingIndex] = installedPackage;\n }\n return;\n }\n\n // Fallback to legacy extraction logic\n const installedPackage = {\n name: pkg.package_name || pkg.name,\n version: pkg.version || 'Unknown',\n project: pkg.context?.project?.id || pkg.project || 'Unknown',\n package_manager: pkg.ecosystem || pkg.package_manager || 'Unknown',\n install_path: pkg.install_path || 'Unknown',\n installed_at: pkg.installed_at || pkg.event_time || 'Never'\n };\n\n const existingIndex = user.packages.findIndex(p =>\n p.name === installedPackage.name &&\n p.version === installedPackage.version &&\n p.project === installedPackage.project\n );\n\n if (existingIndex === -1) {\n user.packages.push(installedPackage);\n user.total_packages++;\n } else {\n user.packages[existingIndex] = installedPackage;\n }\n });\n\n // Sort packages by installation date after processing all installed packages\n this.users.forEach(user => {\n user.packages.sort((a, b) => new Date(b.installed_at).getTime() - new Date(a.installed_at).getTime());\n });\n },\n\n renderPackagesTable(user: FirewallUser) {\n const truncatePath = (path: string) => {\n const maxPathLength = 30;\n if (path.length > maxPathLength) {\n const parts = path.split('/');\n const fileName = parts.pop();\n if (!fileName) return path;\n const remainingPath = parts.join('/');\n return `${remainingPath.slice(0, maxPathLength - fileName.length - 3)}.../${fileName}`;\n }\n return path;\n };\n\n const truncateProject = (project: string) => {\n const maxLength = 20;\n if (project.length > maxLength) {\n return `${project.slice(0, maxLength)}...`;\n }\n return project;\n };\n\n const packages = user.packages || [];\n const sortedPackages = [...packages].sort((a, b) => new Date(b.installed_at).getTime() - new Date(a.installed_at).getTime());\n const packagesToShow = user.showAllPackages ? sortedPackages : sortedPackages.slice(0, 5);\n\n let packageRows = packagesToShow.map(pkg => `\n \n ${this.escapeHtml(pkg.name)}\n ${this.escapeHtml(pkg.version)}\n ${this.escapeHtml(truncateProject(pkg.project || 'N/A'))}\n ${this.escapeHtml(pkg.package_manager)}\n ${this.escapeHtml(truncatePath(pkg.install_path))}\n ${this.getRelativeTime(pkg.installed_at)}\n \n `).join('');\n\n // Add \"Load more\" row if there are more packages and not showing all\n const loadMoreRow = !user.showAllPackages && sortedPackages.length > 5 ? `\n \n \n \n \n \n ` : '';\n\n return packageRows + loadMoreRow;\n },\n\n resetHighlights() {\n document.querySelectorAll('.search-highlight').forEach(highlighted => {\n const parent = highlighted.parentElement;\n if (parent && parent.hasAttribute('data-original')) {\n parent.textContent = parent.getAttribute('data-original') || '';\n parent.removeAttribute('data-original');\n }\n });\n\n document.querySelectorAll('.no-matches-row').forEach(row => {\n row.remove();\n });\n\n document.querySelectorAll('tr').forEach(row => {\n if (!row.classList.contains('see-more-row')) {\n (row as HTMLElement).style.display = '';\n }\n });\n\n document.querySelectorAll('.flash-highlight').forEach(row => {\n row.classList.remove('flash-highlight');\n });\n },\n\n notifyNewEvent() {\n // No animations needed\n },\n\n async loadUserPackages(userEmail: string) {\n try {\n const userIndex = this.users.findIndex(u => u.email === userEmail);\n if (userIndex === -1) {\n console.error(`User with email ${userEmail} not found`);\n return;\n }\n\n const user = this.users[userIndex];\n const userId = user.id;\n user.isLoadingPackages = true;\n\n const response = await fetch(`api/user-packages/?email=${encodeURIComponent(userEmail)}`);\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const data = await response.json();\n\n // Use the standardized data from the serializer without fallbacks\n const updatedUser = {\n ...user,\n packages: data.packages || [],\n total_packages: data.total_count || 0,\n hasMorePackages: data.total_count > (data.packages?.length || 0),\n isLoadingPackages: false\n };\n\n this.users[userIndex] = updatedUser;\n\n const tableBody = document.getElementById(`${userId}-packages-tbody`);\n if (tableBody) {\n tableBody.innerHTML = this.renderPackagesTable(updatedUser);\n\n tableBody.classList.add('animate-fade-in');\n setTimeout(() => {\n tableBody.classList.remove('animate-fade-in');\n }, 500);\n }\n\n } catch (error: any) {\n console.error(`Error loading packages for user ${userEmail}:`, error);\n\n const userIndex = this.users.findIndex(u => u.email === userEmail);\n if (userIndex === -1) return;\n\n const user = this.users[userIndex];\n const userId = user.id;\n\n this.users[userIndex] = {\n ...user,\n isLoadingPackages: false\n };\n\n const tableBody = document.getElementById(`${userId}-packages-tbody`);\n if (tableBody) {\n tableBody.innerHTML = `\n \n \n
\n \n \n \n Failed to load packages: ${this.escapeHtml(error.message || 'Unknown error')}\n \n \n
\n \n \n `;\n }\n }\n },\n\n async loadMorePackages(userId: string) {\n const userIndex = this.users.findIndex(u => u.id === userId);\n if (userIndex === -1) return;\n\n const user = this.users[userIndex];\n user.showAllPackages = true;\n\n // Update the table with all packages\n const tableBody = document.getElementById(`${userId}-packages-tbody`);\n if (tableBody) {\n tableBody.innerHTML = this.renderPackagesTable(user);\n }\n },\n\n toggleEventDetails(eventIndex: number) {\n if (eventIndex < 0 || eventIndex >= this.updates.length) return;\n\n const event = this.updates[eventIndex];\n if (!event) return;\n\n if (this.expandedEvents.has(eventIndex)) {\n this.expandedEvents.delete(eventIndex);\n event.expanded = false;\n } else {\n this.expandedEvents.add(eventIndex);\n event.expanded = true;\n\n if (event.expandable &&\n (!event.packages || event.packages.length === 0) &&\n event.raw_event?.data?.packages) {\n event.packages = event.raw_event.data.packages;\n }\n }\n\n this.$nextTick(() => {\n // Adjust the height of the events container after expanding/collapsing\n const updatesContainer = document.querySelector('#updates-container');\n if (updatesContainer) {\n const event = new CustomEvent('content-updated');\n updatesContainer.dispatchEvent(event);\n }\n });\n },\n\n $destroy() {\n // Cleanup code when the component is destroyed\n if (this.timeUpdateInterval) {\n clearInterval(this.timeUpdateInterval);\n }\n },\n\n escapeHtml(unsafe: string): string {\n return unsafe\n .replace(/&/g, \"&\")\n .replace(//g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n }\n };\n}\n\nexport const firewallIndicator = () => ({\n isEnabled: false,\n isProtected: false,\n isLoading: true,\n\n async init() {\n try {\n const response = await fetch('/firewall/api/user-status/');\n if (!response.ok) {\n throw new Error('Failed to fetch firewall status');\n }\n const data = await response.json();\n this.isEnabled = data.is_enabled;\n this.isProtected = data.is_protected;\n } catch (error) {\n console.error('Error fetching firewall status:', error);\n this.isEnabled = false;\n this.isProtected = false;\n } finally {\n this.isLoading = false;\n }\n }\n});\n","import { FirewallIndicatorState } from '../types';\n\nexport default function FirewallIndicator() {\n return {\n init() {\n this.fetchStatus();\n // Poll for status updates every 30 seconds\n setInterval(() => this.fetchStatus(), 30000);\n\n // Listen for refresh events\n document.addEventListener('firewall:refresh-events', () => {\n this.fetchStatus();\n });\n },\n\n state: {\n isProtected: false,\n isLoading: true,\n error: null,\n lastInstallation: null,\n showTooltip: false,\n lastStatus: null\n } as FirewallIndicatorState,\n\n async fetchStatus() {\n try {\n if (this.state.lastStatus === null) {\n this.state.isLoading = true;\n }\n this.state.error = null;\n\n const response = await fetch('/firewall/api/user-status/');\n if (!response.ok) {\n throw new Error('Failed to fetch firewall status');\n }\n\n const data = await response.json();\n const newStatus = data.is_protected;\n\n if (this.state.lastStatus !== newStatus) {\n this.state.isProtected = newStatus;\n this.state.lastStatus = newStatus;\n }\n\n this.state.lastInstallation = data.last_installation;\n } catch (error) {\n this.state.error = error instanceof Error ? error.message : 'An error occurred';\n } finally {\n this.state.isLoading = false;\n }\n },\n\n get statusText() {\n if (this.state.error) {\n return 'Error';\n }\n return this.state.isProtected ? 'Protected by Firewall' : 'Firewall Not Active';\n },\n\n get statusClass() {\n if (this.state.error) {\n return 'text-[#ef4444]';\n }\n return this.state.isProtected ? 'text-[#15803d]' : 'text-[#b45309]';\n },\n\n getRelativeTime(dateString: string): string {\n const date = new Date(dateString);\n const now = new Date();\n const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);\n\n if (diffInSeconds < 60) {\n return 'just now';\n }\n\n const diffInMinutes = Math.floor(diffInSeconds / 60);\n if (diffInMinutes < 60) {\n return `${diffInMinutes} minute${diffInMinutes === 1 ? '' : 's'} ago`;\n }\n\n const diffInHours = Math.floor(diffInMinutes / 60);\n if (diffInHours < 24) {\n return `${diffInHours} hour${diffInHours === 1 ? '' : 's'} ago`;\n }\n\n const diffInDays = Math.floor(diffInHours / 24);\n if (diffInDays < 30) {\n return `${diffInDays} day${diffInDays === 1 ? '' : 's'} ago`;\n }\n\n const diffInMonths = Math.floor(diffInDays / 30);\n if (diffInMonths < 12) {\n return `${diffInMonths} month${diffInMonths === 1 ? '' : 's'} ago`;\n }\n\n const diffInYears = Math.floor(diffInMonths / 12);\n return `${diffInYears} year${diffInYears === 1 ? '' : 's'} ago`;\n },\n\n get tooltipText() {\n if (this.state.error) {\n return 'Error loading Firewall status';\n }\n if (this.state.isProtected) {\n if (this.state.lastInstallation) {\n return `Last installation: ${this.getRelativeTime(this.state.lastInstallation)}`;\n }\n return 'Firewall is protecting your packages';\n }\n return 'Run \\'safety init\\' to enable Firewall protection';\n },\n\n showTooltip() {\n this.state.showTooltip = true;\n },\n\n hideTooltip() {\n this.state.showTooltip = false;\n },\n\n handleClick() {\n if (this.state.isProtected) {\n window.location.href = '/firewall';\n } else {\n window.location.href = '/get-started';\n }\n }\n };\n}\n","export const toggleTheme = (e: MouseEvent): void => {\n e.preventDefault();\n e.stopPropagation();\n // if set via local storage previously\n if (localStorage.theme) {\n if (localStorage.theme === \"light\") {\n document.documentElement.classList.add(\"dark\");\n localStorage.setItem(\"theme\", \"dark\");\n } else {\n document.documentElement.classList.remove(\"dark\");\n localStorage.setItem(\"theme\", \"light\");\n }\n // if NOT set via local storage previously\n } else {\n document.documentElement.classList.add(\"dark\");\n localStorage.setItem(\"theme\", \"dark\");\n }\n}\n\nexport function setupTheme(element: HTMLButtonElement | null): void {\n if (!element) {\n return;\n }\n element.addEventListener('click', (e: MouseEvent) => toggleTheme(e));\n}\n\nexport function loadTheme(): void {\n if (localStorage.theme === 'dark') {\n document.documentElement.classList.add('dark')\n } else {\n document.documentElement.classList.remove('dark')\n }\n}\n","import { Repository } from \"../utils\";\nimport { InviteCreateRequest, Role } from \"./main\";\n\nexport class InviteRepository extends Repository {\n apiUrl = '/api/v1/invites/';\n invitee_email = '';\n invitee_role = 'member';\n invites : InviteCreateRequest[] = [];\n\n constructor(public organizationId: number){\n super()\n this.organizationId = organizationId\n }\n\n addInvite(availableSeats: number | null) {\n\n if (!availableSeats || availableSeats <= 0) {\n return { success: false, message: 'You have reached the maximum number of invites', type: 'error' };\n }\n\n if (!this.invitee_email || !/\\S+@\\S+\\.\\S+/.test(this.invitee_email)) {\n return { success: false, message: 'A valid email is required', type: 'error' };\n }\n\n if (this.invites.some(invite => invite.invitee_email === this.invitee_email)) {\n return { success: false, message: 'Email already exists', type: 'error' };\n }\n\n this.invites.push({invitee_email: this.invitee_email, invitee_role: this.invitee_role as Role});\n this.invitee_email = '';\n this.invitee_role = 'member';\n\n return { success: true };\n}\n\n\n async getByOrganization(): Promise {\n const response = await fetch(this.apiUrl + \"?object_type=organization&object_id=\" + this.organizationId);\n return response.status === 200 ? await response.json().then(data => data):[];\n }\n\n async createInvites(csrfToken: string): Promise {\n let objectType = \"organization\";\n\n const response = await fetch(\n this.apiUrl + \"?object_type=\" + objectType + \"&object_id=\" + this.organizationId,\n {\n method: \"POST\",\n body: JSON.stringify(this.invites),\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n\n const responseData = await response.json();\n\n const successfulInvites = responseData.successful_invites || [];\n const failedInvites = responseData.failed_invites || [];\n\n // Remove the successfully sent invites\n this.invites = this.invites.filter(invite =>\n !successfulInvites.includes(invite.invitee_email)\n );\n\n // Only keep invites that failed to send\n this.invites = this.invites.filter(invite =>\n failedInvites.some((fail: { email: string; reason: string }) => fail.email === invite.invitee_email)\n );\n\n return responseData; // Return the parsed data\n }\n\n\n\n async cancelInvite(inviteId: number, csrfToken: string): Promise {\n let objectType = \"organization\";\n\n return await fetch(\n this.apiUrl + inviteId + \"/cancel/\" + \"?object_type=\" + objectType + \"&object_id=\" + this.organizationId,\n {\n method: \"PUT\",\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n\n\n async resendInvite(inviteId: number, csrfToken: string): Promise {\n let objectType = \"organization\";\n\n return await fetch(\n this.apiUrl + inviteId + \"/resend/\" + \"?object_type=\" + objectType + \"&object_id=\" + this.organizationId,\n {\n method: \"PUT\",\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n}\nexport class UserRepository extends Repository {\n apiUrl = '/api/v1/members/';\n\n async getByOrganization(organizationId: number, includeInvites: boolean = true): Promise {\n const response = await fetch(this.apiUrl + \"?object_type=organization&object_id=\" + organizationId);\n let users = response.status === 200 ? await response.json().then(data => data):[];\n\n if (includeInvites) {\n const invites = await new InviteRepository(organizationId).getByOrganization();\n\n const invitesAsPotentialUsers = invites.map((invite: any) => ({\n id: 'invite-' + invite.id,\n name: invite.invitee_email,\n picture: '/static/img/invite.svg',\n email: invite.invitee_email,\n role: `Invited as a${invite.invitee_role === \"admin\" ? 'n' : ''} ${invite.invitee_role.charAt(0).toUpperCase() + invite.invitee_role.slice(1)}`,\n is_org_admin: false,\n is_active: false,\n email_verified: false,\n status: {\n 'invite_status': (invite.expires_in.includes('ago') ? 'expired' : (invite.status || 'pending')),\n 'expires_in': invite.expires_in,\n }\n }));\n users = [...users, ...invitesAsPotentialUsers];\n }\n\n return users;\n }\n\n async activateMember(objectType: string, objectId: number, memberId: number, csrfToken: string): Promise {\n return await fetch(\n this.apiUrl + memberId + \"/activate/\" + \"?object_type=\" + objectType + \"&object_id=\" + objectId,\n {\n method: \"PUT\",\n body: JSON.stringify({userId: memberId}),\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n\n async getByProject(projectId: number): Promise {\n const response = await fetch(this.apiUrl + \"?object_type=project&object_id=\" + projectId);\n return response.status === 200 ? await response.json().then(data => data):[];\n }\n\n async addMember(objectType: string, objectId: number, userId: number, csrfToken: string): Promise {\n return await fetch(\n this.apiUrl + \"?object_type=\" + objectType + \"&object_id=\" + objectId,\n {\n method: \"POST\",\n body: JSON.stringify({new_user_id: userId}),\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n\n async removeMember(objectType: string, objectId: number, memberId: number, csrfToken: string): Promise {\n return await fetch(\n this.apiUrl + memberId + \"?object_type=\" + objectType + \"&object_id=\" + objectId,\n {\n method: \"DELETE\",\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n\n async changeRole(objectType: string, objectId: number, memberId: number, csrfToken: string, role: string): Promise {\n return await fetch(\n this.apiUrl + memberId + \"/change_role/\" + \"?object_type=\" + objectType + \"&object_id=\" + objectId,\n {\n method: \"PUT\",\n body: JSON.stringify({role: role}),\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n}\n","import { Repository } from \"../../utils\";\n\nexport class RiskScoreInputRepository extends Repository {\n apiUrl = '/api/v1/risk_score_inputs/';\n\n async createInput(newInput: object, csrfToken: string): Promise {\n return await fetch(\n this.apiUrl,\n {\n method: \"POST\",\n body: JSON.stringify(newInput),\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n\n async updateLevel(id: number, newLevelId: number, csrfToken: string): Promise {\n return await fetch(\n this.apiUrl + id + \"/\",\n {\n method: \"PATCH\",\n body: JSON.stringify({level: newLevelId}),\n headers: {\n \"X-CSRFToken\": csrfToken,\n \"Content-Type\": \"application/json\"\n }\n }\n );\n }\n}\n\nexport class RiskScoreInputLevelRepository extends Repository {\n apiUrl = '/api/v1/risk_score_input_levels/';\n\n async getByType(type: string): Promise {\n const response = await fetch(this.apiUrl + \"?type=\" + type);\n return response.status === 200 ? await response.json().then(data => data):[];\n }\n}\n","import \"vite/modulepreload-polyfill\";\nimport Alpine from \"alpinejs\";\nimport \"../css/main.css\";\nimport \"flatpickr/dist/flatpickr.css\";\nimport * as Sentry from \"@sentry/browser\";\n\n// Import Alpine.js plugins\nimport focus from \"@alpinejs/focus\";\n// @ts-ignore - No type definitions available for @alpinejs/ui\nimport ui from \"@alpinejs/ui\";\n\nimport { FindingTable } from \"../ts/findings/main\";\nimport { ProjectTable } from \"../ts/projects/main\";\nimport { ScanTable } from \"./scans/main\";\nimport { PackageTable } from \"./projects/packages/main\";\nimport { FilterTable, IndividualFilter } from \"./filters/main\";\nimport { LanguageSelector } from \"./languages/main\";\nimport { ButtonsTab } from \"./tab/main\";\n\nimport { PlanForm } from \"./accounts/main\";\n\nimport { PackageRepository } from \"./projects/packages/repository\";\nimport {\n FindingsTableItem,\n LifeCycleStatusIndividual,\n PackageTableData,\n ProjectTableData,\n ScanTableData,\n ScoreInividual,\n UserTableData,\n InviteToSendData,\n VerificationEmailData,\n} from \"../models/tables\";\nimport { ScanRepository } from \"./scans/repository\";\nimport { FindingRepository } from \"./findings/repository\";\n\nimport { FilterData } from \"../models/filters\";\nimport { capitalize, displayDate, getBadgeColor, getLabel, getLevelColor, getStatusIcon, labelColor } from \"./utils\";\nimport { storeFilterData } from './constants';\n\nimport { ProjectRepository } from \"./projects/repository\";\nimport { policiesTab, policyWizard, excludePatternsManager, ignoreSeveritiesManager, ignoredVulnerabilitiesFormsetManager } from \"./policies/main\";\nimport { fixVulnerabilityTab } from \"./findings/main\";\nimport { Notifications } from \"./toast/main\";\nimport { Modal } from \"./modals/main\";\n\nimport onboarding from './onboarding/main';\nimport { connectToChannel } from './websockets/ws';\n\n// Import firewall component without unused interfaces\nimport { firewallComponent } from './firewall/main';\n\nimport FirewallIndicator from './firewall/components/FirewallIndicator';\n\n// Add global declarations\ndeclare global {\n interface Window {\n platformEnabled: boolean;\n Sentry: typeof Sentry;\n Alpine: typeof Alpine;\n organization?: {\n firewall_enabled: boolean;\n };\n }\n}\n\nif (import.meta.env.PROD) {\n Sentry.init({\n dsn: \"https://70fdbbfba9c7f8530efcfa0113b06717@o136163.ingest.us.sentry.io/4508699562344448\",\n integrations: [\n Sentry.browserTracingIntegration(),\n ],\n tracesSampleRate: 1.0,\n replaysOnErrorSampleRate: 1.0\n });\n\n // Add global error handlers\n window.addEventListener('error', (event) => {\n Sentry.captureException(event.error);\n });\n\n window.addEventListener('unhandledrejection', (event) => {\n Sentry.captureException(event.reason);\n });\n} else {\n console.log(\"Development Mode: Sentry initialization skipped.\");\n}\n\nconsole.log(`\n ███████╗ █████╗ ███████╗███████╗████████╗██╗ ██╗\n ██╔════╝██╔══██╗██╔════╝██╔════╝╚══██╔══╝╚██╗ ██╔╝\n ███████╗███████║█████╗ █████╗ ██║ ╚████╔╝\n ╚════██║██╔══██║██╔══╝ ██╔══╝ ██║ ╚██╔╝\n ███████║██║ ██║██║ ███████╗ ██║ ██║\n ╚══════╝╚═╝ ╚═╝╚═╝ ╚══════╝ ╚═╝ ╚═╝\n\n 🚀 We're hiring! Join our team: https://jobs.ashbyhq.com/safety\n`);\n\nAlpine.plugin(focus);\nAlpine.plugin(ui);\n\n// Register Alpine.js global objects\nwindow.Alpine = Alpine;\n\nAlpine.store(\"theme\", {\n darkMode: localStorage.getItem('theme') === 'dark',\n toggle() {\n this.darkMode = !this.darkMode;\n }\n} as any);\n\nAlpine.store(\"userMenuOptions\", {\n items: [\n // { title: \"Your Profile\", url: \"/profile\" },\n { title: \"Sign Out\", url: \"/logout\" },\n ],\n});\n\nAlpine.store(\"mainMenuHeaderOptions\", {\n items: [\n { title: window.platformEnabled ? \"Projects\" : \"Dashboard\", url: \"/\" },\n {\n title: \"Firewall\",\n url: \"/firewall\",\n showIf: () => window.organization?.firewall_enabled\n },\n { title: \"Organization\", url: \"/organization\" },\n ]\n});\n\nAlpine.store(\"organizationMenuOptions\", {\n items: [\n { title: \"Team\", url: \"/organization/team\" },\n { title: \"Policies\", url: \"/organization/policies\", platformEnabledOnly: true },\n { title: \"API Keys\", url: \"/organization/apikeys\" },\n { title: \"Settings\", url: \"/organization/settings\" },\n { title: \"Billing\", url: \"/organization/plan\" },\n { title: \"Usage\", url: \"/organization/usage\" },\n ],\n});\n\nAlpine.store(\"lifeCycleStages\", {\n items: [\n {\n name: \"development\", title: \"Development\", shortTitle: \"Dev\", cta: \"Configure development scanning\",\n description: \"The project is in its development phase. At this stage, features are being built and the structure of the project is evolving. The system is not ready for live usage, and will likely have many changes, bugs, and enhancements to be addressed.\"\n },\n {\n name: \"cicd\", title: \"CI/CD\", shortTitle: \"CI/CD\", cta: \"Configure ci/cd security\",\n description: \"Is a set of practices that aims to automate the software development and deployment processes.\"\n },\n {\n name: \"production\", title: \"Production\", shortTitle: \"Prod\", cta: \"Configure production security\",\n description: \"The system is in a production environment. It's being used actively for its intended purpose and is maintained with regular updates and patches to ensure stability, performance, and security. At this stage, changes are usually limited to maintenance, minor updates, and responding to any new issues that arise.\"\n },\n ],\n});\n\nAlpine.store('findingsTableFilters', storeFilterData.findingsTableFilters);\nAlpine.store('projectFindingsTableFilters', storeFilterData.projectFindingsTableFilters);\nAlpine.store('scansTableFilters', storeFilterData.scansTableFilters);\nAlpine.store('packagesTableFilters', storeFilterData.packagesTableFilters);\nAlpine.store('projectScansTableFilters', storeFilterData.projectScansTableFilters);\n\n\ndocument.addEventListener(\"alpine:init\", () => {\n Alpine.data(\"ProjectRepository\", (..._initialStateArgs) => {\n const result = new ProjectRepository();\n return {\n ...result,\n getAll: result.getAll,\n branches: result.branches,\n confirmName: result.confirmName,\n delete: result.delete,\n reset: result.reset\n };\n });\n Alpine.data(\"ProjectTable\", (...initialStateArgs) => {\n const data = initialStateArgs[0] as ProjectTableData[];\n const result = new ProjectTable(data);\n return {\n ...result,\n sort: result.sort,\n nextPage: result.nextPage,\n previousPage: result.previousPage,\n pagedTableData: result.pagedTableData,\n toggleAllChecked: result.toggleAllChecked,\n onChangeItemChecked: result.onChangeItemChecked,\n loadData: result.loadData,\n };\n });\n Alpine.data(\"FindingRepository\", (..._initialStateArgs) => {\n const result = new FindingRepository();\n return {\n ...result,\n getAll: result.getAll,\n getByProject: result.getByProject,\n getByScan: result.getByScan,\n getMetaData: result.getMetaData,\n updateStatus: result.updateStatus,\n ignore: result.ignore,\n groupByPackage: result.groupByPackage.bind(result)\n };\n });\n Alpine.data(\"FindingTable\", (...initialStateArgs) => {\n const data = initialStateArgs[0] as FindingsTableItem[];\n const result = new FindingTable(data);\n return {\n ...result,\n sort: result.sort,\n filterTable: result.filterTable,\n nextPage: result.nextPage,\n previousPage: result.previousPage,\n pagedTableData: result.pagedTableData,\n allTableData: result.allTableData,\n loadData: result.loadData,\n groupFindings: result.groupFindings\n };\n });\n Alpine.data(\"ScanRepository\", (..._initialStateArgs) => {\n const result = new ScanRepository();\n return {\n ...result,\n getAll: result.getAll,\n getByProject: result.getByProject,\n getByFinding: result.getByFinding,\n };\n });\n Alpine.data('ScanTable', (...initialStateArgs) => {\n const data = initialStateArgs[0] as ScanTableData[];\n const result = new ScanTable(data);\n return {\n ...result,\n sort: result.sort,\n nextPage: result.nextPage,\n previousPage: result.previousPage,\n firstPage: result.firstPage,\n resetTableData: result.resetTableData,\n pagedTableData: result.pagedTableData,\n filterTable: result.filterTable,\n prepareDisplayedScans: result.prepareDisplayedScans,\n loadData: result.loadData,\n defaultSorting: result.defaultSorting,\n compareValues: result.compareValues,\n groupByProject: result.groupByProject,\n setIsProject: result.setIsProject,\n };\n });\n Alpine.data(\"PackageRepository\", (..._initialStateArgs) => {\n const result = new PackageRepository();\n return {\n ...result,\n getByProject: result.getByProject,\n };\n });\n Alpine.data(\"PackageTable\", (...initialStateArgs) => {\n const data = initialStateArgs[0] as PackageTableData[];\n const result = new PackageTable(data);\n return {\n ...result,\n sort: result.sort,\n filterTable: result.filterTable,\n nextPage: result.nextPage,\n previousPage: result.previousPage,\n pagedTableData: result.pagedTableData,\n searchTable: result.searchTable,\n loadData: result.loadData,\n trimPaths: result.trimPaths,\n groupedByName: result.groupedByName,\n allGroupedPackages: result.allGroupedPackages,\n groupPackagesByName: result.groupPackagesByName,\n getVersionsText: result.getVersionsText\n };\n });\n Alpine.data(\"UserRepository\", (..._initialStateArgs) => {\n const result = new UserRepository();\n return {\n ...result,\n getByProject: result.getByProject,\n getByOrganization: result.getByOrganization,\n addMember: result.addMember,\n activateMember: result.activateMember,\n removeMember: result.removeMember,\n changeRole: result.changeRole\n };\n });\n Alpine.data(\"InviteRepository\", (...initialStateArgs) => {\n const organization_id = initialStateArgs[0] as number\n const result = new InviteRepository(organization_id);\n return {\n ...result,\n getByOrganization: result.getByOrganization,\n createInvites: result.createInvites,\n cancelInvite: result.cancelInvite,\n addInvite: result.addInvite,\n resendInvite: result.resendInvite\n };\n });\n Alpine.data(\"UserTable\", (...initialStateArgs) => {\n const data = initialStateArgs[0] as UserTableData[];\n const result = new UserTable(data);\n return {\n ...result,\n nextPage: result.nextPage,\n previousPage: result.previousPage,\n pagedTableData: result.pagedTableData,\n searchTable: result.searchTable,\n loadData: result.loadData\n };\n });\n Alpine.data(\"InviteToSendTable\", (...initialStateArgs) => {\n let data = initialStateArgs[0] as InviteToSendData[];\n let result = new InviteToSendTable(data);\n\n Alpine.effect(() => {\n data = initialStateArgs[0] as InviteToSendData[];\n result = new InviteToSendTable(data);\n });\n\n return {\n ...result,\n nextPage: result.nextPage,\n previousPage: result.previousPage,\n pagedTableData: result.pagedTableData,\n };\n });\n Alpine.data(\"RiskScoreInputRepository\", (..._initialStateArgs) => {\n const result = new RiskScoreInputRepository();\n return {\n ...result,\n getByProject: result.getByProject,\n createInput: result.createInput,\n updateLevel: result.updateLevel,\n };\n });\n Alpine.data(\"RiskScoreInputLevelRepository\", (..._initialStateArgs) => {\n const result = new RiskScoreInputLevelRepository();\n return {\n ...result,\n getByType: result.getByType\n };\n });\n Alpine.data(\"TableFilter\", (...initialStateArgs) => {\n const filterData = initialStateArgs[1] as FilterData;\n const result = new FilterTable(filterData);\n return {\n ...result,\n setFilterData: result.setFilterData,\n selectOnlyOneOption: result.selectOnlyOneOption,\n clearFilters: result.clearFilters,\n };\n });\n Alpine.data(\"IndividualFilter\", (..._initialStateArgs) => {\n const result = new IndividualFilter();\n return {\n ...result,\n toggle: result.toggle,\n close: result.close,\n handleAddFilter: result.handleAddFilter,\n rangePicker: result.rangePicker,\n };\n });\n\n Alpine.data(\"LanguageSelector\", (...initialStateArgs: unknown[]) => {\n const defaultOnly: boolean = initialStateArgs[0] as boolean;\n const currentLangCode: string = initialStateArgs[1] as string;\n\n const result = new LanguageSelector(defaultOnly, currentLangCode);\n return {\n ...result,\n toggle: result.toggle,\n close: result.close,\n selectLanguage: result.selectLanguage\n }\n });\n\n Alpine.data(\"ButtonsTab\", (..._initialStateArgs) => {\n const result = new ButtonsTab();\n return {\n ...result,\n setCurrentTab: result.setCurrentTab\n }\n });\n\n Alpine.data(\"Notifications\", (..._initialStateArgs) => {\n const result = new Notifications();\n\n return {\n ...result,\n add: result.add,\n remove: result.remove\n }\n });\n\n Alpine.data(\"Modals\", (..._initialStateArgs) => {\n const result = new Modal();\n\n return {\n ...result,\n openModal: result.openModal,\n closeModal: result.closeModal,\n }\n });\n\n\n Alpine.data(\"EmailVerificationAlert\", (...initialStateArgs) => {\n /*\n * The EmailVerificationAlert data currently handles email verification alerts.\n * It follows a similar data structure to Django's messages framework,\n * which makes it well-suited for handling system-wide alerts.\n * In the future, this class could be extended to handle more types of system alerts.\n */\n\n let { userEmailVerified, userEmail, csrfToken, emailVerificationResent } = initialStateArgs[0] as VerificationEmailData;\n\n let alerts = [];\n\n if (!userEmailVerified && !emailVerificationResent) {\n const verificationMessage = `\n Your email (${userEmail}) is unverified. `;\n\n alerts.push({\n tags: \"warning\",\n message: verificationMessage,\n extra_tags: \"safe\",\n });\n }\n\n const displayMessage = (alert: {\n tags: string;\n message: string;\n extra_tags: string;\n }) => {\n // Instead of declaring a separate function that's flagged as unused,\n // we'll inline the HTML escaping logic only when needed\n return alert.extra_tags.includes('safe')\n ? alert.message\n : (() => {\n const text = document.createTextNode(alert.message);\n const div = document.createElement('div');\n div.appendChild(text);\n return div.innerHTML;\n })();\n };\n\n const sendVerificationEmail = async (): Promise => {\n await fetch('/account/resend-email-verification', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-CSRFToken': csrfToken!\n },\n body: JSON.stringify({})\n });\n window.location.reload();\n }\n\n return {\n alerts,\n displayMessage,\n sendVerificationEmail,\n }\n });\n\n // @ts-ignore\n Alpine.data(\"labelColor\", (...initialStateArgs) => {\n const label = initialStateArgs[0] as string;\n return labelColor(label)\n });\n\n // @ts-ignore\n Alpine.data(\"getLevelColor\", (...initialStateArgs) => {\n const label = initialStateArgs[0] as ScoreInividual;\n return getLevelColor(label)\n });\n\n // @ts-ignore\n Alpine.data(\"getBadgeColor\", (...initialStateArgs) => {\n const status = initialStateArgs[0] as LifeCycleStatusIndividual;\n return getBadgeColor(status)\n });\n\n // @ts-ignore\n Alpine.data(\"getStatusIcon\", (...initialStateArgs) => {\n const status = initialStateArgs[0] as LifeCycleStatusIndividual;\n return getStatusIcon(status)\n });\n\n // @ts-ignore\n Alpine.data(\"getLabel\", (...initialStateArgs) => {\n const score = initialStateArgs[0] as number;\n return getLabel(score)\n });\n\n // @ts-ignore\n Alpine.data(\"displayDate\", (...initialStateArgs) => {\n const date = initialStateArgs[0] as number;\n return displayDate(date)\n });\n\n // @ts-ignore\n Alpine.data(\"capitalize\", (...initialStateArgs) => {\n const string_ = initialStateArgs[0] as string;\n return capitalize(string_)\n });\n\n Alpine.data(\"policiesTab\", policiesTab);\n Alpine.data(\"ignoreSeveritiesManager\", ignoreSeveritiesManager);\n Alpine.data(\"ignoredVulnerabilitiesFormsetManager\", ignoredVulnerabilitiesFormsetManager);\n Alpine.data(\"WizardForm\", (...initialStateArgs) => {\n const currentStep = initialStateArgs[0] as string;\n return policyWizard(currentStep);\n });\n Alpine.data(\"excludePatternsManager\", (...initialStateArgs) => {\n const excludePatternsFieldId = initialStateArgs[0] as string;\n const defaultMaxDepth = typeof initialStateArgs[1] === 'number' ? initialStateArgs[1] : 4;\n return excludePatternsManager(excludePatternsFieldId, defaultMaxDepth);\n });\n\n Alpine.data(\"fixVulnerabilityTab\", fixVulnerabilityTab);\n\n Alpine.data(\"Tooltip\", (..._initialStateArgs) => {\n return {\n init() {\n this.initializeTooltip(this.$el, this.$el.dataset.tooltip || \"\", {\n theme: this.$el.dataset.tooltipTheme || \"light\",\n placement: this.$el.dataset.tooltipPlacement || \"top\",\n });\n },\n initializeTooltip(el: HTMLElement, content: string, options: any) {\n if (!content) return;\n\n // Set title attribute for native tooltip\n el.setAttribute(\"title\", content);\n\n // Add tooltip classes for styling\n el.classList.add(\"native-tooltip\");\n if (options.theme) {\n el.classList.add(`tooltip-theme-${options.theme}`);\n }\n if (options.placement) {\n el.classList.add(`tooltip-placement-${options.placement}`);\n }\n }\n };\n });\n Alpine.data(\"PlanForm\", (...initialStateArgs) => {\n return { planForm: new PlanForm(...(initialStateArgs as [PlanType, BillingFrequency, number, number, PlanType?]))};\n });\n Alpine.data(\"betaAccessBlock\", (..._initialStateArgs) => {\n return {\n showCTA: false,\n checkCTA() {\n const cookieItems = document.cookie ? document.cookie.split('; ') : [];\n const found = cookieItems.find(row => typeof row === 'string' && row.startsWith('beta_cta_hidden='));\n this.showCTA = !found;\n },\n hideCTA() {\n document.cookie = \"beta_cta_hidden=true; path=/; max-age=\" + (60 * 60 * 24 * 30); // 30 days\n this.showCTA = false;\n }\n }\n })\n\n Alpine.data(\"apiKeyCreator\", () => ({\n generating: false,\n createKey() {\n if (this.generating) return;\n this.generating = true;\n const url = document.getElementById('apiKeyCreator')?.getAttribute('data-create-url') || '';\n fetch(url, {\n method: 'POST',\n headers: {\n 'X-CSRFToken': (document.querySelector('[name=csrfmiddlewaretoken]') as HTMLInputElement).value,\n 'Content-Type': 'application/json'\n }\n })\n .then(response => response.json())\n .then(data => {\n if (data.status === \"success\") {\n this.$dispatch('notify', {\n content: data.message,\n type: 'success',\n displayDuration: 5000\n });\n setTimeout(() => {\n window.location.reload();\n }, 3000);\n } else {\n this.$dispatch('notify', {\n content: data.message,\n type: 'error',\n displayDuration: 5000\n });\n }\n })\n .catch(err => {\n console.error(err);\n alert(\"Error creating API key.\");\n })\n .finally(() => {\n this.generating = false;\n });\n }\n }));\n\n\n Alpine.data(\"apiKeyGenerator\", (...initialStateArgs: unknown[]) => {\n const initialKey = (initialStateArgs[0] as string) || '';\n return {\n key: initialKey,\n copied: false,\n revealed: false,\n onClick() {\n if (this.revealed) {\n // Copy the key\n this.copied = true;\n navigator.clipboard.writeText(this.key);\n setTimeout(() => { this.copied = false; }, 2000);\n } else {\n // Reveal the key first\n this.revealed = true;\n }\n }\n };\n });\n\n // Add Firewall component using the imported implementation\n Alpine.data(\"Firewall\", firewallComponent);\n\n Alpine.data(\"onboarding\", onboarding);\n\n // Register the FirewallIndicator component\n Alpine.data(\"FirewallIndicator\", FirewallIndicator);\n});\n\nAlpine.start();\n\n// Test here\nimport { loadTheme, setupTheme } from \"./theme\";\nimport { InviteRepository, UserRepository } from \"./users/repository\";\nimport { InviteToSendTable, UserTable } from \"./users/main\";\nimport { RiskScoreInputLevelRepository, RiskScoreInputRepository } from \"./projects/risk_score_inputs/repository\";\nimport { BillingFrequency, PlanType } from \"../models/components\";\n\nwindow.addEventListener(\"DOMContentLoaded\", () => {\n loadTheme();\n connectToChannel();\n});\nsetupTheme(document.querySelector(\"#theme-toggle\")!);\n\n// Make native tooltips available globally\nwindow.Alpine = Alpine;\n"],"names":["availableFilters","storeFilterData","FilterTable","filters","tableData","item","availableFiltersCopy","dataItem","a","b","filterItem","row","col","option","filter","checkboxElement","targetCheckbox","IndividualFilter","focusAfter","method","picker","flatpickr","date","startDate","endDate","formatDate","dateLabel","LanguageSelector","defaultOnly","currentLangCode","lang","matched","obj","langItem","previousSelectedLang","pathname","cleanPathname","ButtonsTab","tabName","PackageRepository","RepositoryProjectBranch","ScanRepository","findingId","response","data","FindingRepository","v1","v2","v1Parts","part","match","v2Parts","v1Part","v2Part","error","scanId","newStatus","csrfToken","findingUUID","reason","expires","packageId","location","groups","acc","finding","groupKey","stage","group","ProjectRepository","Repository","projectId","projectName","policiesTab","tabItem","policyWizard","currentStep","form","currentFormData","entries","value","key","normalizedEntries","seenForms","name","formIndex","currentState","entry","formData","event","submitButton","step","excludePatternsManager","excludePatternsFieldId","defaultMaxDepth","excludeField","patterns","p","e","pattern","numValue","ignoreSeveritiesManager","severityOptions","checkbox","total","checked","cb","ignoredVulnerabilitiesFormsetManager","totalFormsInput","initialFormsInput","template","newForm","newIndex","el","rootDiv","removeButton","index","deleteInput","formElement","Notifications","notification","i","Modal","stepMap","onboarding","onboardingData","dateString","now","today","authDate","diffInTime","diffInDays","previousStep","newStep","reverseMap","_","val","modal","command","nextStepMap","projectsResponse","projects","timer","err","processedEventIds","MAX_CACHE_SIZE","handleWebSocketMessage","message","id","dispatchFirewallEvent","handleAuthEvent","handleNotification","eventName","detail","payload","userEmail","websocket","isConnectionAcked","reconnectAttempts","MAX_RECONNECT_ATTEMPTS","isReconnecting","base64UrlEncode","getWebSocketDetails","parseJwt","token","payloadBase64","payloadJson","subscribeToChannel","channelName","authorization","subscriptionId","subscribeMessage","connectToChannel","connection","ws","http","authorizationHeaders","headerString","dynamicChannelPath","handleTokenRefresh","Sentry.captureMessage","Sentry.captureException","evt","closeChannel","firewallComponent","callback","dateInput","timestamp","diffMs","diffSec","diffMin","diffHr","diffDays","diffWeeks","monthDiff","diffMonths","diffYears","customEvent","refreshEvent","update","eventsContainer","loadMoreButton","scrollLoader","isLoading","scrollTimeout","lastRequestTime","MIN_REQUEST_INTERVAL","scrollTop","scrollHeight","clientHeight","existingUsersMap","user","users","existingUser","reset","params","correlatedEvents","nonCorrelatedEvents","correlationId","summaryEvents","events","firstEvent","summaryEventType","summaryEventTypeDisplay","summaryEvent","allEvents","formattedEvents","eventData","eventContext","eventType","eventTypeDisplay","userName","deviceName","eventId","displayType","expandable","packages","relatedEvents","count","firstPackage","packageName","packageVersion","packageManager","project","packageInfo","previousVersion","commandName","errorMessage","displayedEventCount","originalEventCount","existingEventIds","uniqueNewEvents","enabledTypes","enabled","type","filteredUpdates","userId","u","chevron","isHidden","tableBody","searchTerm","packagesByUser","pkg","userRow","userPackages","userRowElement","detailsRow","thisUser","packageRows","cell","content","lowerContent","lowerSearchTerm","highlightedContent","originalContent","searchInput","loadingIndicator","usersWithPackageMatches","packageMatches","packagesTable","packagesBody","userPackagesMap","packageKeys","updatedUsers","uniqueNewPackages","existingNoMatchesRow","matchCount","rowHasMatch","noMatchesRow","resolve","reject","cachedData","packageMatch","version","blockedPackages","blockedPackage","existingIndex","packageNameFromCommand","packageVersionFromCommand","commandStr","packageArgIndex","arg","pkgArg","parts","installedPackages","installedPackage","truncatePath","path","fileName","truncateProject","sortedPackages","loadMoreRow","highlighted","parent","userIndex","updatedUser","eventIndex","updatesContainer","unsafe","FirewallIndicator","diffInSeconds","diffInMinutes","diffInHours","diffInMonths","diffInYears","toggleTheme","setupTheme","element","loadTheme","InviteRepository","organizationId","availableSeats","invite","responseData","successfulInvites","failedInvites","fail","inviteId","UserRepository","includeInvites","invitesAsPotentialUsers","objectType","objectId","memberId","role","RiskScoreInputRepository","newInput","newLevelId","RiskScoreInputLevelRepository","Sentry.init","Sentry.browserTracingIntegration","Alpine","focus","ui","_initialStateArgs","result","initialStateArgs","ProjectTable","FindingTable","ScanTable","PackageTable","organization_id","UserTable","InviteToSendTable","filterData","userEmailVerified","emailVerificationResent","alerts","verificationMessage","alert","text","div","label","labelColor","getLevelColor","status","getBadgeColor","getStatusIcon","score","getLabel","displayDate","string_","capitalize","fixVulnerabilityTab","options","PlanForm","found","url"],"mappings":"4jDAAO,MAAMA,GAAmB,CAC5B,KAAM,CACF,CACI,MAAO,UACP,MAAO,UACP,QAAS,EACb,EAAG,CACC,MAAO,gBACP,MAAO,qBACP,QAAS,EAAA,CAEjB,EACA,WAAY,CACR,CACI,MAAO,WACP,MAAO,WACP,QAAS,EACb,EAAG,CACC,MAAO,OACP,MAAO,OACP,QAAS,EACb,EAAG,CACC,MAAO,WACP,MAAO,WACP,QAAS,EACb,EAAG,CACC,MAAO,MACP,MAAO,MACP,QAAS,EACb,EAAG,CACC,MAAO,UACP,MAAO,UACP,QAAS,EAAA,CAEjB,EACA,OAAQ,CACJ,CACI,MAAO,aACP,MAAO,MACP,QAAS,EACb,EAAG,CACC,MAAO,WACP,MAAO,OACP,QAAS,EACb,EAAG,CACC,MAAO,WACP,MAAO,WACP,QAAS,EACb,EAAG,CACC,MAAO,WACP,MAAO,WACP,QAAS,EAAA,CAEjB,EACA,UAAW,CACP,CACI,MAAO,eACP,MAAO,UACP,QAAS,EACb,EAAG,CACC,MAAO,eACP,MAAO,UACP,QAAS,EACb,EAAG,CACC,MAAO,cACP,MAAO,SACP,QAAS,EAAA,CAEjB,EACA,MAAO,CACH,CACI,MAAO,cACP,MAAO,cACP,QAAS,EACb,EAAG,CACC,MAAO,QACP,MAAO,OACP,QAAS,EACb,EAAG,CACC,MAAO,aACP,MAAO,aACP,QAAS,EAAA,CAEjB,EACA,SAAU,CACN,CACI,MAAO,eACP,MAAO,WACP,QAAS,EACb,EAAG,CACC,MAAO,WACP,MAAO,OACP,QAAS,EACb,EAAG,CACC,MAAO,UACP,MAAO,MACP,QAAS,EACb,EAAG,CACC,MAAO,eACP,MAAO,WACP,QAAS,EACb,EAAG,CACC,MAAO,cACP,MAAO,UACP,QAAS,EAAA,CAEjB,EACA,KAAM,CACF,CACI,MAAO,YACP,MAAO,YACP,KAAM,IAAI,KAAK,KAAK,IAAA,EAAQ,KAAO,GAAI,EAAE,gBAAgB,CAAC,EAC1D,GAAI,IAAI,OAAO,gBAAgB,CAAC,EAChC,QAAS,EACb,EACA,CACI,MAAO,gBACP,MAAO,gBACP,KAAM,IAAI,KAAK,KAAK,IAAA,EAAQ,MAAQ,GAAI,EAAE,gBAAgB,CAAC,EAC3D,GAAI,IAAI,OAAO,gBAAgB,CAAC,EAChC,QAAS,EACb,EAAG,CACC,MAAO,cACP,MAAO,cACP,KAAM,IAAI,KAAK,KAAK,IAAQ,EAAA,EAAI,MAAQ,GAAI,EAAE,gBAAgB,CAAC,EAC/D,GAAI,IAAI,OAAO,gBAAgB,CAAC,EAChC,QAAS,EACb,EAAG,CACC,MAAO,eACP,MAAO,eACP,KAAM,IAAI,KAAK,KAAK,IAAQ,EAAA,GAAK,MAAQ,GAAI,EAAE,gBAAgB,CAAC,EAChE,GAAI,IAAI,OAAO,gBAAgB,CAAC,EAChC,QAAS,EACb,EAAG,CACC,MAAO,uBACP,MAAO,eACP,KAAM,OACN,GAAI,OACJ,QAAS,EAAA,CAEjB,EACA,WAAY,CACR,CACI,MAAO,OACP,MAAO,OACP,QAAS,EACb,EAAG,CACC,MAAO,MACP,MAAO,MACP,QAAS,EAAA,CACb,CAER,EAEaC,EAAkB,CAC3B,qBAAsB,CAClB,MAAO,WACP,QAAS,CACL,CAAE,MAAO,UAAW,IAAK,UAAW,KAAM,QAAS,EACnD,CAAE,MAAO,SAAU,IAAK,SAAU,KAAM,QAAS,CAAA,CAEzD,EACA,4BAA6B,CACzB,MAAO,WACP,QAAS,CACL,CAAE,MAAO,SAAU,IAAK,SAAU,KAAM,QAAS,CAAA,CAEzD,EACA,kBAAmB,CACf,MAAO,QACP,QAAS,CACL,CAAE,MAAO,aAAc,IAAK,OAAQ,KAAM,YAAa,EACvD,CAAE,MAAO,UAAW,IAAK,UAAW,KAAM,QAAS,EACnD,CAAE,MAAO,QAAS,IAAK,QAAS,KAAM,QAAS,EAC/C,CAAE,MAAO,WAAY,IAAK,WAAY,KAAM,QAAS,EACrD,CAAE,MAAO,SAAU,IAAK,cAAe,KAAM,QAAS,CAAA,CAE9D,EACA,qBAAsB,CAClB,MAAO,mBACP,QAAS,CACL,CAAE,MAAO,WAAY,IAAK,aAAc,KAAM,QAAS,CAAA,CAE/D,EACA,yBAA0B,CACtB,MAAO,gBACP,QAAS,CACL,CAAE,MAAO,aAAc,IAAK,OAAQ,KAAM,YAAa,EACvD,CAAE,MAAO,QAAS,IAAK,QAAS,KAAM,QAAS,EAC/C,CAAE,MAAO,WAAY,IAAK,WAAY,KAAM,QAAS,CAAA,CACzD,CAER,EC/KO,MAAMC,EAAY,CACvB,WAAiC,CAAC,EAClC,QAEA,YAAYC,EAAqB,CAC/B,KAAK,QAAUA,CAAA,CAIjB,cACEC,EAMA,CACA,KAAK,WAAa,KAAK,QAAQ,QAAQ,IAAKC,GAAqB,CAC3D,IAAAC,EAAuB,CAAE,GAAGN,EAAiB,EACjD,OACE,KAAK,QAAQ,QAAU,SACvB,KAAK,QAAQ,QAAU,mBAEAM,EAAA,CACrB,GAAGA,EACH,KAAMA,EAAqB,SAC7B,GAEE,KAAK,QAAQ,QAAU,qBACFA,EAAA,CACrB,GAAGA,EACF,KACCA,EAAqB,UACzB,GAEK,CACL,GAAGD,EACH,QACEA,EAAK,MAAQ,WAAaA,EAAK,MAAQ,cACnC,CACE,GAAG,IAAI,IACLD,EAAU,IAAKG,GACTF,EAAK,MAAQ,UACR,YAAaE,GAAYA,EAAS,QACrCA,EAAS,QAAQ,KACjB,GACKF,EAAK,MAAQ,eACf,gBAAiBE,EAAWA,EAAS,YAEvC,EACR,CAAA,CACH,EAEC,OAAQF,GAASA,IAAS,EAAE,EAC5B,KAAK,CAACG,EAAWC,IAAeD,EAAIC,EAAI,GAAK,CAAE,EAC/C,IAAKJ,IACG,CACL,MAAOA,EACP,MAAOA,EACP,QAAS,EACX,EACD,EACHA,EAAK,MAAQ,OACbC,EACED,EAAK,GACP,EACAC,EACED,EAAK,GACP,EAAE,OAAQK,GACR,CAAC,CAACN,EAAU,KAAMO,GACZ,eAAgBA,GAAON,EAAK,MAAQ,aAEpCM,EAAI,YACJA,EAAI,WAAW,MAAM,gBACnBD,EAAW,MAAM,YAAY,EAG/B,SAAUC,GAAOA,EAAI,MAAQN,EAAK,MAAQ,OAE1CM,EAAI,KAAK,UAAU,gBACnBD,EAAW,MAAM,YAAY,EAG7B,eAAgBC,GAAON,EAAK,MAAQ,aAC/BM,EAAI,WAAW,SAASD,EAAW,KAAK,EAE7C,aAAcC,GAAON,EAAK,MAAQ,YAEjCM,EAAI,SAAS,OACZD,EAAW,KACb,GAAK,GAAK,EAIZC,EAAIN,EAAK,GAAuB,IAAMK,EAAW,KAEpD,CAAA,CAEX,CAAA,CACD,CAAA,CAIH,oBAAoBE,EAAaC,EAAoB,CACnD,OAAQ,KAAK,WAAa,KAAK,WAAW,IAAKC,GACzCA,EAAO,MAAQF,EACV,CACL,GAAGE,EACH,QAASA,EAAO,QAAQ,IAAKT,GAAS,CACpC,MAAMU,EACJ,SAAS,eAAeV,EAAK,KAAK,EAChC,OAAAU,IACFA,EAAgB,QACdV,EAAK,QAAUQ,EAAO,OACnB,CACL,GAAGR,EACH,QAASA,EAAK,QAAUQ,EAAO,MAC/B,KACER,EAAK,QAAU,uBAAyBQ,EAAO,KAAOR,EAAK,KAC7D,GAAIA,EAAK,QAAU,uBAAyBQ,EAAO,GAAKR,EAAK,EAC/D,CACD,CAAA,CACH,EACYS,CACf,CAAA,CAIH,aAAaF,EAAa,CACxB,KAAK,WAAa,KAAK,WAAW,IAAKP,GACjCA,EAAK,MAAQO,GACVP,EAAA,QAAQ,QAASQ,GAAW,CAC/B,MAAMG,EAAiB,SAAS,eAC9BH,EAAO,KACT,EACIG,IACFA,EAAe,QAAU,GAC3B,CACD,EACM,CACL,GAAGX,EACH,QAASA,EAAK,QAAQ,IAAKQ,IAClB,CAAE,GAAGA,EAAQ,QAAS,EAAM,EACpC,CACH,GAEKR,CACR,CAAA,CAEL,CAEO,MAAMY,EAAiB,CAC5B,KAAgB,GAChB,MACA,gBAAgC,CAAC,EAGjC,QAAS,CACP,GAAI,KAAK,KACP,OAAO,KAAK,MAAM,EAEf,KAAA,MAAM,OAAO,MAAM,EAExB,KAAK,KAAO,EAAA,CAId,MAAMC,EAAgC,CAC/B,KAAK,OAEV,KAAK,KAAO,GAEZA,GAAcA,EAAW,MAAM,EAAA,CAGjC,gBAAgBL,EAAoBM,EAAgB,CAC9CA,IAAW,SACR,KAAA,gBAAkBN,EAAO,QAC1B,CAAC,GAAG,KAAK,gBAAiBA,CAAM,EAChC,KAAK,gBAAgB,OACpBR,GAAqBA,EAAK,QAAUQ,EAAO,KAC9C,EACOM,IAAW,QACf,KAAA,gBAAkB,CAACN,CAAM,EAC9B,KAAK,MAAM,GACD,KAAA,gBAAkB,CAAC,CAAA,CAGjC,aAAc,CACZ,MAAMO,EAASC,GAAU,KAAK,MAAM,OAAQ,CAC1C,KAAM,QACN,WAAY,QACZ,SAAWC,GAAiB,CACpB,MAAAC,EAAYD,EAAK,CAAC,EAAI,IAAI,KAAKA,EAAK,CAAC,CAAC,EAAI,KAC1CE,EAAUF,EAAK,CAAC,EAAI,IAAI,KAAKA,EAAK,CAAC,CAAC,EAAI,KACxCG,EAAcH,GACbA,EACEA,EAAK,mBAAmB,OAAW,CAAE,IAAK,UAAW,MAAO,QAAS,EAD1D,GAGdI,EAAY,GAAGD,EAAWF,CAAS,CAAC,MAAME,EAAWD,CAAO,CAAC,GACnE,GAAID,GAAaC,EAAS,CACxB,MAAMX,EAAS,CACb,MAAO,uBACP,MAAOa,EACP,QAAS,GACT,KAAMH,EACN,GAAIC,CACN,EACK,KAAA,gBAAkB,CAACX,CAAM,EAC9B,KAAK,MAAM,EACXO,EAAO,QAAQ,CAAA,CAEnB,EACA,QAAUE,GAAiB,EAEvBA,EAAK,OAAS,GACb,IAAI,KAAKA,EAAK,CAAC,CAAC,IAAM,IAAI,KAAK,KAAK,gBAAgB,CAAC,EAAE,MAAQ,EAAE,GAChE,IAAI,KAAKA,EAAK,CAAC,CAAC,IAAM,IAAI,KAAK,KAAK,gBAAgB,CAAC,EAAE,IAAM,EAAE,IAEjEF,EAAO,QAAQ,CAAA,CACnB,CACD,EACD,KAAK,MAAM,EACXA,EAAO,KAAK,CAAA,CAEhB,CChPO,MAAMO,EAAiB,CAC1B,KAAgB,GAChB,MACA,mBAAqC,CAAC,CAClC,MAAO,KACP,KAAM,SAAA,EACP,CACC,MAAO,KACP,KAAM,QAAA,CACT,EACD,iBAEA,YAAYC,EAAuB,GAAMC,EAAyB,CAC1DD,IAAgB,KAChB,KAAK,mBAAqB,CAAC,KAAK,mBAAmB,CAAC,CAAC,GAGrD,IAAAE,EAAO,KAAK,mBAAmB,CAAC,EAC9B,MAAAC,EAAU,KAAK,mBAAmB,UAAcC,EAAI,MAAM,YAAY,IAAMH,CAAe,EAE7FE,EAAQ,SAAW,IACnBD,EAAOC,EAAQ,CAAC,GAGpB,KAAK,iBAAmBD,CAAA,CAG5B,QAAS,CACL,GAAI,KAAK,KACL,OAAO,KAAK,MAAM,EAGjB,KAAA,MAAM,OAAO,MAAM,EAExB,KAAK,KAAO,EAAA,CAGhB,MAAMZ,EAAgC,CAC7B,KAAK,OAEV,KAAK,KAAO,GAEZA,GAAcA,EAAW,MAAM,EAAA,CAGnC,eAAee,EAAwB,CACnC,KAAK,MAAM,EAEX,MAAMC,EAAuB,KAAK,iBAE9B,GAAAA,EAAqB,MAAQD,EAAS,KACtC,OAGE,MAAAE,EAAW,OAAO,SAAS,SACjC,IAAIC,EAAgB,GAAGH,EAAS,MAAM,YAAa,CAAA,GAAGE,CAAQ,GAEnCA,EAAS,WAAW,IAAID,EAAqB,MAAM,aAAa,GAAG,IAG1EE,EAAAD,EAAS,QAAQ,IAAID,EAAqB,MAAM,YAAa,CAAA,IAAK,EAAE,GAGxF,KAAK,iBAAmBD,EACjB,OAAA,SAAS,KAAO,IAAIG,CAAa,EAAA,CAEhD,CCpEO,MAAMC,EAAW,CACpB,WAAqB,aAErB,aAAc,CAAA,CAEd,cAAcC,EAAiB,CAC3B,KAAK,WAAaA,CAAA,CAE1B,CCNO,MAAMC,WAA0BC,CAAwB,CAC7D,OAAS,mBACX,CCAO,MAAMC,WAAwBD,CAAwB,CAC3D,OAAS,iBAET,MAAM,aAAaE,EAA6C,CAC9D,MAAMC,EAAW,MAAM,MAAM,KAAK,OAAS,eAAiBD,CAAS,EAC9D,OAAAC,EAAS,SAAW,IAAM,MAAMA,EAAS,KAAK,EAAE,KAAKC,GAAQA,CAAI,EAAqB,CAAC,CAAA,CAElG,CCRO,MAAMC,WAA0BL,CAAwB,CAC7D,OAAS,oBAED,gBAAgBM,EAAmBC,EAA2B,CAChE,GAAAD,IAAO,KAAa,MAAA,GACpB,GAAAC,IAAO,KAAa,MAAA,GAEpB,GAAA,CACF,MAAMC,EAAUF,EAAG,MAAM,GAAG,EAAE,IAAYG,GAAA,CAElC,MAAAC,EAAQD,EAAK,MAAM,MAAM,EAC/B,OAAOC,EAAQ,SAASA,EAAM,CAAC,EAAG,EAAE,EAAI,CAAA,CACzC,EACKC,EAAUJ,EAAG,MAAM,GAAG,EAAE,IAAYE,GAAA,CAClC,MAAAC,EAAQD,EAAK,MAAM,MAAM,EAC/B,OAAOC,EAAQ,SAASA,EAAM,CAAC,EAAG,EAAE,EAAI,CAAA,CACzC,EAGQ,QAAA,EAAI,EAAG,EAAI,KAAK,IAAIF,EAAQ,OAAQG,EAAQ,MAAM,EAAG,IAAK,CAC3D,MAAAC,EAASJ,EAAQ,CAAC,GAAK,EACvBK,EAASF,EAAQ,CAAC,GAAK,EACzB,GAAAC,EAASC,EAAe,MAAA,GACxB,GAAAD,EAASC,EAAe,MAAA,EAAA,CAEvB,MAAA,SACAC,EAAO,CACd,eAAQ,MAAM,4BAA4BR,CAAE,QAAQC,CAAE,IAAKO,CAAK,EAEzD,EAAA,CACT,CAGF,MAAM,UAAUC,EAA8C,CAC5D,MAAMZ,EAAW,MAAM,MAAM,KAAK,OAAS,YAAcY,CAAM,EACxD,OAAAZ,EAAS,SAAW,IAAM,MAAMA,EAAS,KAAK,EAAE,KAAKC,GAAQA,CAAI,EAA2B,CAAC,CAAA,CAGtG,MAAM,aAA+B,CAC7B,MAAAD,EAAW,MAAM,MAAM,KAAK,OAAQ,CAAE,OAAQ,UAAW,EACxD,OAAAA,EAAS,SAAW,IAAM,MAAMA,EAAS,KAAK,EAAE,KAAKC,GAAQA,CAAI,EAAc,CAAC,CAAA,CAGzF,MAAM,aAAaF,EAAmBc,EAAmBC,EAAoC,CAC3F,OAAO,MAAM,MACX,KAAK,OAASf,EAAY,IAC1B,CACE,OAAQ,QACR,KAAM,KAAK,UAAU,CAAE,OAAQc,EAAW,EAC1C,QAAS,CACP,cAAeC,EACf,eAAgB,kBAAA,CAClB,CAEJ,CAAA,CAGF,MAAM,OAAOC,EAAqBC,EAAgBC,EAAiBH,EAAoC,CACrG,OAAO,MAAM,MACX,KAAK,OAASC,EAAc,WAC5B,CACE,OAAQ,OACR,KAAM,KAAK,UAAU,CAAE,OAAAC,EAAgB,QAAAC,EAAkB,EACzD,QAAS,CACP,cAAeH,EACf,eAAgB,kBAAA,CAClB,CAEJ,CAAA,CAGM,yBAAyBI,EAAmBC,EAA0B,CAE5E,MAAO,GAAGD,CAAS,IAAI,mBAAmBC,CAAQ,CAAC,EAAA,CAGrD,eAAelB,EAA2B,CACxC,GAAI,CAACA,GAAQ,CAAC,MAAM,QAAQA,CAAI,EAC9B,MAAO,CAAC,EAGV,MAAMmB,EAASnB,EAAK,OAAO,CAACoB,EAAKC,IAAY,CACvC,GAAA,CAACA,GAAS,SAAS,WACb,eAAA,KAAK,wBAAyBA,CAAO,EACtCD,EAEH,MAAAH,EAAYI,EAAQ,QAAQ,WAC5BH,EAAWG,EAAQ,QAAQ,UAAY,GACvCC,EAAW,KAAK,yBAAyBL,EAAWC,CAAQ,EAE9D,OAACE,EAAIE,CAAQ,IAEfF,EAAIE,CAAQ,EAAI,CACd,WAAYL,EACZ,SAAAC,EACA,SAAU,CAAC,EACX,aAAc,EACd,aAAc,EACd,YAAa,EACb,uBAAwB,KACxB,WAAY,IACZ,SAAUI,EACV,iBAAkB,CACpB,GAIEF,EAAAE,CAAQ,EAAE,SAAS,KAAK,CAC1B,GAAGD,EACH,WAAYA,EAAQ,YAAc,CAAE,MAAO,EAAG,MAAO,MAAO,EAC5D,WAAYA,EAAQ,YAAc,KAClC,qBAAsBA,EAAQ,sBAAwB,KACtD,YAAaA,EAAQ,aAAe,KACpC,SAAUA,EAAQ,UAAY,CAAC,EAC/B,OAAQA,EAAQ,QAAU,CAAC,EAC3B,YAAaA,EAAQ,aAAe,GACpC,uBAAwBA,EAAQ,wBAA0B,EAAA,CAC3D,EAGGD,EAAAE,CAAQ,EAAE,aAAe,KAAK,IAAIF,EAAIE,CAAQ,EAAE,aAAcD,EAAQ,sBAAwB,CAAC,EAC/FD,EAAAE,CAAQ,EAAE,aAAe,KAAK,IAAIF,EAAIE,CAAQ,EAAE,aAAcD,EAAQ,YAAc,CAAC,EACrFD,EAAAE,CAAQ,EAAE,YAAc,KAAK,IAAIF,EAAIE,CAAQ,EAAE,YAAaD,EAAQ,gBAAkB,CAAC,EAGvFA,EAAQ,yBACPD,EAAIE,CAAQ,EAAE,yBAA2B,MACzC,KAAK,gBAAgBD,EAAQ,uBAAwBD,EAAIE,CAAQ,EAAE,sBAAsB,EAAI,KAC5FF,EAAAE,CAAQ,EAAE,uBAAyBD,EAAQ,wBAI7C,MAAM,QAAQA,EAAQ,MAAM,GACtBA,EAAA,OAAO,QAAiBE,GAAAH,EAAIE,CAAQ,EAAE,OAAO,IAAIC,CAAK,CAAC,EAI7DH,EAAAE,CAAQ,EAAE,iBAAmB,KAAK,IACpCF,EAAIE,CAAQ,EAAE,iBACdD,EAAQ,YAAY,OAAS,CAC/B,EAEOD,CACT,EAAG,EAAyB,EAG5B,OAAO,OAAO,OAAOD,CAAM,EAAE,IAAcK,IAAA,CACzC,GAAGA,EACH,OAAQ,MAAM,KAAKA,EAAM,MAAM,EAC/B,SAAUA,EAAM,SAAS,IAAKH,IAAkB,CAC9C,GAAGA,EACH,SAAUA,EAAQ,UAAY,CAAC,EAC/B,OAAQA,EAAQ,QAAU,CAAC,EAC3B,WAAYA,EAAQ,YAAc,CAAE,MAAO,EAAG,MAAO,MAAO,EAC5D,QAASA,EAAQ,SAAW,CAAC,EAC7B,QAAS,CACP,GAAGA,EAAQ,QACX,iBAAkBA,EAAQ,QAAQ,kBAAoB,EACxD,EACA,eAAgBA,EAAQ,gBAAkB,0BAAA,EAC1C,CAAA,EACF,CAAA,CAEN,CCpKO,MAAMI,WAA0BC,CAAW,CAChD,OAAS,oBAET,MAAM,SAASC,EAA2C,CACxD,MAAM5B,EAAW,MAAM,MACrB,KAAK,OAAS4B,EAAY,YAC5B,EACO,OAAA5B,EAAS,SAAW,IAAM,MAAMA,EAAS,KAAK,EAAE,KAAKC,GAAQA,CAAI,EAAE,CAAC,CAAA,CAG7E,MAAM,YAAY2B,EAAmBC,EAAqBf,EAAoC,CAC5F,OAAO,MAAM,MACX,KAAK,OAASc,EAAY,iBAC1B,CACE,OAAQ,OACR,KAAM,KAAK,UAAU,CAAC,KAAMC,EAAY,EACxC,QAAS,CACP,cAAef,EACf,eAAgB,kBAAA,CAClB,CAEJ,CAAA,CAGF,MAAM,OAAOc,EAAmBd,EAAoC,CAClE,OAAO,MAAM,MACX,KAAK,OAASc,EAAY,IAC1B,CACE,OAAQ,SACR,QAAS,CACP,cAAed,EACf,eAAgB,kBAAA,CAClB,CAEJ,CAAA,CAGF,MAAM,MAAMc,EAAmBd,EAAoC,CACjE,OAAO,MAAM,MACX,KAAK,OAASc,EAAY,UAC1B,CACE,OAAQ,OACR,QAAS,CACP,cAAed,EACf,eAAgB,kBAAA,CAClB,CAEJ,CAAA,CAEJ,CCpCS,SAASgB,IAAc,CACrB,MAAA,CACL,SAAU,CACR,CAAE,MAAO,aAAc,SAAU,EAAK,EACtC,CAAE,MAAO,QAAS,SAAU,EAAM,EAClC,CAAE,MAAO,cAAe,SAAU,EAAM,CAC1C,EACA,WAAWC,EAAiB,CAC1B,KAAK,SAAW,KAAK,SAAS,IAAKrE,IAC1B,CAAE,GAAGA,EAAM,SAAUA,EAAK,QAAUqE,CAAQ,EACpD,CAAA,CAEL,CACF,CAcK,SAASC,GAAaC,EAA4C,CAChE,MAAA,CACH,YAAAA,EACA,YAAa,GACb,OAAQ,GACR,iBAAkB,KAElB,kBAA8D,CACpD,MAAAC,EAAO,KAAK,MAAM,WAClBC,EAAkB,IAAI,SAASD,CAAI,EACnCE,EAA0C,CAAC,EACjCD,EAAA,QAAQ,CAACE,EAAOC,IAAQ,CACpCF,EAAQ,KAAK,CAACE,EAAKD,CAAK,CAAC,CAAA,CAC5B,EACD,MAAME,EAAwC,CAAC,EACzCC,MAAgB,IAGrBJ,EAA2C,QAAQ,CAAC,CAACK,EAAMJ,CAAK,IAAM,CAC/DI,EAAK,SAAS,kBAAkB,GAAKJ,GACrCG,EAAU,IAAIC,EAAK,MAAM,GAAG,EAAE,CAAC,CAAC,CACpC,CACH,EAGAL,EAA2C,QAAQ,CAAC,CAACK,EAAMJ,CAAK,IAAM,CAY/D,GATAI,EAAK,SAAS,aAAa,GAC3BA,EAAK,SAAS,eAAe,GAC7BA,EAAK,SAAS,eAAe,GAC7BA,EAAK,SAAS,eAAe,GAM7BA,EAAK,SAAS,SAAS,EACvB,OAIA,GAAAA,EAAK,SAAS,kBAAkB,EAAG,CAC/BJ,GACAG,EAAU,IAAIC,EAAK,MAAM,GAAG,EAAE,CAAC,CAAC,EAEpC,MAAA,CAIJ,MAAMC,EAAYD,EAAK,MAAM,GAAG,EAAE,CAAC,EAC/BC,GAAaF,EAAU,IAAIE,CAAS,GACpCH,EAAkB,KAAK,CAACE,EAAMJ,CAAe,CAAC,CAClD,CACH,EAGK,MAAAM,EAAeJ,EAChB,KAAK,CAAC1E,EAAGC,IAAMD,EAAE,CAAC,EAAE,cAAcC,EAAE,CAAC,CAAC,CAAC,EACvC,IAAa8E,GAAAA,EAAM,KAAK,GAAG,CAAC,EAC5B,KAAK,GAAG,EAET,OAAC,KAAK,iBAIHD,IAAiB,KAAK,iBAHlB,EAIf,EAEA,kBAA8D,CACpD,MAAAT,EAAO,KAAK,MAAM,WAClBW,EAAW,IAAI,SAASX,CAAI,EAC9BE,EAA0C,CAAC,EACxCS,EAAA,QAAQ,CAACR,EAAOC,IAAQ,CAC7BF,EAAQ,KAAK,CAACE,EAAKD,CAAK,CAAC,CAAA,CAC5B,EACD,MAAME,EAAoBH,EACrB,OAAO,CAAC,CAACK,CAAI,IACV,CAACA,EAAK,SAAS,aAAa,GAC5B,CAACA,EAAK,SAAS,eAAe,GAC9B,CAACA,EAAK,SAAS,eAAe,GAC9B,CAACA,EAAK,SAAS,eAAe,CAAA,EAEjC,KAAK,CAAC5E,EAAGC,IAAMD,EAAE,CAAC,EAAE,cAAcC,EAAE,CAAC,CAAC,CAAC,EACvC,IAAa8E,GAAAA,EAAM,KAAK,GAAG,CAAC,EAC5B,KAAK,GAAG,EAEX,KAAK,iBAAmBL,CAC5B,EAEA,MAAM,aAA0DO,EAAoB,CAC1E,MAAAC,EAAgBD,EAAM,WAAmC,KAE3D,GAAAC,GAAgBA,EAAa,OAAS,OAAQ,CAC9CD,EAAM,eAAe,EACrB,KAAK,OAAS,GAEd,MAAMZ,EAAOY,EAAM,OACbD,EAAW,IAAI,SAASX,CAAI,EACzBW,EAAA,OAAO,OAAQ,MAAM,EAE1B,GAAA,CACA,MAAM7C,EAAW,MAAM,MAAMkC,EAAK,OAAQ,CACtC,OAAQ,OACR,KAAMW,EACN,QAAS,CACL,mBAAoB,gBAAA,CACxB,CACH,EAEK5C,EAAO,MAAMD,EAAS,KAAK,EAEjC,GAAIA,EAAS,GACT,KAAK,UAAU,SAAU,CACrB,QAASC,EAAK,SAAW,6BACzB,KAAM,SAAA,CACT,EACD,KAAK,iBAAiB,EACtB,KAAK,YAAc,OAEnB,OAAM,IAAI,MAAMA,EAAK,SAAW,aAAa,QAE5CU,EAAY,CACjB,KAAK,UAAU,SAAU,CACrB,QAASA,EAAM,SAAW,yBAC1B,KAAM,OAAA,CACT,CAAA,QACH,CACE,KAAK,OAAS,EAAA,CAClB,CAER,EAEA,iBAA8DqC,EAAc,EACpE,CAAC,KAAK,aAAe,QAAQ,uDAAuD,KACnF,KAAK,MAAM,UAA+B,MAAQA,EACnD,KAAK,YAAc,GAClB,KAAK,MAAM,WAA+B,OAAO,EAE1D,EAEA,MAAkD,CAC9C,KAAK,iBAAiB,EAEjB,KAAA,OAAO,cAAgBX,GAAmB,CACpC,OAAA,eAAiBA,EAAQ,IAAM,GAAK,IAAA,CAC9C,EAEA,KAAK,MAAM,WAA+B,iBAAiB,QAAS,IAAM,CAClE,KAAA,YAAc,KAAK,iBAAiB,CAAA,CAC5C,EAEI,KAAA,IAAI,iBAAiB,eAAgB,IAAM,CACvC,KAAA,YAAc,KAAK,iBAAiB,CAAA,CAC5C,EAEI,KAAA,IAAI,iBAAiB,kBAAmB,IAAM,CAC1C,KAAA,YAAc,KAAK,iBAAiB,CAAA,CAC5C,CAAA,CAET,CACF,CAoBgB,SAAAY,GACdC,EACAC,EAAkB,EACW,CAEtB,MAAA,CACL,qBAAsB,IACtB,WAAY,GACZ,WAAYA,EACZ,eAAgB,CACd,CAAE,KAAM,OAAQ,YAAa,uCAAwC,EACrE,CAAE,KAAM,SAAU,YAAa,gBAAiB,EAChD,CAAE,KAAM,OAAQ,YAAa,sBAAuB,EACpD,CAAE,KAAM,cAAe,YAAa,6BAA8B,EAClE,CAAE,KAAM,eAAgB,YAAa,8BAA+B,EACpE,CAAE,KAAM,OAAQ,YAAa,uDAAwD,CACvF,EAEA,MAAwD,CAChD,MAAAC,EAAe,SAAS,eAAeF,CAAsB,EAC/D,GAAAE,GAAgBA,EAAa,MAC3B,GAAA,CACF,MAAMC,EAAW,KAAK,MAAMD,EAAa,KAAK,EAC1C,MAAM,QAAQC,CAAQ,GACxBA,EAAS,QAASC,GAAc,KAAK,iBAAiB,IAAIA,CAAC,CAAC,QAEvDC,EAAG,CACF,QAAA,MAAM,kCAAmCA,CAAC,CAAA,CAGtD,KAAK,kBAAkB,CACzB,EAEA,YAA8D,CACtD,MAAAC,EAAU,KAAK,WAAW,KAAK,EACjCA,GAAW,CAAC,KAAK,iBAAiB,IAAIA,CAAO,IAC1C,KAAA,iBAAiB,IAAIA,CAAO,EACjC,KAAK,kBAAkB,EACvB,KAAK,WAAa,GACb,KAAA,UAAU,eAAgB,EAAI,EAEvC,EAEA,cAAiEA,EAAiB,CAC3E,KAAA,iBAAiB,OAAOA,CAAO,EACpC,KAAK,kBAAkB,EAClB,KAAA,UAAU,eAAgB,EAAI,CACrC,EAEA,iBAAoEA,EAAiB,CAC9E,KAAK,iBAAiB,IAAIA,CAAO,IAC/B,KAAA,iBAAiB,IAAIA,CAAO,EACjC,KAAK,kBAAkB,EAClB,KAAA,UAAU,eAAgB,EAAI,EAEvC,EAEA,kBAAqEA,EAAiB,CAC7E,OAAA,KAAK,iBAAiB,IAAIA,CAAO,CAC1C,EAEA,qBAAuE,CAC9D,OAAA,MAAM,KAAK,KAAK,gBAAgB,CACzC,EAEA,mBAAqE,CAC7D,MAAAJ,EAAe,SAAS,eAAeF,CAAsB,EAC/DE,IACFA,EAAa,MAAQ,KAAK,UAAU,KAAK,qBAAqB,EAElE,EAEA,cAAiEf,EAAe,CAC1E,GAAAA,IAAU,GAAW,OAAAA,EACzB,MAAMoB,EAAW,SAASpB,EAAO,EAAE,GAAK,EACxC,OAAO,KAAK,IAAI,KAAK,IAAIoB,EAAU,CAAC,EAAG,EAAE,CAAA,CAE7C,CACF,CAqBO,SAASC,IAAwD,CAC/D,MAAA,CACL,UAAW,GACX,gBAAiB,GACjB,WAAY,CAAC,EACb,YAAa,GAEb,MAAyD,CAEvD,KAAK,UAAU,IAAM,CACb,MAAAC,EAAkB,KAAK,MAAM,gBAC9BA,IAEL,KAAK,WAAa,MAAM,KAAKA,EAAgB,iBAAiB,sBAAsB,CAAC,EAGrF,KAAK,qBAAqB,EAGrB,KAAA,WAAW,QAAoBC,GAAA,CACzBA,EAAA,iBAAiB,SAAU,IAAM,CACxC,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,CAAA,CACvB,CAAA,CACF,EAGD,KAAK,iBAAiB,EAAA,CACvB,CACH,EAEA,iBAAoE,CAC7D,KAAA,WAAW,QAAoBA,GAAA,CAClCA,EAAS,QAAU,KAAK,SAAA,CACzB,EACD,KAAK,gBAAkB,GACvB,KAAK,iBAAiB,CACxB,EAEA,sBAAyE,CACjE,MAAAC,EAAQ,KAAK,WAAW,OACxBC,EAAU,KAAK,WAAW,OAAaC,GAAAA,EAAG,OAAO,EAAE,OAErDD,IAAYD,GACd,KAAK,UAAY,GACjB,KAAK,gBAAkB,IACdC,IAAY,GACrB,KAAK,UAAY,GACjB,KAAK,gBAAkB,KAEvB,KAAK,UAAY,GACjB,KAAK,gBAAkB,GAE3B,EAEA,kBAAqE,CACnE,KAAK,YAAc,KAAK,WAAW,MAAMC,GAAMA,EAAG,OAAO,CAAA,CAE7D,CACF,CAmBO,SAASC,IAA2E,CAClF,MAAA,CACL,WAAY,EACZ,aAAc,EAEd,MAA+D,CAC7D,KAAK,UAAU,IAAM,CACb,MAAAC,EAAkB,SAAS,cAAgC,8CAA8C,EACzGC,EAAoB,SAAS,cAAgC,gDAAgD,EAE/GD,IACF,KAAK,WAAa,SAASA,EAAgB,MAAO,EAAE,GAElDC,IACF,KAAK,aAAe,SAASA,EAAkB,MAAO,EAAE,GAGrD,KAAA,OAAO,aAAuB7B,GAAA,CAC3B4B,MAAAA,EAAkB,SAAS,cAAc,8CAA8C,EACzFA,IACFA,EAAgB,MAAQ,OAAO5B,CAAK,EACtC,CACD,CAAA,CACF,CACH,EAEA,SAAkE,CAC1D,MAAA8B,EAAW,SAAS,cAAmC,sBAAsB,EACnF,GAAI,CAACA,EAAU,OAEf,MAAMC,EAAUD,EAAS,QAAQ,UAAU,EAAI,EACzCE,EAAW,KAAK,WAGtBD,EAAQ,iBAA8B,QAAQ,EAAE,QAAcE,GAAA,EACxDA,aAAc,kBAAoBA,aAAc,uBAClDA,EAAG,KAAOA,EAAG,KAAK,QAAQ,aAAc,OAAOD,CAAQ,CAAC,EACpDC,EAAG,KACLA,EAAG,GAAKA,EAAG,GAAG,QAAQ,aAAc,OAAOD,CAAQ,CAAC,GAExD,CACD,EAGK,MAAAE,EAAUH,EAAQ,cAAc,KAAK,EACvCG,IACMA,EAAA,GAAK,QAAQF,CAAQ,IAIzB,MAAAG,EAAeJ,EAAQ,cAA2B,oBAAoB,EACxEI,GACFA,EAAa,aAAa,aAAc,cAAcH,CAAQ,GAAG,EAGnE,SAAS,cAAc,oBAAoB,GAAG,YAAYD,CAAO,EAC5D,KAAA,aACL,KAAK,UAAU,cAAc,CAC/B,EAEA,WAAqEK,EAAe,CAClF,MAAMC,EAAc,SAAS,cAAgC,kCAAkCD,CAAK,WAAW,EAC3GC,IACFA,EAAY,MAAQ,MAGtB,MAAMC,EAAc,SAAS,cAAc,SAASF,CAAK,EAAE,EACvDE,IACDA,EAA4B,MAAM,QAAU,QAG/C,KAAK,UAAU,cAAc,CAAA,CAEjC,CACF,CC1dO,MAAMC,EAAc,CACvB,cAAuB,CAAC,EAExB,aAAc,CAAA,CAEd,IAAI,EAAQ,CACR,KAAK,cAAc,KAAK,CACpB,GAAI,EAAE,UACN,KAAM,EAAE,OAAO,KACf,QAAS,EAAE,OAAO,QAClB,OAAQ,EAAE,OAAO,OACjB,WAAY,EAAE,OAAO,WACrB,gBAAiB,EAAE,OAAO,gBAC1B,gBAAiB,EAAE,OAAO,gBAC1B,oBAAqB,EAAE,OAAO,mBAAA,CACjC,CAAA,CAGL,OAAOC,EAAmB,CACjB,KAAA,cAAgB,KAAK,cAAc,UAAYC,EAAE,KAAOD,EAAa,EAAE,CAAA,CAEpF,CCrBO,MAAME,EAAM,CACf,YAAuB,GAEvB,aAAc,CAAA,CAEd,WAAY,CACR,KAAK,YAAc,EAAA,CAGvB,YAAa,CACT,KAAK,YAAc,EAAA,CAE3B,CC0DA,MAAMC,EAAqC,CACvC,MAAS,EACT,QAAW,EACX,OAAU,CACd,EAYAC,GAAe,IAAsB,CAEjC,MAAMC,EAAiB,KAAK,MACxB,SAAS,eAAe,iBAAiB,GAAG,aAAe,IAC/D,EAEO,MAAA,CAIH,KAAMA,EAAe,cAAgB,QACrC,UAAWA,EAAe,WAAa,GACvC,eAAgBA,EAAe,gBAAkB,GACjD,YAAa,KACb,QAAS,GACT,OAAQ,GACR,oBAAqBA,EAAe,cAAgB,GACpD,SAAUA,EAAe,UAAY,CAAC,EACtC,gBAAiB,GACjB,MAAOA,EAAe,OAAS,GAC/B,kBAAmB,EACnB,gBAAiB,GACjB,aAAc,GACd,YAAaA,EAAe,aAAe,GAW3C,WAAWC,EAA4B,CACnC,GAAI,CAACA,EACM,MAAA,GAEL,MAAAxG,EAAO,IAAI,KAAKwG,CAAU,EAC1BC,MAAU,KAGVC,EAAQ,IAAI,KAAKD,EAAI,YAAA,EAAeA,EAAI,SAAS,EAAGA,EAAI,SAAS,EAEjEE,EAAW,IAAI,KAAK3G,EAAK,YAAA,EAAeA,EAAK,SAAS,EAAGA,EAAK,SAAS,EAGvE4G,EAAaF,EAAM,QAAQ,EAAIC,EAAS,QAAQ,EAChDE,EAAa,KAAK,MAAMD,GAAc,IAAO,GAAK,GAAK,GAAG,EAEhE,OAAIC,IAAe,EACR,YAAc7G,EAAK,mBAAmB,CAAC,EAAG,CAAE,KAAM,UAAW,OAAQ,UAAW,EAChF6G,IAAe,EACf,gBAAkB7G,EAAK,mBAAmB,CAAC,EAAG,CAAE,KAAM,UAAW,OAAQ,UAAW,EAEpF,GAAG6G,CAAU,WAE5B,EAOA,SAAkB,CACP,OAAAR,EAAQ,KAAK,IAAI,GAAK,CACjC,EAUA,MAAM,QAAQhC,EAAsC,CAEhD,MAAMyC,EAAe,KAAK,KAEtB,GAAA,CAEI,IAAAC,EACA,GAAA,OAAO1C,GAAS,SAAU,CAC1B,MAAM2C,EAAa,OAAO,QAAQX,CAAO,EAAE,KAAK,CAAC,CAACY,EAAGC,CAAG,IAAMA,IAAQ7C,CAAI,EAC1E0C,EAAUC,EAAaA,EAAW,CAAC,EAAI,OAAO3C,CAAI,CAAA,MAElD0C,EAAU,OAAO1C,CAAI,EAEzB,KAAK,KAAO0C,EAGRA,IAAY,UACZ,MAAM,KAAK,UAAU,EAIzB,KAAK,QAAU,GAGf,MAAM5E,EAAY,SAAS,OACtB,MAAM,IAAI,EACV,KAAK9C,GAAOA,EAAI,WAAW,YAAY,CAAC,GACvC,MAAM,GAAG,EAAE,CAAC,EAWd,GAAA,EATa,MAAM,MAAM,gBAAiB,CAC1C,OAAQ,OACR,QAAS,CACL,eAAgB,mBAChB,cAAe8C,GAAa,EAChC,EACA,KAAM,KAAK,UAAU,CAAE,KAAM4E,CAAS,CAAA,CAAA,CACzC,GAEa,GACJ,MAAA,IAAI,MAAM,uBAAuB,QAEtC/E,EAAO,CAEZ,GAAIA,GAAS,OAAOA,GAAU,UAAY,8BAA+BA,EAErE,OAEI,QAAA,MAAM,uBAAwBA,CAAK,EAE3C,KAAK,KAAO8E,CAAA,CAEpB,EAOA,eAAeK,EAAqB,CAChC,KAAK,YAAcA,CACvB,EAKA,YAAmB,CACf,KAAK,YAAc,IACvB,EAQA,MAAM,YAAYC,EAAgC,CACxC,MAAA,UAAU,UAAU,UAAUA,CAAO,EAE3C,KAAK,OAASA,EAAQ,SAAS,aAAa,EAAI,OAAS,UAEzD,WAAW,IAAM,CACb,KAAK,OAAS,IACf,GAAI,CACX,EAKA,MAAM,UAA0B,CACtB,MAAA9D,EAAc,KAAK,QAAQ,EAC3B+D,EAAyC,CAC3C,EAAG,UACH,EAAG,QACP,EAEA,GAAI/D,IAAgB,EAAG,CACnB,QAAQ,IAAI,8DAA8D,EAC1E,MAAA,CAGJ,MAAM,KAAK,QAAQ+D,EAAY/D,CAAW,GAAK,OAAO,CAC1D,EAKA,MAAM,SAAyB,CACvB,GAAA,CACA,MAAMnB,EAAY,SAAS,OACtB,MAAM,IAAI,EACV,KAAK9C,GAAOA,EAAI,WAAW,YAAY,CAAC,GACvC,MAAM,GAAG,EAAE,CAAC,GAED,MAAM,MAAM,gBAAiB,CAC1C,OAAQ,OACR,QAAS,CACL,eAAgB,mBAChB,cAAe8C,GAAa,EAChC,EACA,KAAM,KAAK,UAAU,CAAE,OAAQ,OAAS,CAAA,CAAA,CAC3C,GAEa,IACV,QAAQ,MAAM,4BAA4B,EAI9C,KAAK,KAAO,QACZ,KAAK,UAAY,GACjB,KAAK,YAAc,KACnB,KAAK,gBAAkB,GACvB,KAAK,kBAAoB,EACzB,KAAK,gBAAkB,GACvB,KAAK,aAAe,SAEfH,EAAO,CACJ,QAAA,MAAM,wBAAyBA,CAAK,EAC5C,KAAK,KAAO,QACZ,KAAK,UAAY,GACjB,KAAK,YAAc,KACnB,KAAK,gBAAkB,GACvB,KAAK,kBAAoB,EACzB,KAAK,gBAAkB,GACvB,KAAK,aAAe,EAAA,CAE5B,EAEA,MAAM,gBAAgC,CAElC,MAAMG,EAAY,SAAS,OACtB,MAAM,IAAI,EACV,KAAK9C,GAAOA,EAAI,WAAW,YAAY,CAAC,GACvC,MAAM,GAAG,EAAE,CAAC,EACd,GAAA,EACiB,MAAM,MAAM,gBAAiB,CAC1C,OAAQ,OACR,QAAS,CACL,eAAgB,mBAChB,cAAe8C,GAAa,EAChC,EACA,KAAM,KAAK,UAAU,CAAE,OAAQ,MAAQ,CAAA,CAAA,CAC1C,GACa,IAGV,QAAQ,IAAI,kCAAkC,EAE9C,KAAK,UAAY,GACjB,OAAO,SAAS,KAAO,KALvB,QAAQ,MAAM,2BAA2B,QAOxCH,EAAO,CACJ,QAAA,MAAM,mCAAoCA,CAAK,CAAA,CAE/D,EAQA,MAAM,WAA2B,CACzB,KAAK,QAAQ,IAAM,IAEd,KAAA,oBAAsB,KAAK,SAAS,OAAS,EAE1D,EAKA,qBAA4B,CACxB,KAAK,gBAAkB,EAC3B,EAQA,MAAM,oBAAoC,CAElC,GAAA,CACA,MAAMG,EAAY,SAAS,OACtB,MAAM,IAAI,EACV,KAAK9C,GAAOA,EAAI,WAAW,YAAY,CAAC,GACvC,MAAM,GAAG,EAAE,CAAC,EAWd,GAAA,EATa,MAAM,MAAM,gBAAiB,CAC1C,OAAQ,OACR,QAAS,CACL,eAAgB,mBAChB,cAAe8C,GAAa,EAChC,EACA,KAAM,KAAK,UAAU,CAAE,KAAM,SAAU,UAAW,EAAM,CAAA,CAAA,CAC3D,GAEa,GACJ,MAAA,IAAI,MAAM,wCAAwC,EAG5D,KAAK,UAAY,GACjB,QAAQ,IAAI,gCAAgC,EAGtC,MAAAmF,EAAmB,MAAM,MAAM,mBAAmB,EACpD,GAAA,CAACA,EAAiB,GACZ,MAAA,IAAI,MAAM,+BAA+B,EAE7C,MAAAC,EAAW,MAAMD,EAAiB,KAAK,EAGzCC,EAAS,SAAW,EAEpB,OAAO,SAAS,KAAO,aAAaA,EAAS,CAAC,EAAE,EAAE,YAC3CA,EAAS,OAAS,EAEzB,OAAO,SAAS,KAAO,IAGvB,QAAQ,IAAI,4CAA4C,QAGvDvF,EAAO,CACJ,QAAA,MAAM,wCAAyCA,CAAK,EAE5D,KAAK,UAAY,EAAA,CAEzB,EAMA,wBAA+B,CAC3B,KAAK,gBAAkB,GACvB,KAAK,kBAAoB,GACnB,MAAAwF,EAAQ,YAAY,IAAM,CAC5B,KAAK,mBAAqB,EACtB,KAAK,mBAAqB,IAC1B,cAAcA,CAAK,EACnB,KAAK,gBAAkB,GACnB,KAAK,QAAQ,EAAI,EAEjB,KAAK,SAAW,EAAA,SAAa,QAAQ,MAAMC,CAAG,CAAC,EAG/C,KAAK,mBAAmB,IAGjC,GAAI,CACX,EASA,MAAa,CACF,OAAA,iBAAiB,8BAA+B,IAAM,CACzD,KAAK,oBAAoB,EAErB,SAAS,WACT,KAAK,uBAAuB,EAErB,OAAA,iBAAiB,QAAS,IAAM,CACnC,KAAK,uBAAuB,CAAA,EAC7B,CAAE,KAAM,GAAM,CACrB,CACH,EACM,OAAA,iBAAiB,0BAA2B,IAAM,CAEjD,KAAK,QAAQ,IAAM,GAAK,CAAC,KAAK,eAC9B,KAAK,aAAe,GAEhB,CAAC,KAAK,iBAAmB,CAAC,KAAK,qBAC/B,KAAK,uBAAuB,EAEpC,CACH,CAAA,CAET,CACJ,EChdMC,MAAwB,IAExBC,EAAiB,IAOhB,SAASC,GAAuBC,EAA+B,CAElE,GAAI,EAAAA,EAAQ,OAAS,QAAU,CAACA,EAAQ,OAIpC,GAAA,CAEA,MAAM1D,EAAoB,KAAK,MAAM0D,EAAQ,KAAK,EAGlD,GAAI1D,EAAM,IAAMuD,EAAkB,IAAIvD,EAAM,EAAE,EAAG,CAC7C,QAAQ,IAAI,qCAAqCA,EAAM,EAAE,EAAE,EAC3D,MAAA,CAcJ,OAVIA,EAAM,KAEFuD,EAAkB,MAAQC,GACN,MAAM,KAAKD,CAAiB,EAAE,MAAM,EAAGC,EAAiB,EAAE,EAClE,QAAQG,GAAMJ,EAAkB,OAAOI,CAAE,CAAC,EAExCJ,EAAA,IAAIvD,EAAM,EAAE,GAI1BA,EAAM,KAAM,CAGhB,IAAK,kCACL,IAAK,oCACL,IAAK,kCACL,IAAK,mCACO,QAAA,IAAI,cAAcA,EAAM,KAAK,MAAM,GAAG,EAAE,IAAK,CAAA,iBAAiB,EACtE4D,EAAsB,0BAA2B,CAC7C,UAAW,IAAI,KAAK5D,EAAM,IAAI,EAAE,eAAe,EAC/C,UAAWA,EAAM,KACjB,QAASA,EAAM,EAAA,CAClB,EACD,MAGJ,IAAK,OACD,QAAQ,IAAI,cAAc,EAC1B,MAGJ,IAAK,OACL,IAAK,qBACD6D,GAAgB7D,EAAM,IAA2B,EACjD,MAGJ,IAAK,6BACD8D,EAAmB9D,EAAM,IAA2B,EACpD4D,EAAsB,0BAA2B,CAC7C,UAAW,IAAI,KAAK5D,EAAM,IAAI,EAAE,eAAe,EAC/C,UAAWA,EAAM,KACjB,QAASA,EAAM,EAAA,CAClB,EACD,MAGJ,IAAK,SACD8D,EAAmB9D,EAAM,IAA2B,EACpD,MAGJ,QACI,QAAQ,IAAI,yBAAyBA,EAAM,IAAI,EAAE,EACjD,KAAA,QAEHnC,EAAO,CACJ,QAAA,MAAM,sCAAuCA,CAAK,CAAA,CAElE,CAoBA,SAAS+F,EAAsBG,EAAmBC,EAAmB,CACjE,OAAO,cAAc,IAAI,YAAYD,EAAW,CAAE,OAAAC,CAAA,CAAQ,CAAC,CAC/D,CAQA,SAASF,EAAmBG,EAAoC,CAC5D,QAAQ,IAAI,iBAAkB,CAC1B,KAAMA,EAAQ,KACd,QAASA,EAAQ,QACjB,SAAUA,EAAQ,gBAAA,CACrB,EACK,MAAAjE,EAAQ,IAAI,YAAY,SAAU,CACpC,QAAS,GACT,OAAQ,CACJ,KAAMiE,EAAQ,KACd,QAASA,EAAQ,QACjB,gBAAiBA,EAAQ,iBACzB,OAAQA,EAAQ,OAChB,WAAYA,EAAQ,YACpB,gBAAiBA,EAAQ,iBACzB,oBAAqBA,EAAQ,qBAAA,CACjC,CACH,EACD,OAAO,cAAcjE,CAAK,EAEtBiE,EAAQ,SAAW,iBACnB,QAAQ,IAAI,2CAA2C,EACvD,OAAO,cAAc,IAAI,YAAY,yBAAyB,CAAC,EAEvE,CAOA,SAASJ,GAAgBI,EAAoC,CACzD,GAAIA,EAAQ,KAAM,CACd,QAAQ,IAAI,eAAgB,CACxB,OAAQA,EAAQ,KAAK,OACrB,MAAOA,EAAQ,KAAK,MACpB,kBAAmBA,EAAQ,KAAK,kBAChC,gBAAiBA,EAAQ,KAAK,eAAA,CACjC,EAED,MAAMC,EAAY,SAAS,eAAe,iBAAiB,GAAG,aAAa,iBAAiB,EACxFD,EAAQ,KAAK,SAAW,OAASA,EAAQ,KAAK,QAAUC,IACxD,QAAQ,IAAI,yDAAyD,EACrE,OAAO,cAAc,IAAI,YAAY,6BAA6B,CAAC,EACvE,CAER,CC9IA,IAAIC,EAA8B,KAC9BC,EAAoB,GAGpBC,EAAoB,EACxB,MAAMC,EAAyB,EAC/B,IAAIC,EAAiB,GASrB,SAASC,GAAgBjI,EAAqC,CAC5D,OAAO,KAAK,KAAK,UAAUA,CAAG,CAAC,EAC5B,QAAQ,MAAO,GAAG,EAClB,QAAQ,MAAO,GAAG,EAClB,QAAQ,MAAO,EAAE,CACtB,CAQA,eAAekI,IAA6D,CACtE,GAAA,CACI,MAAAvH,EAAW,MAAM,MAAM,aAAa,EAOtC,GALAA,EAAS,SAAW,MACtB,QAAQ,IAAI,oDAAoD,EAChE,OAAO,SAAS,KAAO,UAGrBA,EAAS,SAAW,IAAK,CAC3B,QAAQ,IAAI,iCAAiC,EAC7C,MAAA,CAGE,GAAA,CAACA,EAAS,GACZ,cAAQ,MAAM,qCAAsC,CAClD,OAAQA,EAAS,OACjB,WAAYA,EAAS,UAAA,CACtB,EACK,IAAI,MAAM,oCAAoCA,EAAS,MAAM,EAAE,EAGhE,OAAA,MAAMA,EAAS,KAAK,QACpBW,EAAO,CACN,cAAA,MAAM,qCAAsCA,CAAK,EACnDA,CAAA,CAEV,CAQA,SAAS6G,GAASC,EAAoC,CACpD,KAAM,CAAG,CAAAC,CAAa,EAAID,EAAM,MAAM,GAAG,EACnCE,EAAc,KAAKD,EAAc,QAAQ,KAAM,GAAG,EAAE,QAAQ,KAAM,GAAG,CAAC,EACrE,OAAA,KAAK,MAAMC,CAAW,CAC/B,CASA,SAASC,GAAmBC,EAAqBC,EAA2C,CACtF,GAAA,CAACb,GAAa,CAACC,EAAmB,CACpC,QAAQ,KAAK,6CAA6C,EAC1D,MAAA,CAGI,MAAAa,EAAiB,OAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,EAAG,CAAC,EAC/DC,EAAmB,CACvB,KAAM,YACN,GAAID,EACJ,QAASF,EACT,cAAAC,CACF,EAEA,QAAQ,IAAI,uCAAuCD,CAAW,QAAQE,CAAc,EAAE,EACtFd,EAAU,KAAK,KAAK,UAAUe,CAAgB,CAAC,CACjD,CAQA,eAAsBC,GAAkC,CAItD,GAFgC,SAAS,cAAc,kCAAkC,IAAM,KAElE,CACnB,QAAA,IAAI,mCAAoC,qBAAqB,EACrE,MAAA,CAGI,MAAAC,EAAa,MAAMX,GAAoB,EAC7C,GAAI,CAACW,EACH,OAGF,KAAM,CAAE,GAAAC,EAAI,KAAAC,EAAM,MAAAX,CAAU,EAAAS,EAE5B,GAAI,CAACC,GAAM,CAACC,GAAQ,CAACX,EACb,MAAA,IAAI,MAAM,2BAA2B,EAI7C,MAAMY,EAA6C,CACjD,KAAMD,EACN,cAAe,UAAUX,CAAK,EAChC,EAGMa,EAAe,UAAUhB,GAAgBe,CAAoB,CAAC,GAGpEpB,EAAY,IAAI,UAAUkB,EAAI,CAACG,EAAc,sBAAsB,CAAC,EAGpErB,EAAU,OAAS,IAAM,CACvB,QAAQ,IAAI,+CAA+C,EAC3DA,GAAW,KAAK,KAAK,UAAU,CAAE,KAAM,iBAAA,CAAmB,CAAC,CAC7D,EAGUA,EAAA,UAAanE,GAAU,CAC/B,MAAM7C,EAAuB,KAAK,MAAM6C,EAAM,IAAI,EAElD,OAAQ7C,EAAK,KAAM,CACjB,IAAK,iBACH,QAAQ,IAAI,qCAAqC,EAC7BiH,EAAA,GACAC,EAAA,EAId,MAAAoB,EAAqB,QAFZf,GAASC,CAAK,EACN,IAAI,QAAQ,IAAK,GAAG,CACD,GAC1CG,GAAmBW,EAAoBF,CAAoB,EAC3D,MAEF,IAAK,KAEH,MAEF,IAAK,oBACH,QAAQ,IAAI,qCAAqCpI,EAAK,EAAE,EAAE,EAC1D,MAEF,IAAK,OACHsG,GAAuBtG,CAAI,EAC3B,MAEF,IAAK,mBACL,IAAK,kBACH,QAAQ,MAAM,eAAeA,EAAK,IAAI,IAAKA,EAAK,MAAM,EAClDA,EAAK,SAAS,CAAC,GAAG,YAAc,wBACfuI,EAAA,EAEnBC,EAAsB,aAAaxI,EAAK,IAAI,GAAI,CAC9C,MAAO,QACP,MAAO,CAAE,OAAQA,EAAK,MAAO,CAAA,CAC9B,EAGH,MAEF,QACU,QAAA,IAAI,oCAAqCA,CAAI,EACrD,KAAA,CAEN,EAEUgH,EAAA,QAAWnE,GAAU,CACrB,QAAA,MAAM,qBAAsBA,CAAK,EACzC4F,EAAwB,IAAI,MAAM,4BAA4B,EAAG,CAC/D,MAAO,CACL,WAAYzB,GAAW,WACvB,IAAKA,GAAW,GAAA,CAClB,CACD,CACH,EAEUA,EAAA,QAAW0B,GAAQ,CACf1B,EAAA,KACQC,EAAA,GAGhB,CAACG,IAAmB,CAACsB,EAAI,QAAUA,EAAI,SAAW,cACpD,QAAQ,IAAI,wEAAwE,EACjEH,EAAA,GAEnB,QAAQ,IAAI,sBAAuBG,EAAI,QAAU,WAAW,CAEhE,CACF,CAKO,SAASC,IAAqB,CAC/B3B,IACF,QAAQ,IAAI,wBAAwB,EACpCA,EAAU,MAAM,EACJA,EAAA,KACQC,EAAA,GAExB,CAGO,SAASsB,GAA2B,CACzC,GAAInB,EAAgB,CAClB,QAAQ,IAAI,6CAA6C,EACzD,MAAA,CAGF,GAAIF,GAAqBC,EAAwB,CAC/C,QAAQ,MAAM,+CAA+C,EAC7DqB,EAAsB,8CAA+C,CACnE,MAAO,QACP,MAAO,CACL,SAAUtB,EACV,YAAaC,CAAA,CACf,CACD,EACD,MAAA,CAGeC,EAAA,GACjBF,IAEA,QAAQ,IAAI,oCAAoCA,CAAiB,IAAIC,CAAsB,EAAE,EAGhFwB,GAAA,EAGb,WAAW,IAAM,CACEX,EAAA,EACd,MAAetH,GAAA,CACN,QAAA,MAAM,mCAAoCA,CAAK,CAAA,CACxD,EACA,QAAQ,IAAM,CACI0G,EAAA,EAAA,CAClB,CAAA,EACF,IAAOF,CAAiB,CAC7B,CC1LO,SAAS0B,IAA2C,CAClD,MAAA,CACL,UAAW,GACX,eAAgB,GAChB,iBAAkB,GAClB,gBAAiB,GACjB,OAAQ,SACR,YAAa,CACX,OAAQ,aACR,gBAAiB,EACjB,YAAa,EACb,aAAc,aACd,kBAAmB,CAAC,EACpB,iBAAkB,EAClB,kBAAmB,CACrB,EACA,MAAO,CAAC,EACR,QAAS,CAAC,EACV,cAAe,KACf,WAAY,EACZ,YAAa,GACb,iBAAkB,CAChB,QAAS,GACT,MAAO,GACP,KAAM,GACN,QAAS,GACT,QAAS,EACX,EACA,cAAe,CAAC,EAChB,eAAgB,CACd,mBAAoB,EACpB,gBAAiB,EACjB,oBAAqB,CACvB,EACA,sBAAuB,IACvB,gBAAiB,EACjB,YAAa,EACb,cAAe,GACf,gBAAiB,GACjB,cAAe,GACf,oBAAqB,KACrB,gBAAiB,IACjB,oBAAqB,GACrB,kBAAmB,GACnB,YAAa,GACb,QAAS,GACT,QAAS,KACT,qBAAsB,KACtB,mBAAoB,GACpB,mBAAoB,KACpB,mBAAoB,IAEpB,UAAY,SAASC,EAAsB,CAChCA,EAAA,CACX,EACA,MAAO,CAAC,EAER,WAAWC,EAA2C,CAChD,GAAA,CAACA,EAAkB,MAAA,GAEjB,MAAApK,EAAO,IAAI,KAAKoK,CAAS,EAC/B,OAAI,MAAMpK,EAAK,QAAS,CAAA,EAAU,GAE3BA,EAAK,eAAe,QAAS,CAClC,KAAM,UACN,MAAO,QACP,IAAK,UACL,KAAM,UACN,OAAQ,SAAA,CACT,CACH,EAEA,gBAAgBqK,EAA2C,CACzD,GAAI,CAACA,GAAaA,IAAc,QAAgB,MAAA,QAE1C,MAAA5D,MAAU,KACVzG,EAAO,IAAI,KAAKqK,CAAS,EAG/B,GAAI,MAAMrK,EAAK,QAAS,CAAA,EAAU,MAAA,QAElC,MAAMsK,EAAS7D,EAAI,QAAQ,EAAIzG,EAAK,QAAQ,EACtCuK,EAAU,KAAK,MAAMD,EAAS,GAAI,EAClCE,EAAU,KAAK,MAAMD,EAAU,EAAE,EACjCE,EAAS,KAAK,MAAMD,EAAU,EAAE,EAChCE,EAAW,KAAK,MAAMD,EAAS,EAAE,EACjCE,EAAY,KAAK,MAAMD,EAAW,CAAC,EAGnCE,GAAanE,EAAI,YAAY,EAAIzG,EAAK,eAAiB,IAAMyG,EAAI,SAAa,EAAAzG,EAAK,SAAS,GAC5F6K,EAAa,KAAK,IAAI,EAAGD,CAAS,EAClCE,EAAY,KAAK,MAAMJ,EAAW,GAAG,EAGvC,OAAAH,EAAU,GAAW,GAAGA,CAAO,UAAUA,IAAY,EAAI,IAAM,EAAE,OAGjEC,EAAU,GAAW,GAAGA,CAAO,UAAUA,IAAY,EAAI,IAAM,EAAE,OAGjEC,EAAS,GAAW,GAAGA,CAAM,QAAQA,IAAW,EAAI,IAAM,EAAE,OAG5DC,EAAW,EAAU,GAAGA,CAAQ,OAAOA,IAAa,EAAI,IAAM,EAAE,OAGhEC,EAAY,EAAU,GAAGA,CAAS,QAAQA,IAAc,EAAI,IAAM,EAAE,OAGpEE,EAAa,GAAW,GAAGA,CAAU,SAASA,IAAe,EAAI,IAAM,EAAE,OAGtE,GAAGC,CAAS,QAAQA,IAAc,EAAI,IAAM,EAAE,MACvD,EAEA,MAAO,CACL,KAAK,QAAU,CAAC,EACX,KAAA,cAAgB,KAAK,eAAiB,CAAC,EAC5C,KAAK,eAAiB,GACtB,KAAK,iBAAmB,GACxB,KAAK,gBAAkB,GACvB,KAAK,eAAiB,CAAE,mBAAoB,EAAG,gBAAiB,EAAG,oBAAqB,CAAE,EACrF,KAAA,sBAAwB,IAC7B,KAAK,mBAAqB,GAG1B,KAAK,wBAAwB,EAG7B,QAAQ,IAAI,CACV,KAAK,oBACF,KAAK,IAAM,CACV,KAAK,eAAiB,EAAA,CACvB,EACA,MAAO9I,GAAiB,CACf,QAAA,MAAM,gCAAiCA,CAAK,EACpD,KAAK,eAAiB,EAAA,CACvB,EACH,KAAK,sBACF,KAAK,IAAM,CACV,KAAK,iBAAmB,EAAA,CACzB,EACA,MAAOA,GAAiB,CACf,QAAA,MAAM,kCAAmCA,CAAK,EACtD,KAAK,iBAAmB,EAAA,CACzB,EACH,KAAK,uBACF,KAAK,IAAM,CACV,KAAK,sBAAsB,EAC3B,KAAK,gBAAkB,EAAA,CACxB,EACA,MAAOA,GAAe,CACb,QAAA,MAAM,mCAAoCA,CAAK,EACvD,KAAK,gBAAkB,EACxB,CAAA,CAAA,CACJ,EAAE,MAAeA,GAAA,CACR,QAAA,MAAM,+BAAgCA,CAAK,CAAA,CACpD,EAGD,YAAY,IAAM,CAChB,KAAK,oBAAoB,CAAA,EACxB,EAAI,GAAK,GAAI,EAGT,OAAA,iBAAiB,kBAAqBmC,GAAiB,CAC5D,MAAM4G,EAAc5G,EACf,KAAA,qBAAqB4G,EAAY,MAAM,CAAA,CAC3B,EAEZ,OAAA,iBAAiB,qBAAwB5G,GAAiB,CAC/D,MAAM4G,EAAc5G,EACf,KAAA,cAAgB4G,EAAY,OAAO,UACnC,KAAA,YAAY,aAAeA,EAAY,OAAO,SAAA,CAClC,EAGZ,OAAA,iBAAiB,sBAAyB5G,GAAiB,CAChE,MAAM4G,EAAc5G,EACf,KAAA,qBAAqB4G,EAAY,MAAM,EAC5C,KAAK,OAAS,QAAA,CACG,EAEZ,OAAA,iBAAiB,oBAAuB5G,GAAiB,CAC9D,MAAM4G,EAAc5G,EACf,KAAA,qBAAqB4G,EAAY,MAAM,EAC5C,KAAK,OAAS,UAAA,CACG,EAGnB,YAAY,IAAM,CAEZ,GAAA,CAAC,KAAK,mBAAoB,CAEtB,MAAAC,EAAe,IAAI,YAAY,0BAA2B,CAC9D,OAAQ,CACN,QAAS,QAAQ,KAAK,IAAK,CAAA,GAC3B,UAAW,iBAAA,CACb,CACD,EACD,OAAO,cAAcA,CAAY,CAAA,GAElC,GAAK,EAGD,OAAA,iBAAiB,0BAA6B7G,GAAiB,CACpE,MAAM4G,EAAc5G,EAEhB4G,EAAY,OAAO,SACrB,KAAK,kBAAkB,IAAIA,EAAY,OAAO,OAAO,EAIvD,KAAK,mBAAqB,GAG1B,QAAQ,IAAI,CAEV,KAAK,kBAAA,EAAoB,MAAe/I,GAAA,CAC9B,QAAA,MAAM,kCAAmCA,CAAK,CAAA,CACvD,EAED,KAAK,oBAAA,EAAsB,MAAeA,GAAA,CAChC,QAAA,MAAM,oCAAqCA,CAAK,CAAA,CACzD,EAED,KAAK,qBAAqB,EAAK,EAAE,KAAK,IAAM,CAC1C,KAAK,eAAe,CAAA,CACrB,EAAE,MAAeA,GAAA,CACR,QAAA,MAAM,2BAA4BA,CAAK,CAChD,CAAA,CAAA,CACF,EAAE,QAAQ,IAAM,CAEf,KAAK,mBAAqB,EAAA,CAC3B,CAAA,CACgB,EAEnB,KAAK,UAAU,IAAM,CACnB,KAAK,oBAAoB,CAAA,CAC1B,CACH,EAEA,yBAA0B,CAEpB,KAAK,oBACP,cAAc,KAAK,kBAAkB,EAIlC,KAAA,mBAAqB,OAAO,YAAY,IAAM,CAE7C,KAAK,QAAQ,OAAS,IAExB,KAAK,QAAU,KAAK,QAAQ,IAAeiJ,IAAA,CACzC,GAAGA,EAEH,UAAWA,EAAO,SAAA,EAClB,IAEH,GAAK,CACV,EAEA,MAAM,qBAAsB,CACtB,GAAA,CACI,MAAA5J,EAAW,MAAM,MAAM,sBAAsB,EAE/C,GAAA,CAACA,EAAS,GACZ,MAAM,IAAI,MAAM,uBAAuBA,EAAS,MAAM,EAAE,EAGpD,MAAAC,EAAO,MAAMD,EAAS,KAAK,EAE7BC,IACF,KAAK,eAAiB,CACpB,mBAAoBA,EAAK,oBAAsB,EAC/C,gBAAiBA,EAAK,iBAAmB,EACzC,oBAAqBA,EAAK,qBAAuB,EACjD,mBAAoBA,EAAK,oBAAsB,CACjD,SAEKU,EAAO,CACN,QAAA,MAAM,kCAAmCA,CAAK,EAEtD,KAAK,eAAiB,CACpB,mBAAoB,EACpB,gBAAiB,EACjB,oBAAqB,EACrB,mBAAoB,CACtB,CAAA,QACA,CACA,KAAK,iBAAmB,EAAA,CAE5B,EAEA,qBAAsB,CACd,MAAAkJ,EAAkB,SAAS,cAAc,yBAAyB,EACxE,GAAI,CAACA,EAAiB,OAEhB,MAAAC,EAAiB,SAAS,cAAc,mCAAmC,EAC7EA,IACFA,EAAe,gBAAgB,sBAAsB,EACtCA,EAAA,aAAa,SAAU,MAAM,GAGxC,MAAAC,EAAe,SAAS,eAAe,wBAAwB,EAErE,IAAIC,EAAY,GACZC,EAA+B,KAC/BC,EAAkB,EACtB,MAAMC,EAAuB,IAEbN,EAAA,iBAAiB,SAAU,IAAM,CAC3CI,GACF,OAAO,aAAaA,CAAa,EAGnBA,EAAA,OAAO,WAAW,IAAM,CACtC,GAAID,GAAa,CAAC,KAAK,MAAM,aAAe,KAAK,QAAQ,OAAS,KAAK,MAAM,aAAe,CAAC,KAAK,cAChG,OAGF,KAAM,CAAE,UAAAI,EAAW,aAAAC,EAAc,aAAAC,CAAiB,EAAAT,EAOlD,IAL4BO,EAAYE,GAAgBD,EAEtC,GAGkB,CAC5B,MAAAjF,EAAM,KAAK,IAAI,EACjB,GAAAA,EAAM8E,EAAkBC,EAC1B,OAGUH,EAAA,GACME,EAAA9E,EAEd2E,GACWA,EAAA,UAAU,OAAO,QAAQ,EAGnC,KAAA,iBAAiB,QAAQ,IAAM,CACtBC,EAAA,GAERD,GACWA,EAAA,UAAU,IAAI,QAAQ,CACrC,CACD,CAAA,GAEF,GAAG,CAAA,CACP,CACH,EAEA,MAAM,mBAAoB,CACpB,GAAA,CACI,MAAA/J,EAAW,MAAM,MAAM,aAAa,EAEtC,GAAA,CAACA,EAAS,GACZ,MAAM,IAAI,MAAM,uBAAuBA,EAAS,MAAM,EAAE,EAGpD,MAAAC,EAAO,MAAMD,EAAS,KAAK,EAE5B,KAAA,oBAAsBC,EAAK,gBAAgB,mBAC3C,KAAA,kBAAoBA,EAAK,gBAAgB,oBACzC,KAAA,YAAcA,EAAK,mBAAqB,QAG7C,MAAMsK,EAAmB,IAAI,IAC3B,KAAK,MAAM,IAAYC,GAAA,CAACA,EAAK,GAAI,CAC/B,gBAAiBA,EAAK,gBACtB,SAAUA,EAAK,SACf,kBAAmBA,EAAK,iBAAA,CACzB,CAAC,CACJ,EAEMC,EAAwBxK,EAAK,MAAM,IAAKuK,GAAc,CAC1D,MAAME,EAAeH,EAAiB,IAAIC,EAAK,KAAK,EAC7C,MAAA,CACL,GAAIA,EAAK,MACT,MAAOA,EAAK,MACZ,WAAYA,EAAK,YAAc,GAC/B,UAAWA,EAAK,WAAa,GAC7B,SAAUA,EAAK,MAAM,MAAM,GAAG,EAAE,CAAC,EACjC,aAAcA,EAAK,aACnB,iBAAkBA,EAAK,kBAAoB,CAAC,EAC5C,yBAA0BA,EAAK,0BAA4B,CAAC,EAC5D,UAAWA,EAAK,WAAa,QAC7B,SAAUE,GAAc,UAAY,CAAC,EACrC,eAAgBF,EAAK,aAAe,EACpC,gBAAiBE,GAAc,iBAAmB,GAClD,gBAAiBF,EAAK,YAAc,EACpC,kBAAmBE,GAAc,mBAAqB,EACxD,CAAA,CACD,EAED,KAAK,MAAQD,EACb,KAAK,eAAiB,GACtB,KAAK,UAAY,GACjB,KAAK,QAAU,SAER9J,EAAO,CACN,QAAA,MAAM,gCAAiCA,CAAK,EACpD,KAAK,eAAiB,GACtB,KAAK,UAAY,EAAA,CAErB,EAEA,MAAM,qBAAqBgK,EAAQ,GAAM,CACnC,GAAA,CACEA,IACF,KAAK,WAAa,EAClB,KAAK,cAAgB,IAGjB,MAAAZ,EAAe,SAAS,eAAe,wBAAwB,EACjEA,GAAgBY,GACLZ,EAAA,UAAU,OAAO,QAAQ,EAGlC,MAAAa,EAAS,IAAI,gBAAgB,CACjC,MAAO,KAAK,YAAY,SAAS,EACjC,SAAU,KAAK,WAAa,GAAK,KAAK,aAAa,SAAS,CAAA,CAC7D,EAEG,KAAK,cAAc,OAAS,GAC9BA,EAAO,OAAO,cAAe,KAAK,cAAc,KAAK,GAAG,CAAC,EAKvD,CAACD,GAAS,KAAK,aAAe,GAEzBC,EAAA,IAAI,SAAU,GAAG,EAG1B,MAAM5K,EAAW,MAAM,MAAM,yBAAyB4K,EAAO,SAAU,CAAA,EAAE,EAErE,GAAA,CAAC5K,EAAS,GAAI,CAEhB,GAAIA,EAAS,SAAW,KAAO,CAAC2K,EAAO,CACrC,KAAK,cAAgB,GACf,MAAAb,EAAiB,SAAS,cAAc,mCAAmC,EAC7EA,GACaA,EAAA,UAAU,IAAI,QAAQ,EAEvC,MAAA,CAEF,MAAM,IAAI,MAAM,uBAAuB9J,EAAS,MAAM,EAAE,CAAA,CAGpD,MAAAC,EAAO,MAAMD,EAAS,KAAK,EAEjC,GAAIC,GAAQ,MAAM,QAAQA,EAAK,OAAO,EAAG,CAEjC,MAAA4K,MAAuB,IACvBC,EAAkD,CAAC,EAGpD7K,EAAA,QAAQ,QAAS6C,GAA+B,CAE/C,GAAAA,EAAM,aAAeA,EAAM,WAAW,SAAS,mBAAmB,GAAKA,EAAM,WAAW,SAAS,qBAAqB,GAAI,CAC5H,MAAMiI,EAAgBjI,EAAM,gBAAkBA,EAAM,SAAS,eACzDiI,GACGF,EAAiB,IAAIE,CAAa,GACpBF,EAAA,IAAIE,EAAe,EAAE,EAExCF,EAAiB,IAAIE,CAAa,GAAG,KAAKjI,CAAK,GAE/CgI,EAAoB,KAAKhI,CAAK,CAChC,MAGAgI,EAAoB,KAAKhI,CAAK,CAChC,CACD,EAGD,MAAMkI,EAA4C,CAAC,EAElCH,EAAA,QAAQ,CAACI,EAAQF,IAAkB,CAI9C,GAFJE,EAAO,KAAK,CAACpN,EAAGC,IAAM,IAAI,KAAKA,EAAE,SAAS,EAAE,QAAA,EAAY,IAAI,KAAKD,EAAE,SAAS,EAAE,SAAS,EAEnFoN,EAAO,SAAW,EAEAH,EAAA,KAAKG,EAAO,CAAC,CAAC,MAC7B,CAEC,MAAAC,EAAaD,EAAO,CAAC,EAGvB,IAAAE,EACAC,EAEAF,EAAW,WAAW,SAAS,mBAAmB,GACjCC,EAAA,4BACOC,EAAA,gCACjBF,EAAW,WAAW,SAAS,qBAAqB,GAC1CC,EAAA,8BACOC,EAAA,mCAGPD,EAAA,UACOC,EAAA,iBAI5B,MAAMC,EAAe,CACnB,GAAGH,EACH,GAAI,WAAWH,CAAa,GAC5B,WAAY,GACZ,cAAeE,EAAO,OACtB,eAAgBA,EAChB,WAAYE,EACZ,mBAAoBC,CACtB,EAEAJ,EAAc,KAAKK,CAAY,CAAA,CACjC,CACD,EAGD,MAAMC,EAAY,CAAC,GAAGN,EAAe,GAAGF,CAAmB,EAC3DQ,EAAU,KAAK,CAACzN,EAAGC,IAAM,IAAI,KAAKA,EAAE,SAAS,EAAE,QAAA,EAAY,IAAI,KAAKD,EAAE,SAAS,EAAE,SAAS,EAG1F,MAAM0N,EAAkBD,EAAU,IAAKxI,GAAqD,CACpF,MAAA0I,EAAY1I,EAAM,MAAQ,CAAC,EAC3B2I,EAAe3I,EAAM,SAAW,CAAC,EACjC4I,EAAY5I,EAAM,YAAc,GAChC6I,EAAmB7I,EAAM,oBAAsB4I,EAAU,MAAM,GAAG,EAAE,OAAS,QAGnF,IAAIE,EAAW,KAAK,WAAW9I,EAAM,MAAM,MAAQ,cAAc,EAGjE,MAAM+I,EAAa,KAAK,WAAWJ,EAAa,SAAS,MAAM,MAAQ,EAAE,EAGnE7J,EAAY,KAAK,WAAW6J,EAAa,SAAS,IAAM,EAAE,EAE1DK,EAAUhJ,EAAM,IAAM,OAAOA,EAAM,UAAU,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,EAAG,CAAC,CAAC,GAEjG,GAAI,KAAK,kBAAkB,IAAIgJ,CAAO,EAC7B,OAAA,KAGJ,KAAA,kBAAkB,IAAIA,CAAO,EAElC,IAAItF,EAAU,GACVuF,EAAc,GACdC,EAAa,GACbC,EAA8B,CAAC,EAE/B,GAAAP,EAAU,SAAS,2BAA2B,EAAG,CACrCK,EAAA,UACR,MAAAG,EAAgBpJ,EAAM,gBAAkB,CAAC,EACzCqJ,EAAQrJ,EAAM,eAAiBoJ,EAAc,OACnDF,EAAaG,EAAQ,EAGrB,MAAMC,EAAeF,EAAc,CAAC,GAAG,SAAW,CAAC,EAC7CG,EAAc,KAAK,WAAWD,EAAa,MAAQ,iBAAiB,EACpEE,EAAiB,KAAK,WAAWF,EAAa,SAAW,iBAAiB,EAC1EG,EAAiB,KAAK,WAAWL,EAAc,CAAC,GAAG,MAAM,iBAAmBE,EAAa,iBAAmB,yBAAyB,EACrII,EAAU,KAAK,WAAWJ,EAAa,SAAWxK,GAAa,EAAE,EAEvE4E,EAAU,6BAA6BoF,CAAQ,+CAA+CS,CAAW,sEAAsEC,CAAc,UAGzLH,EAAQ,IACC3F,GAAA,kCAAkC2F,EAAQ,CAAC,wBAAwBA,EAAQ,EAAI,EAAI,IAAM,EAAE,IAGxG3F,GAAW,UAAU+F,CAAc,GAE/BC,IACFhG,GAAW,yCAAyCgG,CAAO,WAIlDP,EAAAC,EAAc,IAAK3I,IAAY,CACxC,KAAM,KAAK,WAAWA,EAAE,SAAS,MAAQ,SAAS,EAClD,QAAS,KAAK,WAAWA,EAAE,SAAS,SAAW,SAAS,EACxD,gBAAiB,KAAK,WAAWA,EAAE,MAAM,iBAAmBA,EAAE,SAAS,iBAAmB,SAAS,EACnG,QAAS,KAAK,WAAWA,EAAE,SAAS,SAAW3B,GAAa,EAAE,EAC9D,aAAc,KAAK,WAAW2B,EAAE,SAAS,cAAgB,EAAE,EAC3D,aAAcA,EAAE,SAAA,EAChB,CAEK,SAAAmI,EAAU,SAAS,6BAA6B,EAAG,CAC5CK,EAAA,OACR,MAAAG,EAAgBpJ,EAAM,gBAAkB,CAAC,EACzCqJ,EAAQrJ,EAAM,eAAiBoJ,EAAc,OACnDF,EAAaG,EAAQ,EAGrB,MAAMC,EAAeF,EAAc,CAAC,GAAG,SAAW,CAAC,EAC7CG,EAAc,KAAK,WAAWD,EAAa,MAAQF,EAAc,CAAC,GAAG,MAAM,cAAgB,iBAAiB,EAC5GI,EAAiB,KAAK,WAAWF,EAAa,SAAWF,EAAc,CAAC,GAAG,MAAM,SAAW,iBAAiB,EAC7GK,EAAiB,KAAK,WAAWL,EAAc,CAAC,GAAG,MAAM,MAAQA,EAAc,CAAC,GAAG,MAAM,iBAAmBE,EAAa,iBAAmB,yBAAyB,EACrKI,EAAU,KAAK,WAAWJ,EAAa,SAAWxK,GAAa,EAAE,EAEvE4E,EAAU,6BAA6BoF,CAAQ,iDAAiDS,CAAW,oEAAoEC,CAAc,UAGzLH,EAAQ,IACC3F,GAAA,kCAAkC2F,EAAQ,CAAC,wBAAwBA,EAAQ,EAAI,EAAI,IAAM,EAAE,IAGxG3F,GAAW,UAAU+F,CAAc,GAE/BC,IACFhG,GAAW,2CAA2CgG,CAAO,WAIpDP,EAAAC,EAAc,IAAK3I,IAAY,CACxC,KAAM,KAAK,WAAWA,EAAE,SAAS,MAAQA,EAAE,MAAM,cAAgB,SAAS,EAC1E,QAAS,KAAK,WAAWA,EAAE,SAAS,SAAWA,EAAE,MAAM,SAAW,SAAS,EAC3E,gBAAiB,KAAK,WAAWA,EAAE,MAAM,MAAQA,EAAE,MAAM,iBAAmBA,EAAE,SAAS,iBAAmB,SAAS,EACnH,QAAS,KAAK,WAAWA,EAAE,SAAS,SAAW3B,GAAa,EAAE,EAC9D,aAAc,KAAK,WAAW2B,EAAE,SAAS,cAAgB,EAAE,EAC3D,aAAcA,EAAE,SAAA,EAChB,CAEK,SAAAmI,EAAU,SAAS,mBAAmB,EAAG,CAClCK,EAAA,UACDC,EAAA,GAEP,MAAAS,EAAc3J,EAAM,SAAW,CAAC,EAChCuJ,EAAc,KAAK,WAAWI,EAAY,MAAQ,iBAAiB,EACnEH,EAAiB,KAAK,WAAWG,EAAY,SAAW,iBAAiB,EACzEF,EAAiB,KAAK,WAAWzJ,EAAM,MAAM,iBAAmB2J,EAAY,iBAAmB,yBAAyB,EACxHD,EAAU,KAAK,WAAWC,EAAY,SAAW7K,GAAa,EAAE,EAEtE4E,EAAU,6BAA6BoF,CAAQ,+CAA+CS,CAAW,sEAAsEC,CAAc,iBAAiBC,CAAc,GAExNC,IACFhG,GAAW,yCAAyCgG,CAAO,WAI7DP,EAAW,CAAC,CACV,KAAMI,EACN,QAASC,EACT,gBAAiBC,EACjB,QAAAC,EACA,aAAc,KAAK,WAAWC,EAAY,cAAgB,EAAE,EAC5D,aAAc3J,EAAM,SAAA,CACrB,CAEM,SAAA4I,EAAU,SAAS,iBAAiB,EAAG,CAChCK,EAAA,UACR,MAAAU,EAAc3J,EAAM,SAAW,CAAC,EAChCuJ,EAAc,KAAK,WAAWI,EAAY,MAAQ3J,EAAM,MAAM,cAAgB,iBAAiB,EAC/FwJ,EAAiB,KAAK,WAAWG,EAAY,SAAW3J,EAAM,MAAM,SAAW,iBAAiB,EAChGyJ,EAAiB,KAAK,WAAWzJ,EAAM,MAAM,iBAAmB2J,EAAY,iBAAmB,yBAAyB,EACxHD,EAAU,KAAK,WAAWC,EAAY,SAAW7K,GAAa,EAAE,EAChEZ,EAAS,KAAK,WAAWyL,EAAY,QAAU3J,EAAM,MAAM,QAAU,EAAE,EAE7E0D,EAAU,mDAAmDoF,CAAQ,8CAA8CS,CAAW,oEAAoEC,CAAc,eAAeC,CAAc,GAEzOC,IACFhG,GAAW,yCAAyCgG,CAAO,WAGzDxL,IACFwF,GAAW,+EAA+ExF,CAAM,UAG3F,SAAA0K,EAAU,SAAS,qBAAqB,EAAG,CACpCK,EAAA,OAER,MAAAU,EAAc3J,EAAM,SAAW,CAAC,EAChCuJ,EAAc,KAAK,WAAWI,EAAY,MAAQ3J,EAAM,MAAM,cAAgB,iBAAiB,EAC/FwJ,EAAiB,KAAK,WAAWG,EAAY,SAAW3J,EAAM,MAAM,SAAW,iBAAiB,EAChGyJ,EAAiB,KAAK,WAAWzJ,EAAM,MAAM,MAAQA,EAAM,MAAM,iBAAmB2J,EAAY,iBAAmB,yBAAyB,EAC5ID,EAAU,KAAK,WAAWC,EAAY,SAAW7K,GAAa,EAAE,EACzDoK,EAAA,GAEbxF,EAAU,6BAA6BoF,CAAQ,iDAAiDS,CAAW,oEAAoEC,CAAc,iBAAiBC,CAAc,GAExNC,IACFhG,GAAW,2CAA2CgG,CAAO,WAI/DP,EAAW,CAAC,CACV,KAAMI,EACN,QAASC,EACT,gBAAiBC,EACjB,QAAAC,EACA,aAAc,KAAK,WAAWC,EAAY,cAAgB,EAAE,EAC5D,aAAc3J,EAAM,SAAA,CACrB,CAEM,SAAA4I,EAAU,SAAS,iBAAiB,EAAG,CAChCK,EAAA,UAER,MAAAU,EAAc3J,EAAM,SAAW,CAAC,EAChCuJ,EAAc,KAAK,WAAWI,EAAY,MAAQ3J,EAAM,MAAM,cAAgB,iBAAiB,EAC/FwJ,EAAiB,KAAK,WAAWG,EAAY,SAAW3J,EAAM,MAAM,iBAAmBA,EAAM,MAAM,SAAW,iBAAiB,EAC/H4J,EAAkB,KAAK,WAAWD,EAAY,kBAAoB3J,EAAM,MAAM,kBAAoB,EAAE,EACpGyJ,EAAiB,KAAK,WAAWzJ,EAAM,MAAM,iBAAmB2J,EAAY,iBAAmB,yBAAyB,EACxHD,EAAU,KAAK,WAAWC,EAAY,SAAW7K,GAAa,EAAE,EAE5D4E,EAAA,6BAA6BoF,CAAQ,6CAA6CS,CAAW,UAEnGK,IACFlG,GAAW,kEAAkEkG,CAAe,WAGnFlG,GAAA,kEAAkE8F,CAAc,iBAAiBC,CAAc,GAEtHC,IACFhG,GAAW,yCAAyCgG,CAAO,UAGtD,SAAAd,EAAU,SAAS,qBAAqB,EACjCK,EAAA,UACdvF,EAAU,6BAA6BoF,CAAQ,6CAExCF,EAAU,SAAS,mBAAmB,EAAG,CAClCK,EAAA,QACd,MAAM/K,EAAS,KAAK,WAAW8B,EAAM,MAAM,QAAU,EAAE,EACvD0D,EAAU,6BAA6BoF,CAAQ,mCAC3C5K,IACFwF,GAAW,8DAA8DxF,CAAM,UAG1E,SAAA0K,EAAU,SAAS,oBAAoB,EAChCK,EAAA,OACdvF,EAAU,4DAA4DoF,CAAQ,UAC1EC,IACFrF,GAAW,wCAAwCqF,CAAU,mBAGxDH,EAAU,SAAS,kBAAkB,EAAG,CACjCK,EAAA,UACd,MAAMY,EAAc,KAAK,WAAW7J,EAAM,MAAM,cAAgB,iBAAiB,EACvE0D,EAAA,6BAA6BoF,CAAQ,gMAAgMe,CAAW,SAEnP,SAAAjB,EAAU,SAAS,eAAe,EAAG,CAC9BK,EAAA,QACd,MAAMY,EAAc,KAAK,WAAW7J,EAAM,MAAM,cAAgB,iBAAiB,EAC3E8J,EAAe,KAAK,WAAW9J,EAAM,MAAM,aAAa,EACpD0D,EAAA,6BAA6BoF,CAAQ,iNAAiNe,CAAW,UACvQC,IACFpG,GAAW,8EAA8EoG,CAAY,UACvG,MAIUpG,EAAA,GAAGmF,CAAgB,iCAAiCC,CAAQ,UAGjE,MAAA,CACL,KAAMG,EACN,QAAAvF,EACA,UAAW1D,EAAM,UACjB,QAAAgJ,EACA,MAAO,CAACnB,GAAS,KAAK,aAAe,GAAK,CAAC,KAAK,kBAAkB,IAAImB,CAAO,EAC7E,WAAAE,EACA,SAAU,GACV,SAAAC,EACA,UAAW,CACT,KAAMT,EACN,QAASC,EACT,WAAYC,EACZ,mBAAoBC,EACpB,OAAQ7I,EAAM,QAAU,UACxB,UAAWA,EAAM,SAAA,CAErB,CACD,CAAA,EAAE,OAAQA,GAAkCA,IAAU,IAAI,EAIrD+J,EAAsBtB,EAAgB,OACtCuB,EAAqB7M,EAAK,QAAQ,OAWxC,GAPI4M,EAAsBC,EAAqB,IAAOA,IAAuB,KAAK,YAChF,KAAK,cAAgB,GAGrB,KAAK,cAAgB7M,EAAK,QAAQ,SAAW,KAAK,YAGhD0K,EAEF,KAAK,QAAUY,UACN,KAAK,aAAe,EAAG,CAG1B,MAAAwB,EAAmB,IAAI,IAAI,KAAK,QAAQ,IAAKjK,GAAyBA,EAAM,OAAO,CAAC,EACpFkK,EAAkBzB,EAAgB,OAAQzI,GAAyB,CAACiK,EAAiB,IAAIjK,EAAM,OAAO,CAAC,EAEzGkK,EAAgB,OAAS,GAE3B,WAAW,IAAM,CACf,KAAK,QAAU,CAAC,GAAGA,EAAiB,GAAG,KAAK,OAAO,EACnD,KAAK,eAAe,GACnB,EAAE,CACP,MAGA,KAAK,QAAU,CAAC,GAAG,KAAK,QAAS,GAAGzB,CAAe,EAGrD,KAAK,sBAAsB,EAErB,MAAAzB,EAAiB,SAAS,cAAc,mCAAmC,EAC7EA,IACG,KAAK,cAGOA,EAAA,UAAU,OAAO,QAAQ,EAFzBA,EAAA,UAAU,IAAI,QAAQ,EAIzC,SAEA,KAAK,cAAgB,GACjB,CAACa,EAAO,CACJ,MAAAb,EAAiB,SAAS,cAAc,mCAAmC,EAC7EA,GACaA,EAAA,UAAU,IAAI,QAAQ,CACvC,QAGGnJ,EAAgB,CACf,QAAA,MAAM,mCAAoCA,CAAK,EACvD,KAAK,cAAgB,GAErB,KAAK,QAAU,CAAC,CACd,KAAM,QACN,QAAS,yBAAyBA,aAAiB,MAAQA,EAAM,QAAU,eAAe,oCAC1F,UAAW,KAAK,WAAW,IAAI,IAAM,EACrC,QAAS,cACT,MAAO,EAAA,CACR,EAEK,MAAAmC,EAAQ,IAAI,YAAY,SAAU,CACtC,QAAS,GACT,OAAQ,CACN,KAAM,QACN,QAAS,kCACT,gBAAiB,GAAA,CACnB,CACD,EACD,OAAO,cAAcA,CAAK,CAAA,QAC1B,CACA,KAAK,gBAAkB,GAGjB,MAAAiH,EAAe,SAAS,eAAe,wBAAwB,EACjEA,GAAgBY,GACLZ,EAAA,UAAU,IAAI,QAAQ,CACrC,CAEJ,EAEA,MAAM,gBAAiB,CAErB,GAAI,MAAK,cAIL,GAAA,CACI,MAAAA,EAAe,SAAS,eAAe,wBAAwB,EACjEA,GACWA,EAAA,UAAU,OAAO,QAAQ,EAGnC,KAAA,aACL,KAAK,cAAgB,GAEf,MAAA,KAAK,qBAAqB,EAAK,QAC9BpJ,EAAO,CACN,QAAA,MAAM,6BAA8BA,CAAK,CAAA,QACjD,CACA,KAAK,cAAgB,EAAA,CAEzB,EAEA,uBAAwB,CACtB,KAAK,iBAAmB,CACtB,QAAS,GACT,MAAO,GACP,KAAM,GACN,QAAS,GACT,QAAS,EACX,CACF,EAEA,uBAAwB,CACtB,GAAI,CAAC,MAAM,QAAQ,KAAK,OAAO,EAAG,CAChC,KAAK,QAAU,CAAC,EAChB,MAAA,CAGI,MAAAsM,EAAe,OAAO,QAAQ,KAAK,kBAAoB,CAAA,CAAE,EAC5D,OAAO,CAAC,CAACrH,EAAGsH,CAAO,IAAMA,CAAO,EAChC,IAAI,CAAC,CAACC,CAAI,IAAMA,CAAI,EAEjBC,EAAkB,KAAK,QAAQ,OAAQxD,GAC3CA,GAAUA,EAAO,MAAQqD,EAAa,SAASrD,EAAO,IAAI,CAC5D,EAEIwD,EAAgB,SAAW,GAAK,KAAK,QAAQ,OAAS,EACnD,KAAA,QAAQ,QAAkBxD,GAAA,EACzB,CAACA,EAAO,MAAQ,CAACqD,EAAa,SAASrD,EAAO,IAAI,KACpDA,EAAO,KAAO,OAChB,CACD,EAED,KAAK,QAAUwD,EAGjB,KAAK,cAAgBH,CACvB,EAEA,MAAM,wBAAyB,CACvB,MAAA,KAAK,qBAAqB,EAAK,CACvC,EAEA,cAAe,CACb,OAAO,SAAS,OACb,MAAM,IAAI,EACV,KAAYjP,GAAAA,EAAI,WAAW,YAAY,CAAC,GACvC,MAAM,GAAG,EAAE,CAAC,GAAK,EACvB,EAEA,kBAAkBqP,EAAgB,CAChC,MAAM7C,EAAO,KAAK,MAAM,KAAU8C,GAAAA,EAAE,KAAOD,CAAM,EACjD,GAAI,CAAC7C,EAAM,OAEX,MAAMxM,EAAM,SAAS,eAAe,GAAGqP,CAAM,UAAU,EACjDE,EAAU,SAAS,eAAe,GAAGF,CAAM,UAAU,EAE3D,GAAI,CAACrP,EAAK,OAEV,MAAMwP,EAAWxP,EAAI,UAAU,SAAS,QAAQ,EAQhD,GAPIA,EAAA,UAAU,OAAO,QAAQ,EAEzBuP,IACMA,EAAA,MAAM,UAAYC,EAAW,gBAAkB,IAIrDA,EAAU,CACZ,MAAMC,EAAY,SAAS,eAAe,GAAGJ,CAAM,iBAAiB,EAEhEI,IACFA,EAAU,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aA4BnB,KAAA,iBAAiBjD,EAAK,KAAK,CAAA,CAEpC,EAEA,yBAAyB6C,EAAgB,CACjC,MAAA7C,EAAO,KAAK,MAAM,KAAM8C,GAAoBA,EAAE,KAAOD,CAAM,EACjE,GAAI,CAAC7C,EAAM,OAENA,EAAA,gBAAkB,CAACA,EAAK,gBAE7B,MAAMiD,EAAY,SAAS,eAAe,GAAGJ,CAAM,iBAAiB,EACpE,GAAII,EAAW,CACbA,EAAU,MAAM,QAAU,IAC1BA,EAAU,MAAM,WAAa,qBAG7B,MAAMC,EADc,SAAS,eAAe,cAAc,GAC1B,MAAM,YAAiB,GAAA,GAEvD,WAAW,IAAM,CACLD,EAAA,UAAY,KAAK,oBAAoBjD,CAAI,EAE9CiD,EAAU,aAEfA,EAAU,MAAM,QAAU,IAE1B,WAAW,IAAM,CACXC,IACG,KAAA,0BAA0BL,EAAQK,CAAU,EAEjD,WAAW,IAAM,CAEX,CADoBD,EAAU,cAAc,mBAAmB,GAC3CC,GACjB,KAAA,0BAA0BL,EAAQK,CAAU,GAElD,GAAG,IAEP,GAAG,GACL,EAAE,CAAA,CAET,EAEA,qBAAqBzN,EAAayN,EAA0B,CAC1D,MAAMC,EAAwC,CAAC,EAC1C1N,EAAA,QAAS2N,GAAa,CACrBA,EAAI,aACDD,EAAeC,EAAI,UAAU,IACjBD,EAAAC,EAAI,UAAU,EAAI,CAAC,GAEpCD,EAAeC,EAAI,UAAU,EAAE,KAAKA,CAAG,EACzC,CACD,EAEI,KAAA,MAAM,QAAgBpD,GAAA,CACzB,MAAMqD,EAAU,SAAS,cAAc,kBAAkBrD,EAAK,EAAE,IAAI,EAChEqD,GACMA,EAAA,UAAU,OAAO,SAAS,EAGpC,MAAMJ,EAAY,SAAS,eAAe,GAAGjD,EAAK,EAAE,iBAAiB,EACrE,GAAI,CAACiD,EAAW,OAEhB,MAAMK,EAAeH,EAAenD,EAAK,KAAK,GAAK,CAAC,EAEhD,GAAAsD,EAAa,OAAS,EAAG,CAC3B,GAAID,EAAS,CACX,MAAME,EAAiBF,EACvBE,EAAe,MAAM,QAAU,GAC/BA,EAAe,MAAM,QAAU,IACvBF,EAAA,UAAU,IAAI,gBAAgB,CAAA,CAGxC,MAAMG,EAAa,SAAS,eAAe,GAAGxD,EAAK,EAAE,UAAU,EACzD+C,EAAU,SAAS,eAAe,GAAG/C,EAAK,EAAE,UAAU,EACxDwD,IACSA,EAAA,UAAU,OAAO,QAAQ,EACzBA,EAAA,UAAU,IAAI,yBAAyB,EAE9CT,IACFA,EAAQ,MAAM,UAAY,kBAKxB,MAAAU,EAAW,KAAK,MAAM,QAAUX,EAAE,KAAO9C,EAAK,EAAE,EAClDyD,IACFA,EAAS,gBAAkB,IAG7B,MAAMC,EAAcJ,EAAa,IAAKF,GAAa;AAAA;AAAA,gDAEb,KAAK,WAAWA,EAAI,MAAQ,SAAS,CAAC;AAAA,sCAChD,KAAK,WAAWA,EAAI,SAAW,SAAS,CAAC;AAAA,sCACzC,KAAK,WAAWA,EAAI,SAAW,SAAS,CAAC;AAAA,sCACzC,KAAK,WAAWA,EAAI,iBAAmB,SAAS,CAAC;AAAA,sCACjD,KAAK,WAAWA,EAAI,cAAgB,SAAS,CAAC;AAAA,sCAC9C,KAAK,gBAAgBA,EAAI,YAAY,GAAK,OAAO;AAAA;AAAA,WAE5E,EAAE,KAAK,EAAE,EAEVH,EAAU,UAAYS,EAEJT,EAAU,iBAAiB,YAAY,EAC/C,QAAgBU,GAAA,CAClB,MAAAC,EAAUD,EAAK,aAAe,GAC9BE,EAAeD,EAAQ,YAAY,EACnCE,EAAkBZ,EAAW,YAAY,EAE3C,GAAAW,EAAa,SAASC,CAAe,EAAG,CAC1C,MAAMC,EAAqBH,EAAQ,QACjC,IAAI,OAAO,KAAK,WAAWV,CAAU,EAAE,QAAQ,sBAAuB,MAAM,EAC5E,IAAI,EACHnN,GAAkB,kCAAkC,KAAK,WAAWA,CAAK,CAAC,SAC7E,EACA4N,EAAK,UAAYI,CAAA,CACnB,CACD,CAAA,KACI,CACC,MAAAC,EAAkBf,EAAU,aAAa,uBAAuB,EAClEe,EACFf,EAAU,UAAYe,EAEtBf,EAAU,UAAY,EACxB,CACF,CACD,CACH,EAEA,aAAc,CAEZ,GAAI,KAAK,eACP,OAGI,MAAAgB,EAAc,SAAS,cAAgC,8BAA8B,EAC3F,GAAI,CAACA,EAAa,CAChB,QAAQ,KAAK,wBAAwB,EACrC,MAAA,CAGF,MAAMf,EAAae,EAAY,MAAM,KAAA,EAAO,YAAY,EAGxD,GAAI,CAACf,EAAY,CACf,KAAK,gBAAgB,EAGhB,KAAA,MAAM,QAAgBlD,GAAA,CAEzBA,EAAK,SAAW,CAAC,EAEjB,MAAMqD,EAAU,SAAS,cAAc,kBAAkBrD,EAAK,EAAE,IAAI,EAChEqD,IACDA,EAAwB,MAAM,QAAU,GACxCA,EAAwB,MAAM,QAAU,IACjCA,EAAA,UAAU,OAAO,gBAAgB,GAG3C,MAAMG,EAAa,SAAS,eAAe,GAAGxD,EAAK,EAAE,UAAU,EAC3DwD,IACSA,EAAA,UAAU,IAAI,QAAQ,EACtBA,EAAA,UAAU,OAAO,yBAAyB,EAC1CA,EAAA,UAAU,OAAO,uBAAuB,GAGrD,MAAMT,EAAU,SAAS,eAAe,GAAG/C,EAAK,EAAE,UAAU,EACxD+C,IACFA,EAAQ,MAAM,UAAY,GAC5B,CACD,EAED,MAAA,CAII,MAAAmB,EAAmB,SAAS,cAAc,KAAK,EACrDA,EAAiB,UAAY,2BAC7BA,EAAiB,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA,QAMjBD,EAAA,eAAe,YAAYC,CAAgB,EAGlD,KAAA,MAAM,QAAgBlE,GAAA,CACzB,MAAMqD,EAAU,SAAS,cAAc,kBAAkBrD,EAAK,EAAE,IAAI,EAChEqD,IACDA,EAAwB,MAAM,QAAU,OACxCA,EAAwB,MAAM,QAAU,IACjCA,EAAA,UAAU,OAAO,gBAAgB,EAC3C,CACD,EAGK,MAAAc,MAA8B,IAG/B,KAAA,MAAM,QAAgBnE,GAAA,CACzB,MAAM6C,EAAS7C,EAAK,GACdqD,EAAU,SAAS,cAAc,kBAAkBR,CAAM,IAAI,EACnE,GAAI,CAACQ,EAAS,OAWd,GARiB,GAAGrD,EAAK,UAAU,IAAIA,EAAK,SAAS,IAAIA,EAAK,KAAK,GAAG,YAAY,EACrD,SAASkD,CAAU,IAG7CG,EAAwB,MAAM,QAAU,GACxCA,EAAwB,MAAM,QAAU,KAGvCrD,EAAK,UAAYA,EAAK,SAAS,OAAS,EAAG,CAC7C,IAAIoE,EAAiB,GAgBrB,GAdKpE,EAAA,SAAS,QAAeoD,GAAA,EAExBA,EAAI,MAAQA,EAAI,KAAK,cAAc,SAASF,CAAU,GACtDE,EAAI,SAAWA,EAAI,QAAQ,cAAc,SAASF,CAAU,GAC5DE,EAAI,SAAWA,EAAI,QAAQ,YAAY,EAAE,SAASF,CAAU,GAC5DE,EAAI,iBAAmBA,EAAI,gBAAgB,YAAY,EAAE,SAASF,CAAU,GAC5EE,EAAI,cAAgBA,EAAI,aAAa,YAAc,EAAA,SAASF,CAAU,GACtEE,EAAI,cAAgBA,EAAI,aAAa,YAAY,EAAE,SAASF,CAAU,KAEtDkB,EAAA,GACjBD,EAAwB,IAAItB,CAAM,EACpC,CACD,EAEGuB,EAAgB,CACjBf,EAAwB,MAAM,QAAU,GACxCA,EAAwB,MAAM,QAAU,IACjCA,EAAA,UAAU,IAAI,gBAAgB,EAEtC,MAAMG,EAAa,SAAS,eAAe,GAAGX,CAAM,UAAU,EACxDE,EAAU,SAAS,eAAe,GAAGF,CAAM,UAAU,EAE3D,GAAIW,EAAY,CACHA,EAAA,UAAU,OAAO,QAAQ,EACzBA,EAAA,UAAU,OAAO,wBAAwB,EACzCA,EAAA,UAAU,IAAI,yBAAyB,EACvCA,EAAA,UAAU,IAAI,uBAAuB,EAE5CT,IACFA,EAAQ,MAAM,UAAY,iBAGtB,MAAAsB,EAAgBb,EAAW,cAAc,OAAO,EAChDc,EAAe,SAAS,eAAe,GAAGzB,CAAM,iBAAiB,EAEnEwB,GAAiBC,IAClBD,EAA8B,MAAM,QAAU,QAC9CC,EAA6B,MAAM,QAAU,kBAEzC,KAAA,0BAA0BzB,EAAQK,CAAU,EACnD,CACF,CACF,CACF,CACD,EAEG,KAAK,qBACA,OAAA,aAAa,KAAK,mBAAmB,EAGzC,KAAA,oBAAsB,OAAO,WAAW,SAAY,CACnD,GAAA,CAEE,GAAAA,EAAW,QAAU,EAAG,CAE1B,MAAM1N,EAAW,MAAM,MAAM,0BAA0B,mBAAmB0N,CAAU,CAAC,EAAE,EAEnF,GAAA1N,EAAS,SAAW,IAChB,MAAA,IAAI,MAAM,mEAAmE,EAGjF,GAAA,CAACA,EAAS,GACZ,MAAM,IAAI,MAAM,uBAAuBA,EAAS,MAAM,EAAE,EAGpD,MAAAC,EAAO,MAAMD,EAAS,KAAK,EACjC,GAAIC,GAAQ,MAAM,QAAQA,CAAI,EAAG,CAC/B,MAAM0N,EAAwC,CAAC,EAC1C1N,EAAA,QAAS2N,GAAa,CACrBA,EAAI,aACDD,EAAeC,EAAI,UAAU,IACjBD,EAAAC,EAAI,UAAU,EAAI,CAAC,GAEpCD,EAAeC,EAAI,UAAU,EAAE,KAAKA,CAAG,EACzC,CACD,EAEK,MAAAmB,MAAsB,IAEvB,KAAA,MAAM,QAAgBvE,GAAA,CACnB,MAAAwE,MAAkB,IAEnBxE,EAAA,SAAS,QAAeoD,GAAA,CAC3B,MAAMtL,EAAM,GAAGsL,EAAI,IAAI,IAAIA,EAAI,OAAO,IAAIA,EAAI,OAAO,IAAIA,EAAI,eAAe,IAAIA,EAAI,YAAY,GAChGoB,EAAY,IAAI1M,CAAG,CAAA,CACpB,EAEeyM,EAAA,IAAIvE,EAAK,MAAOwE,CAAW,CAAA,CAC5C,EAED,IAAIC,EAAe,GACnB,KAAK,MAAQ,KAAK,MAAM,IAAYzE,GAAA,CAClC,MAAMwE,EAAcD,EAAgB,IAAIvE,EAAK,KAAK,OAAS,IAErDsD,EAAeH,EAAenD,EAAK,KAAK,GAAK,CAAC,EAEhD,GAAAsD,EAAa,OAAS,EAAG,CAU3B,MAAMoB,EATcpB,EAAa,IAAKxK,IAAY,CAChD,KAAMA,EAAE,KACR,QAASA,EAAE,SAAW,UACtB,QAASA,EAAE,SAAW,UACtB,gBAAiBA,EAAE,iBAAmB,UACtC,aAAcA,EAAE,cAAgB,UAChC,aAAcA,EAAE,YAAA,EAChB,EAEoC,OAAQsK,GAAyB,CACrE,MAAMtL,EAAM,GAAGsL,EAAI,IAAI,IAAIA,EAAI,OAAO,IAAIA,EAAI,OAAO,IAAIA,EAAI,eAAe,IAAIA,EAAI,YAAY,GAC5F,OAAAoB,EAAY,IAAI1M,CAAG,EACd,IAET0M,EAAY,IAAI1M,CAAG,EACZ,GAAA,CACR,EAEG,GAAA4M,EAAkB,OAAS,EACd,OAAAD,EAAA,GACR,CACL,GAAGzE,EACH,SAAU,CAAC,GAAGA,EAAK,SAAU,GAAG0E,CAAiB,CACnD,CACF,CAEK,OAAA1E,CAAA,CACR,EAEGyE,GACF,KAAK,UAAU,IAAM,CACd,KAAA,MAAM,QAAgBzE,GAAA,CACzB,GAAImD,EAAenD,EAAK,KAAK,GAAG,OAAS,EAAG,CAC1C,MAAMqD,EAAU,SAAS,cAAc,kBAAkBrD,EAAK,EAAE,IAAI,EAChEqD,IACFA,EAAQ,MAAM,QAAU,GACxBA,EAAQ,MAAM,QAAU,IAChBA,EAAA,UAAU,IAAI,gBAAgB,GAGxC,MAAMG,EAAa,SAAS,eAAe,GAAGxD,EAAK,EAAE,UAAU,EACzD+C,EAAU,SAAS,eAAe,GAAG/C,EAAK,EAAE,UAAU,EAExDwD,IACSA,EAAA,UAAU,OAAO,QAAQ,EACpCA,EAAW,MAAM,QAAU,GAEvBT,IACFA,EAAQ,MAAM,UAAY,kBAI9B,MAAME,EAAY,SAAS,eAAe,GAAGjD,EAAK,EAAE,iBAAiB,EACjEiD,IACQA,EAAA,UAAY,KAAK,oBAAoBjD,CAAI,EAE/CkD,GACG,KAAA,0BAA0BlD,EAAK,GAAIkD,CAAU,EAEtD,CACF,CACD,CAAA,CACF,CACH,CACF,QAEK/M,EAAO,CACN,QAAA,MAAM,4BAA6BA,CAAK,EAE1C,MAAAiM,EAAe,SAAS,cAAc,KAAK,EACjDA,EAAa,UAAY,iDACzBA,EAAa,YAAcjM,aAAiB,MAAQA,EAAM,QAAU,kCACxD8N,EAAA,eAAe,YAAY7B,CAAY,EAGnD,WAAW,IAAM,CACfA,EAAa,OAAO,GACnB,GAAI,CAAA,QACP,CAEA,MAAM8B,EAAmBD,EAAY,eAAe,cAAc,2BAA2B,EACzFC,GACFA,EAAiB,OAAO,CAC1B,GAED,GAAG,CACR,EAEA,0BAA0BrB,EAAgBK,EAAoB,CACxD,GAAA,CAACL,GAAU,CAACK,EAAY,OAE5B,MAAMD,EAAY,SAAS,eAAe,GAAGJ,CAAM,iBAAiB,EACpE,GAAI,CAACI,EAAW,CACN,QAAA,KAAK,4CAA4CJ,CAAM,EAAE,EACjE,MAAA,CAGFI,EAAU,MAAM,QAAU,kBAEpB,MAAA0B,EAAuB1B,EAAU,cAAc,iBAAiB,EAClE0B,GACFA,EAAqB,OAAO,EAGxB,MAAAjB,EAAcT,EAAU,iBAAiB,4CAA4C,EAC3F,IAAI2B,EAAa,EAiCjB,GA/BAlB,EAAY,QAAelQ,GAAA,CACzB,IAAIqR,EAAc,GAElBrR,EAAI,iBAAiB,IAAI,EAAE,QAAgBmQ,GAAA,CACnC,MAAAC,EAAUD,EAAK,aAAe,GAEpC,GAAIC,EAAQ,YAAY,EAAE,SAASV,EAAW,YAAA,CAAa,EAAG,CAC9C2B,EAAA,GACdD,IAEKjB,EAAK,aAAa,eAAe,GAC/BA,EAAA,aAAa,gBAAiBC,CAAO,EAG5C,MAAMG,EAAqBH,EAAQ,QACjC,IAAI,OAAO,KAAK,WAAWV,CAAU,EAAE,QAAQ,sBAAuB,MAAM,EAAG,IAAI,EAClFnN,GAAkB,kCAAkC,KAAK,WAAWA,CAAK,CAAC,SAC7E,EAEA4N,EAAK,UAAYI,CAAA,CACnB,CACD,EAEGc,GACDrR,EAAoB,MAAM,QAAU,YACjCA,EAAA,UAAU,IAAI,iBAAiB,GAElCA,EAAoB,MAAM,QAAU,MACvC,CACD,EAEGoR,IAAe,EAAG,CACd,MAAAE,EAAe,SAAS,cAAc,IAAI,EAChDA,EAAa,UAAY,iBACzBA,EAAa,UAAY;AAAA;AAAA,oCAEG,KAAK,WAAW5B,CAAU,CAAC;AAAA;AAAA,UAGvDD,EAAU,YAAY6B,CAAY,CAAA,CAEtC,EAEA,MAAM,eAAe5B,EAAsF,CACzG,OAAO,IAAI,QAAQ,MAAO6B,EAASC,IAAW,CACxC,GAAA,CAGF,GAAI,KAAK,YAAY,IAAI9B,CAAU,EAAG,CACpC,MAAM+B,EAAa,KAAK,YAAY,IAAI/B,CAAU,EAClD,GAAI,CAAC+B,EAAY,CACRD,EAAA,IAAI,MAAM,0BAA0B,CAAC,EAC5C,MAAA,CAIG,KAAA,qBAAqBC,EAAY/B,CAAU,EAGxC6B,EAAAE,EAAW,IAAKnM,IAAY,CAClC,WAAYA,EAAE,WACd,QAAS,CACP,KAAMA,EAAE,KACR,QAASA,EAAE,SAAW,UACtB,QAASA,EAAE,SAAW,UACtB,gBAAiBA,EAAE,iBAAmB,UACtC,aAAcA,EAAE,cAAgB,UAChC,aAAcA,EAAE,YAAA,GAElB,CAAC,EACH,MAAA,CAIF,MAAMtD,EAAW,MAAM,MAAM,0BAA0B,mBAAmB0N,CAAU,CAAC,EAAE,EACnF,GAAA,CAAC1N,EAAS,GACZ,MAAM,IAAI,MAAM,uBAAuBA,EAAS,MAAM,EAAE,EAGpD,MAAAC,EAAO,MAAMD,EAAS,KAAK,EAG5B,KAAA,YAAY,IAAI0N,EAAYzN,CAAI,EAGhC,KAAA,qBAAqBA,EAAMyN,CAAU,EAElC6B,EAAAtP,EAAK,IAAKqD,IAAY,CAC5B,WAAYA,EAAE,WACd,QAAS,CACP,KAAMA,EAAE,KACR,QAASA,EAAE,SAAW,UACtB,QAASA,EAAE,SAAW,UACtB,gBAAiBA,EAAE,iBAAmB,UACtC,aAAcA,EAAE,cAAgB,UAChC,aAAcA,EAAE,YAAA,GAElB,CAAC,QACI3C,EAAO,CACN,QAAA,MAAM,4BAA6BA,CAAK,EAE3C,KAAA,MAAM,QAAgB6J,GAAA,CACzB,MAAMqD,EAAU,SAAS,cAAc,kBAAkBrD,EAAK,EAAE,IAAI,EAChEqD,GACMA,EAAA,UAAU,OAAO,SAAS,EAGpC,MAAMJ,EAAY,SAAS,eAAe,GAAGjD,EAAK,EAAE,iBAAiB,EACrE,GAAIiD,EAAW,CACP,MAAAe,EAAkBf,EAAU,aAAa,uBAAuB,EAClEe,IACFf,EAAU,UAAYe,EACtBf,EAAU,gBAAgB,uBAAuB,EACnD,CACF,CACD,EAED+B,EAAO7O,CAAK,CAAA,CACd,CACD,CACH,EAEA,qBAAqBV,EAA8B,CACjD,GAAKA,EAWL,IATIA,EAAK,kBACF,KAAA,oBAAsBA,EAAK,gBAAgB,mBAC3C,KAAA,kBAAoBA,EAAK,gBAAgB,qBAG5CA,EAAK,oBACP,KAAK,YAAcA,EAAK,mBAGtBA,EAAK,MAAO,CACd,MAAMwK,EAAwBxK,EAAK,MAAM,IAAKuK,GAAc,CACpD,MAAAE,EAAe,KAAK,MAAM,QAAU4C,EAAE,QAAU9C,EAAK,KAAK,EACzD,MAAA,CACL,GAAIA,EAAK,MACT,MAAOA,EAAK,MACZ,WAAYA,EAAK,YAAc,GAC/B,UAAWA,EAAK,WAAa,GAC7B,SAAUA,EAAK,MAAM,MAAM,GAAG,EAAE,CAAC,EACjC,aAAcA,EAAK,aACnB,iBAAkBA,EAAK,kBAAoB,CAAC,EAC5C,yBAA0BA,EAAK,0BAA4B,CAAC,EAC5D,UAAWA,EAAK,WAAa,QAC7B,SAAUE,EAAe,CAAC,GAAGA,EAAa,QAAQ,EAAE,KAAK,CAAC7M,EAAGC,IAAM,IAAI,KAAKA,EAAE,YAAY,EAAE,QAAQ,EAAI,IAAI,KAAKD,EAAE,YAAY,EAAE,QAAS,CAAA,EAAI,CAAC,EAC/I,eAAgB2M,EAAK,aAAe,EACpC,gBAAiBE,EAAeA,EAAa,gBAAkB,GAC/D,gBAAiBF,EAAK,YAAc,EACpC,kBAAmB,EACrB,CAAA,CACD,EAED,KAAK,MAAQC,CAAA,CAGf,KAAK,UAAY,GACjB,KAAK,QAAU,GAGJ,UAAA3H,KAAS,KAAK,QAEnB,GAAAA,EAAM,OAAS,WACfA,EAAM,QAAQ,SAAS,WAAW,GAClCA,EAAM,QAAQ,SAAS,OAAO,IAC7BA,EAAM,QAAQ,SAAS,KAAK,GAAKA,EAAM,QAAQ,SAAS,eAAe,IAMtE,GAJJA,EAAM,WAAa,GACnBA,EAAM,SAAW,GAGbA,EAAM,WAAW,MAAM,SACzBA,EAAM,SAAW,MAAM,QAAQA,EAAM,UAAU,KAAK,QAAQ,EACxDA,EAAM,UAAU,KAAK,SACrB,CAACA,EAAM,UAAU,KAAK,QAAQ,UAG3BA,EAAM,WAAW,MAAM,cAAgBA,EAAM,WAAW,MAAM,gBAAiB,CAEtF,MAAM8K,EAAuB,CAC3B,KAAM9K,EAAM,UAAU,KAAK,aAC3B,QAASA,EAAM,UAAU,KAAK,gBAC9B,gBAAiBA,EAAM,UAAU,KAAK,iBAAmB,GACzD,QAASA,EAAM,UAAU,KAAK,SAAW,GACzC,aAAcA,EAAM,UAAU,KAAK,cAAgB,GACnD,aAAcA,EAAM,SACtB,EAKA,GAHMA,EAAA,SAAW,CAAC8K,CAAG,EAGjB9K,EAAM,QAAQ,SAAS,KAAK,EAAG,CAEjC,MAAMvC,EAAQuC,EAAM,QAAQ,MAAM,kCAAkC,EAChEvC,GAASA,EAAM,CAAC,GACS,SAASA,EAAM,CAAC,EAAG,EAAE,EAEvB,GAAKuC,EAAM,WAAW,MAAM,iBAC7CA,EAAA,SAAW,CAAC,GAAGA,EAAM,SAAU,GAAGA,EAAM,UAAU,KAAK,cAAc,EAE/E,CAIK,SAAAA,EAAM,QAAQ,SAAS,GAAG,EAAG,CACpC,MAAM4M,EAAe5M,EAAM,QAAQ,MAAM,oBAAoB,EAC7D,GAAI4M,EAAc,CAChB,KAAM,CAAG,CAAAjN,EAAMkN,CAAO,EAAID,EACpB9B,EAAuB,CAC3B,KAAAnL,EACA,QAAAkN,EACA,gBAAiB7M,EAAM,QAAQ,MAAM,kBAAkB,IAAI,CAAC,GAAK,GACjE,QAASA,EAAM,QAAQ,MAAM,oBAAoB,IAAI,CAAC,GAAK,GAC3D,aAAc,GACd,aAAcA,EAAM,SACtB,EACMA,EAAA,SAAW,CAAC8K,CAAG,CAAA,CACvB,GAIR,EAEA,uBAAuBgC,EAAwC,CACzD,CAACA,GAAmB,CAAC,MAAM,QAAQA,CAAe,IAEjD,KAAA,YAAY,iBAAmBA,EAAgB,OAEpDA,EAAgB,QAAehC,GAAA,CACvB,MAAA5G,EAAY4G,EAAI,YAAcA,EAAI,SAAS,SAAS,MAAM,MAAQA,EAAI,MAAM,MAClF,GAAI,CAAC5G,EAAW,OAEhB,MAAMwD,EAAO,KAAK,MAAM,KAAU8C,GAAAA,EAAE,QAAUtG,CAAS,EACvD,GAAI,CAACwD,EAAM,OAGX,GAAIoD,EAAI,QAAS,CACf,MAAMiC,EAAiB,CACrB,KAAMjC,EAAI,QAAQ,MAAQ,UAC1B,QAASA,EAAI,QAAQ,SAAW,UAChC,QAASA,EAAI,QAAQ,SAAWA,EAAI,SAAS,SAAS,IAAM,UAC5D,gBAAiBA,EAAI,QAAQ,iBAAmB,UAChD,aAAcA,EAAI,QAAQ,cAAgB,UAC1C,aAAcA,EAAI,aAClB,QAAS,EACX,EAEMkC,EAAgBtF,EAAK,SAAS,UAAUlH,GAC5CA,EAAE,OAASuM,EAAe,MAC1BvM,EAAE,UAAYuM,EAAe,SAC7BvM,EAAE,UAAYuM,EAAe,OAC/B,EAEIC,IAAkB,IACftF,EAAA,SAAS,KAAKqF,CAAc,EAC5BrF,EAAA,kBAEAA,EAAA,SAASsF,CAAa,EAAID,EAEjC,MAAA,CAKF,IAAIE,EAAyB,GACzBC,EAA4B,GAG5B,GAAApC,EAAI,aAAe,MAAM,QAAQA,EAAI,WAAW,GAAKA,EAAI,YAAY,OAAS,EAAG,CAEnF,MAAMqC,EAAarC,EAAI,YAAY,KAAK,GAAG,EAErCrN,EADiB,8BACM,KAAK0P,CAAU,EAExC,GAAA1P,GAASA,EAAM,QAAU,EAC3BwP,EAAyBxP,EAAM,CAAC,EAChCyP,EAA4BzP,EAAM,CAAC,MAC9B,CAEC,MAAA2P,EAAkBtC,EAAI,YAAY,UAAU,CAACuC,EAAarL,IAC9DA,EAAI,GACJqL,GACA,CAACA,EAAI,WAAW,GAAG,IAClBA,EAAI,SAAS,GAAG,GAAKA,EAAI,MAAM,YAAY,EAC9C,EAEA,GAAID,EAAkB,EAAG,CACjB,MAAAE,EAASxC,EAAI,YAAYsC,CAAe,EAC1C,GAAAE,EAAO,SAAS,IAAI,EAAG,CACnB,MAAAC,EAAQD,EAAO,MAAM,IAAI,EAC/BL,EAAyBM,EAAM,CAAC,EAChCL,EAA4BK,EAAM,CAAC,CAAA,MAEVN,EAAAK,CAC3B,CACF,CACF,CAGF,MAAMP,EAAiB,CACrB,KAAMjC,EAAI,cAAgBA,EAAI,SAAS,MAAQA,EAAI,MAAQA,EAAI,YAAY,MAAQA,EAAI,YAAY,cAAgBmC,GAA0B,UAC7I,QAASnC,EAAI,SAAWA,EAAI,SAAS,SAAWA,EAAI,SAAS,MAAQA,EAAI,YAAY,SAAWA,EAAI,YAAY,MAAQoC,GAA6BpC,EAAI,cAAc,CAAC,GAAG,MAAM,IAAI,IAAI,CAAC,GAAK,UAC/L,QAASA,EAAI,SAAWA,EAAI,SAAS,SAAS,IAAMA,EAAI,SAAS,SAAS,MAAQ,UAClF,gBAAiBA,EAAI,WAAaA,EAAI,iBAAmBA,EAAI,MAAQA,EAAI,SAAS,iBAAmBA,EAAI,YAAY,iBAAmBA,EAAI,SAAWA,EAAI,SAAS,SAAS,iBAAmB,UAChM,aAAcA,EAAI,cAAgB,UAClC,aAAcA,EAAI,aAClB,QAAS,EACX,EAEMkC,EAAgBtF,EAAK,SAAS,UAAUlH,GAC5CA,EAAE,OAASuM,EAAe,MAC1BvM,EAAE,UAAYuM,EAAe,SAC7BvM,EAAE,UAAYuM,EAAe,OAC/B,EAEIC,IAAkB,IACftF,EAAA,SAAS,KAAKqF,CAAc,EAC5BrF,EAAA,kBAEAA,EAAA,SAASsF,CAAa,EAAID,CACjC,CACD,EAGI,KAAA,MAAM,QAAgBrF,GAAA,CACzBA,EAAK,SAAS,KAAK,CAAC3M,EAAGC,IAAM,IAAI,KAAKA,EAAE,YAAY,EAAE,UAAY,IAAI,KAAKD,EAAE,YAAY,EAAE,SAAS,CAAA,CACrG,EACH,EAEA,yBAAyByS,EAA0C,CAC7D,CAACA,GAAqB,CAAC,MAAM,QAAQA,CAAiB,IAErD,KAAA,YAAY,kBAAoBA,EAAkB,OAEvDA,EAAkB,QAAe1C,GAAA,CAC/B,MAAM5G,EAAY4G,EAAI,YAAcA,EAAI,SAAS,SAAS,MAAM,KAChE,GAAI,CAAC5G,EAAW,OAEhB,MAAMwD,EAAO,KAAK,MAAM,KAAU8C,GAAAA,EAAE,QAAUtG,CAAS,EACvD,GAAI,CAACwD,EAAM,OAGX,GAAIoD,EAAI,QAAS,CACf,MAAM2C,EAAmB,CACvB,KAAM3C,EAAI,QAAQ,MAAQ,UAC1B,QAASA,EAAI,QAAQ,SAAW,UAChC,QAASA,EAAI,QAAQ,SAAWA,EAAI,SAAS,SAAS,IAAM,UAC5D,gBAAiBA,EAAI,QAAQ,iBAAmB,UAChD,aAAcA,EAAI,cAAgBA,EAAI,QAAQ,cAAgB,UAC9D,aAAcA,EAAI,cAAgBA,EAAI,YAAc,OACtD,EAEMkC,EAAgBtF,EAAK,SAAS,UAAUlH,GAC5CA,EAAE,OAASiN,EAAiB,MAC5BjN,EAAE,UAAYiN,EAAiB,SAC/BjN,EAAE,UAAYiN,EAAiB,OACjC,EAEIT,IAAkB,IACftF,EAAA,SAAS,KAAK+F,CAAgB,EAC9B/F,EAAA,kBAEAA,EAAA,SAASsF,CAAa,EAAIS,EAEjC,MAAA,CAIF,MAAMA,EAAmB,CACvB,KAAM3C,EAAI,cAAgBA,EAAI,KAC9B,QAASA,EAAI,SAAW,UACxB,QAASA,EAAI,SAAS,SAAS,IAAMA,EAAI,SAAW,UACpD,gBAAiBA,EAAI,WAAaA,EAAI,iBAAmB,UACzD,aAAcA,EAAI,cAAgB,UAClC,aAAcA,EAAI,cAAgBA,EAAI,YAAc,OACtD,EAEMkC,EAAgBtF,EAAK,SAAS,UAAUlH,GAC5CA,EAAE,OAASiN,EAAiB,MAC5BjN,EAAE,UAAYiN,EAAiB,SAC/BjN,EAAE,UAAYiN,EAAiB,OACjC,EAEIT,IAAkB,IACftF,EAAA,SAAS,KAAK+F,CAAgB,EAC9B/F,EAAA,kBAEAA,EAAA,SAASsF,CAAa,EAAIS,CACjC,CACD,EAGI,KAAA,MAAM,QAAgB/F,GAAA,CACzBA,EAAK,SAAS,KAAK,CAAC3M,EAAGC,IAAM,IAAI,KAAKA,EAAE,YAAY,EAAE,UAAY,IAAI,KAAKD,EAAE,YAAY,EAAE,SAAS,CAAA,CACrG,EACH,EAEA,oBAAoB2M,EAAoB,CAChC,MAAAgG,EAAgBC,GAAiB,CAEjC,GAAAA,EAAK,OAAS,GAAe,CACzB,MAAAJ,EAAQI,EAAK,MAAM,GAAG,EACtBC,EAAWL,EAAM,IAAI,EACvB,OAACK,EAEE,GADeL,EAAM,KAAK,GAAG,EACZ,MAAM,EAAG,GAAgBK,EAAS,OAAS,CAAC,CAAC,OAAOA,CAAQ,GAF9DD,CAE8D,CAE/E,OAAAA,CACT,EAEME,EAAmBnE,GAEnBA,EAAQ,OAAS,GACZ,GAAGA,EAAQ,MAAM,EAAG,EAAS,CAAC,MAEhCA,EAIHoE,EAAiB,CAAC,GADPpG,EAAK,UAAY,CAAC,CACA,EAAE,KAAK,CAAC3M,EAAGC,IAAM,IAAI,KAAKA,EAAE,YAAY,EAAE,UAAY,IAAI,KAAKD,EAAE,YAAY,EAAE,SAAS,EAGvH,IAAAqQ,GAFmB1D,EAAK,gBAAkBoG,EAAiBA,EAAe,MAAM,EAAG,CAAC,GAEvD,IAAWhD,GAAA;AAAA;AAAA,iFAE+B,KAAK,WAAWA,EAAI,IAAI,CAAC;AAAA,8FACZ,KAAK,WAAWA,EAAI,OAAO,CAAC;AAAA,wFAClC,KAAK,WAAWA,EAAI,SAAW,KAAK,CAAC,KAAK,KAAK,WAAW+C,EAAgB/C,EAAI,SAAW,KAAK,CAAC,CAAC;AAAA,iFACvG,KAAK,WAAWA,EAAI,eAAe,CAAC;AAAA,2FAC1B,KAAK,WAAWA,EAAI,YAAY,CAAC,KAAK,KAAK,WAAW4C,EAAa5C,EAAI,YAAY,CAAC,CAAC;AAAA,oFAC5F,KAAK,gBAAgBA,EAAI,YAAY,CAAC;AAAA;AAAA,OAEnH,EAAE,KAAK,EAAE,EAGV,MAAMiD,EAAc,CAACrG,EAAK,iBAAmBoG,EAAe,OAAS,EAAI;AAAA;AAAA;AAAA,gDAG/BpG,EAAK,EAAE;AAAA,qBAClCoG,EAAe,OAAS,CAAC;AAAA;AAAA;AAAA;AAAA,QAIpC,GAEJ,OAAO1C,EAAc2C,CACvB,EAEA,iBAAkB,CAChB,SAAS,iBAAiB,mBAAmB,EAAE,QAAuBC,GAAA,CACpE,MAAMC,EAASD,EAAY,cACvBC,GAAUA,EAAO,aAAa,eAAe,IAC/CA,EAAO,YAAcA,EAAO,aAAa,eAAe,GAAK,GAC7DA,EAAO,gBAAgB,eAAe,EACxC,CACD,EAED,SAAS,iBAAiB,iBAAiB,EAAE,QAAe/S,GAAA,CAC1DA,EAAI,OAAO,CAAA,CACZ,EAED,SAAS,iBAAiB,IAAI,EAAE,QAAeA,GAAA,CACxCA,EAAI,UAAU,SAAS,cAAc,IACvCA,EAAoB,MAAM,QAAU,GACvC,CACD,EAED,SAAS,iBAAiB,kBAAkB,EAAE,QAAeA,GAAA,CACvDA,EAAA,UAAU,OAAO,iBAAiB,CAAA,CACvC,CACH,EAEA,gBAAiB,CAEjB,EAEA,MAAM,iBAAiBgJ,EAAmB,CACpC,GAAA,CACF,MAAMgK,EAAY,KAAK,MAAM,UAAe1D,GAAAA,EAAE,QAAUtG,CAAS,EACjE,GAAIgK,IAAc,GAAI,CACZ,QAAA,MAAM,mBAAmBhK,CAAS,YAAY,EACtD,MAAA,CAGI,MAAAwD,EAAO,KAAK,MAAMwG,CAAS,EAC3B3D,EAAS7C,EAAK,GACpBA,EAAK,kBAAoB,GAEzB,MAAMxK,EAAW,MAAM,MAAM,4BAA4B,mBAAmBgH,CAAS,CAAC,EAAE,EAEpF,GAAA,CAAChH,EAAS,GACZ,MAAM,IAAI,MAAM,uBAAuBA,EAAS,MAAM,EAAE,EAGpD,MAAAC,EAAO,MAAMD,EAAS,KAAK,EAG3BiR,EAAc,CAClB,GAAGzG,EACH,SAAUvK,EAAK,UAAY,CAAC,EAC5B,eAAgBA,EAAK,aAAe,EACpC,gBAAiBA,EAAK,aAAeA,EAAK,UAAU,QAAU,GAC9D,kBAAmB,EACrB,EAEK,KAAA,MAAM+Q,CAAS,EAAIC,EAExB,MAAMxD,EAAY,SAAS,eAAe,GAAGJ,CAAM,iBAAiB,EAChEI,IACQA,EAAA,UAAY,KAAK,oBAAoBwD,CAAW,EAEhDxD,EAAA,UAAU,IAAI,iBAAiB,EACzC,WAAW,IAAM,CACLA,EAAA,UAAU,OAAO,iBAAiB,GAC3C,GAAG,SAGD9M,EAAY,CACnB,QAAQ,MAAM,mCAAmCqG,CAAS,IAAKrG,CAAK,EAEpE,MAAMqQ,EAAY,KAAK,MAAM,UAAe1D,GAAAA,EAAE,QAAUtG,CAAS,EACjE,GAAIgK,IAAc,GAAI,OAEhB,MAAAxG,EAAO,KAAK,MAAMwG,CAAS,EAC3B3D,EAAS7C,EAAK,GAEf,KAAA,MAAMwG,CAAS,EAAI,CACtB,GAAGxG,EACH,kBAAmB,EACrB,EAEA,MAAMiD,EAAY,SAAS,eAAe,GAAGJ,CAAM,iBAAiB,EAChEI,IACFA,EAAU,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mDAOmB,KAAK,WAAW9M,EAAM,SAAW,eAAe,CAAC;AAAA;AAAA,mEAEjC0M,CAAM;AAAA;AAAA;AAAA,2CAG9BA,CAAM;AAAA,iHACiE,KAAK,WAAWrG,CAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAOpI,CAEJ,EAEA,MAAM,iBAAiBqG,EAAgB,CACrC,MAAM2D,EAAY,KAAK,MAAM,UAAe1D,GAAAA,EAAE,KAAOD,CAAM,EAC3D,GAAI2D,IAAc,GAAI,OAEhB,MAAAxG,EAAO,KAAK,MAAMwG,CAAS,EACjCxG,EAAK,gBAAkB,GAGvB,MAAMiD,EAAY,SAAS,eAAe,GAAGJ,CAAM,iBAAiB,EAChEI,IACQA,EAAA,UAAY,KAAK,oBAAoBjD,CAAI,EAEvD,EAEA,mBAAmB0G,EAAoB,CACrC,GAAIA,EAAa,GAAKA,GAAc,KAAK,QAAQ,OAAQ,OAEnD,MAAApO,EAAQ,KAAK,QAAQoO,CAAU,EAChCpO,IAED,KAAK,eAAe,IAAIoO,CAAU,GAC/B,KAAA,eAAe,OAAOA,CAAU,EACrCpO,EAAM,SAAW,KAEZ,KAAA,eAAe,IAAIoO,CAAU,EAClCpO,EAAM,SAAW,GAEbA,EAAM,aACL,CAACA,EAAM,UAAYA,EAAM,SAAS,SAAW,IAC9CA,EAAM,WAAW,MAAM,WACnBA,EAAA,SAAWA,EAAM,UAAU,KAAK,WAI1C,KAAK,UAAU,IAAM,CAEb,MAAAqO,EAAmB,SAAS,cAAc,oBAAoB,EACpE,GAAIA,EAAkB,CACdrO,MAAAA,EAAQ,IAAI,YAAY,iBAAiB,EAC/CqO,EAAiB,cAAcrO,CAAK,CAAA,CACtC,CACD,EACH,EAEA,UAAW,CAEL,KAAK,oBACP,cAAc,KAAK,kBAAkB,CAEzC,EAEA,WAAWsO,EAAwB,CACjC,OAAOA,EACJ,QAAQ,KAAM,OAAO,EACrB,QAAQ,KAAM,MAAM,EACpB,QAAQ,KAAM,MAAM,EACpB,QAAQ,KAAM,QAAQ,EACtB,QAAQ,KAAM,QAAQ,CAAA,CAE7B,CACF,CClkEA,SAAwBC,IAAoB,CACnC,MAAA,CACL,MAAO,CACL,KAAK,YAAY,EAEjB,YAAY,IAAM,KAAK,YAAY,EAAG,GAAK,EAGlC,SAAA,iBAAiB,0BAA2B,IAAM,CACzD,KAAK,YAAY,CAAA,CAClB,CACH,EAEA,MAAO,CACL,YAAa,GACb,UAAW,GACX,MAAO,KACP,iBAAkB,KAClB,YAAa,GACb,WAAY,IACd,EAEA,MAAM,aAAc,CACd,GAAA,CACE,KAAK,MAAM,aAAe,OAC5B,KAAK,MAAM,UAAY,IAEzB,KAAK,MAAM,MAAQ,KAEb,MAAArR,EAAW,MAAM,MAAM,4BAA4B,EACrD,GAAA,CAACA,EAAS,GACN,MAAA,IAAI,MAAM,iCAAiC,EAG7C,MAAAC,EAAO,MAAMD,EAAS,KAAK,EAC3Ba,EAAYZ,EAAK,aAEnB,KAAK,MAAM,aAAeY,IAC5B,KAAK,MAAM,YAAcA,EACzB,KAAK,MAAM,WAAaA,GAGrB,KAAA,MAAM,iBAAmBZ,EAAK,wBAC5BU,EAAO,CACd,KAAK,MAAM,MAAQA,aAAiB,MAAQA,EAAM,QAAU,mBAAA,QAC5D,CACA,KAAK,MAAM,UAAY,EAAA,CAE3B,EAEA,IAAI,YAAa,CACX,OAAA,KAAK,MAAM,MACN,QAEF,KAAK,MAAM,YAAc,wBAA0B,qBAC5D,EAEA,IAAI,aAAc,CACZ,OAAA,KAAK,MAAM,MACN,iBAEF,KAAK,MAAM,YAAc,iBAAmB,gBACrD,EAEA,gBAAgBwE,EAA4B,CACpC,MAAAxG,EAAO,IAAI,KAAKwG,CAAU,EAE1BmM,EAAgB,KAAK,WADX,KAAK,EACiB,UAAY3S,EAAK,QAAQ,GAAK,GAAI,EAExE,GAAI2S,EAAgB,GACX,MAAA,WAGT,MAAMC,EAAgB,KAAK,MAAMD,EAAgB,EAAE,EACnD,GAAIC,EAAgB,GAClB,MAAO,GAAGA,CAAa,UAAUA,IAAkB,EAAI,GAAK,GAAG,OAGjE,MAAMC,EAAc,KAAK,MAAMD,EAAgB,EAAE,EACjD,GAAIC,EAAc,GAChB,MAAO,GAAGA,CAAW,QAAQA,IAAgB,EAAI,GAAK,GAAG,OAG3D,MAAMhM,EAAa,KAAK,MAAMgM,EAAc,EAAE,EAC9C,GAAIhM,EAAa,GACf,MAAO,GAAGA,CAAU,OAAOA,IAAe,EAAI,GAAK,GAAG,OAGxD,MAAMiM,EAAe,KAAK,MAAMjM,EAAa,EAAE,EAC/C,GAAIiM,EAAe,GACjB,MAAO,GAAGA,CAAY,SAASA,IAAiB,EAAI,GAAK,GAAG,OAG9D,MAAMC,EAAc,KAAK,MAAMD,EAAe,EAAE,EAChD,MAAO,GAAGC,CAAW,QAAQA,IAAgB,EAAI,GAAK,GAAG,MAC3D,EAEA,IAAI,aAAc,CACZ,OAAA,KAAK,MAAM,MACN,gCAEL,KAAK,MAAM,YACT,KAAK,MAAM,iBACN,sBAAsB,KAAK,gBAAgB,KAAK,MAAM,gBAAgB,CAAC,GAEzE,uCAEF,iDACT,EAEA,aAAc,CACZ,KAAK,MAAM,YAAc,EAC3B,EAEA,aAAc,CACZ,KAAK,MAAM,YAAc,EAC3B,EAEA,aAAc,CACR,KAAK,MAAM,YACb,OAAO,SAAS,KAAO,YAEvB,OAAO,SAAS,KAAO,cACzB,CAEJ,CACF,CChIa,MAAAC,GAAepO,GAAwB,CAClDA,EAAE,eAAe,EACjBA,EAAE,gBAAgB,EAEd,aAAa,MACX,aAAa,QAAU,SAChB,SAAA,gBAAgB,UAAU,IAAI,MAAM,EAChC,aAAA,QAAQ,QAAS,MAAM,IAE3B,SAAA,gBAAgB,UAAU,OAAO,MAAM,EACnC,aAAA,QAAQ,QAAS,OAAO,IAI9B,SAAA,gBAAgB,UAAU,IAAI,MAAM,EAChC,aAAA,QAAQ,QAAS,MAAM,EAExC,EAEO,SAASqO,GAAWC,EAAyC,CAC7DA,GAGLA,EAAQ,iBAAiB,QAAU,GAAkBF,GAAY,CAAC,CAAC,CACrE,CAEO,SAASG,IAAkB,CAC5B,aAAa,QAAU,OAChB,SAAA,gBAAgB,UAAU,IAAI,MAAM,EAEpC,SAAA,gBAAgB,UAAU,OAAO,MAAM,CAEpD,CC7BO,MAAMC,UAAyBpQ,CAAW,CAM/C,YAAmBqQ,EAAuB,CAClC,MAAA,EADW,KAAA,eAAAA,EAEjB,KAAK,eAAiBA,CAAA,CAPxB,OAAS,mBACT,cAAgB,GAChB,aAAe,SACf,QAAkC,CAAC,EAOnC,UAAUC,EAA+B,CAEnC,MAAA,CAACA,GAAkBA,GAAkB,EAChC,CAAE,QAAS,GAAO,QAAS,iDAAkD,KAAM,OAAQ,EAGhG,CAAC,KAAK,eAAiB,CAAC,eAAe,KAAK,KAAK,aAAa,EACvD,CAAE,QAAS,GAAO,QAAS,4BAA6B,KAAM,OAAQ,EAG7E,KAAK,QAAQ,KAAKC,GAAUA,EAAO,gBAAkB,KAAK,aAAa,EAChE,CAAE,QAAS,GAAO,QAAS,uBAAwB,KAAM,OAAQ,GAGvE,KAAA,QAAQ,KAAK,CAAC,cAAe,KAAK,cAAe,aAAc,KAAK,aAAqB,EAC9F,KAAK,cAAgB,GACrB,KAAK,aAAe,SAEb,CAAE,QAAS,EAAK,EAAA,CAIzB,MAAM,mBAAkC,CACtC,MAAMlS,EAAW,MAAM,MAAM,KAAK,OAAS,uCAAyC,KAAK,cAAc,EAChG,OAAAA,EAAS,SAAW,IAAM,MAAMA,EAAS,KAAK,EAAE,KAAKC,GAAQA,CAAI,EAAE,CAAC,CAAA,CAG7E,MAAM,cAAca,EAAiC,CAe7C,MAAAqR,EAAe,MAZJ,MAAM,MACrB,KAAK,OAAS,gBAHC,eAG8B,cAAgB,KAAK,eAClE,CACE,OAAQ,OACR,KAAM,KAAK,UAAU,KAAK,OAAO,EACjC,QAAS,CACP,cAAerR,EACf,eAAgB,kBAAA,CAClB,CAEJ,GAEoC,KAAK,EAEnCsR,EAAoBD,EAAa,oBAAsB,CAAC,EACxDE,EAAgBF,EAAa,gBAAkB,CAAC,EAGjD,YAAA,QAAU,KAAK,QAAQ,OAC1BD,GAAA,CAACE,EAAkB,SAASF,EAAO,aAAa,CAClD,EAGK,KAAA,QAAU,KAAK,QAAQ,OAAOA,GACjCG,EAAc,KAAMC,GAA4CA,EAAK,QAAUJ,EAAO,aAAa,CACrG,EAEOC,CAAA,CAKT,MAAM,aAAaI,EAAkBzR,EAAiC,CAGpE,OAAO,MAAM,MACT,KAAK,OAASyR,EAAW,wBAHZ,eAGwD,cAAgB,KAAK,eAC1F,CACI,OAAQ,MACR,QAAS,CACP,cAAezR,EACf,eAAgB,kBAAA,CAClB,CAER,CAAA,CAIF,MAAM,aAAayR,EAAkBzR,EAAiC,CAGpE,OAAO,MAAM,MACT,KAAK,OAASyR,EAAW,wBAHZ,eAGwD,cAAgB,KAAK,eAC1F,CACI,OAAQ,MACR,QAAS,CACP,cAAezR,EACf,eAAgB,kBAAA,CAClB,CAER,CAAA,CAEJ,CACO,MAAM0R,WAAuB7Q,CAAW,CAC7C,OAAS,mBAET,MAAM,kBAAkBqQ,EAAwBS,EAA0B,GAAoB,CAC5F,MAAMzS,EAAW,MAAM,MAAM,KAAK,OAAS,uCAAyCgS,CAAc,EAClG,IAAIvH,EAAQzK,EAAS,SAAW,IAAM,MAAMA,EAAS,KAAK,EAAE,KAAKC,GAAQA,CAAI,EAAE,CAAC,EAEhF,GAAIwS,EAAgB,CAGlB,MAAMC,GAFU,MAAM,IAAIX,EAAiBC,CAAc,EAAE,kBAAkB,GAErC,IAAKE,IAAiB,CAC5D,GAAI,UAAYA,EAAO,GACvB,KAAMA,EAAO,cACb,QAAS,yBACT,MAAOA,EAAO,cACd,KAAM,eAAeA,EAAO,eAAiB,QAAU,IAAM,EAAE,IAAIA,EAAO,aAAa,OAAO,CAAC,EAAE,YAAY,EAAIA,EAAO,aAAa,MAAM,CAAC,CAAC,GAC7I,aAAc,GACd,UAAW,GACX,eAAgB,GAChB,OAAQ,CACN,cAAkBA,EAAO,WAAW,SAAS,KAAK,EAAI,UAAaA,EAAO,QAAU,UACpF,WAAcA,EAAO,UAAA,CACvB,EACE,EACJzH,EAAQ,CAAC,GAAGA,EAAO,GAAGiI,CAAuB,CAAA,CAGxC,OAAAjI,CAAA,CAGT,MAAM,eAAekI,EAAoBC,EAAkBC,EAAkB/R,EAAiC,CAC5G,OAAO,MAAM,MACX,KAAK,OAAS+R,EAAW,0BAAiCF,EAAa,cAAgBC,EACvF,CACI,OAAQ,MACR,KAAM,KAAK,UAAU,CAAC,OAAQC,EAAS,EACvC,QAAS,CACP,cAAe/R,EACf,eAAgB,kBAAA,CAClB,CAER,CAAA,CAGA,MAAM,aAAac,EAAiC,CAClD,MAAM5B,EAAW,MAAM,MAAM,KAAK,OAAS,kCAAoC4B,CAAS,EACjF,OAAA5B,EAAS,SAAW,IAAM,MAAMA,EAAS,KAAK,EAAE,KAAKC,GAAQA,CAAI,EAAE,CAAC,CAAA,CAG7E,MAAM,UAAU0S,EAAoBC,EAAkBvF,EAAgBvM,EAAiC,CACrG,OAAO,MAAM,MACT,KAAK,OAAS,gBAAkB6R,EAAa,cAAgBC,EAC7D,CACI,OAAQ,OACR,KAAM,KAAK,UAAU,CAAC,YAAavF,EAAO,EAC1C,QAAS,CACP,cAAevM,EACf,eAAgB,kBAAA,CAClB,CAER,CAAA,CAGF,MAAM,aAAa6R,EAAoBC,EAAkBC,EAAkB/R,EAAiC,CAC1G,OAAO,MAAM,MACT,KAAK,OAAS+R,EAAW,gBAAkBF,EAAa,cAAgBC,EACxE,CACI,OAAQ,SACR,QAAS,CACP,cAAe9R,EACf,eAAgB,kBAAA,CAClB,CAER,CAAA,CAGF,MAAM,WAAW6R,EAAoBC,EAAkBC,EAAkB/R,EAAmBgS,EAA4B,CACtH,OAAO,MAAM,MACT,KAAK,OAASD,EAAW,6BAAoCF,EAAa,cAAgBC,EAC1F,CACI,OAAQ,MACR,KAAM,KAAK,UAAU,CAAC,KAAAE,EAAW,EACjC,QAAS,CACP,cAAehS,EACf,eAAgB,kBAAA,CAClB,CAER,CAAA,CAEJ,CClMO,MAAMiS,WAAiCpR,CAAW,CACvD,OAAS,6BAET,MAAM,YAAYqR,EAAkBlS,EAAiC,CACnE,OAAO,MAAM,MACX,KAAK,OACL,CACE,OAAQ,OACR,KAAM,KAAK,UAAUkS,CAAQ,EAC7B,QAAS,CACP,cAAelS,EACf,eAAgB,kBAAA,CAClB,CAEJ,CAAA,CAGF,MAAM,YAAY2F,EAAYwM,EAAoBnS,EAAiC,CACjF,OAAO,MAAM,MACX,KAAK,OAAS2F,EAAK,IACnB,CACE,OAAQ,QACR,KAAM,KAAK,UAAU,CAAC,MAAOwM,EAAW,EACxC,QAAS,CACP,cAAenS,EACf,eAAgB,kBAAA,CAClB,CAEJ,CAAA,CAEJ,CAEO,MAAMoS,WAAsCvR,CAAW,CAC5D,OAAS,mCAET,MAAM,UAAUwL,EAA4B,CAC1C,MAAMnN,EAAW,MAAM,MAAM,KAAK,OAAS,SAAWmN,CAAI,EACnD,OAAAnN,EAAS,SAAW,IAAM,MAAMA,EAAS,KAAK,EAAE,KAAKC,GAAQA,CAAI,EAAE,CAAC,CAAA,CAE/E,CC0BIkT,GAAY,CACV,IAAK,wFACL,aAAc,CACZC,GAAiC,CACnC,EACA,iBAAkB,EAClB,yBAA0B,CAAA,CAC3B,EAGM,OAAA,iBAAiB,QAAUtQ,GAAU,CACnC4F,EAAiB5F,EAAM,KAAK,CAAA,CACpC,EAEM,OAAA,iBAAiB,qBAAuBA,GAAU,CAChD4F,EAAiB5F,EAAM,MAAM,CAAA,CACrC,EAKL,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CASX,EAEDuQ,EAAO,OAAOC,EAAK,EACnBD,EAAO,OAAOE,EAAE,EAGhB,OAAO,OAASF,EAEhBA,EAAO,MAAM,QAAS,CACpB,SAAU,aAAa,QAAQ,OAAO,IAAM,OAC5C,QAAS,CACF,KAAA,SAAW,CAAC,KAAK,QAAA,CAE1B,CAAQ,EAERA,EAAO,MAAM,kBAAmB,CAC9B,MAAO,CAEL,CAAE,MAAO,WAAY,IAAK,SAAU,CAAA,CAExC,CAAC,EAEDA,EAAO,MAAM,wBAAyB,CACpC,MAAO,CACH,CAAE,MAAO,OAAO,gBAAkB,WAAa,YAAa,IAAK,GAAI,EACrE,CACE,MAAO,WACP,IAAK,YACL,OAAQ,IAAM,OAAO,cAAc,gBACrC,EACA,CAAE,MAAO,eAAgB,IAAK,eAAgB,CAAA,CAEpD,CAAC,EAEDA,EAAO,MAAM,0BAA2B,CACtC,MAAO,CACL,CAAE,MAAO,OAAQ,IAAK,oBAAqB,EAC3C,CAAE,MAAO,WAAY,IAAK,yBAA0B,oBAAqB,EAAK,EAC9E,CAAE,MAAO,WAAY,IAAK,uBAAwB,EAClD,CAAE,MAAO,WAAY,IAAK,wBAAyB,EACnD,CAAE,MAAO,UAAW,IAAK,oBAAqB,EAC9C,CAAE,MAAO,QAAS,IAAK,qBAAsB,CAAA,CAEjD,CAAC,EAEDA,EAAO,MAAM,kBAAmB,CAC9B,MAAO,CACL,CACE,KAAM,cAAe,MAAO,cAAe,WAAY,MAAO,IAAK,iCACnE,YAAa,mPACf,EACA,CACE,KAAM,OAAQ,MAAO,QAAS,WAAY,QAAS,IAAK,2BACxD,YAAa,gGACf,EACA,CACE,KAAM,aAAc,MAAO,aAAc,WAAY,OAAQ,IAAK,gCAClE,YAAa,wTAAA,CACf,CAEJ,CAAC,EAEDA,EAAO,MAAM,uBAAwB/V,EAAgB,oBAAoB,EACzE+V,EAAO,MAAM,8BAA+B/V,EAAgB,2BAA2B,EACvF+V,EAAO,MAAM,oBAAqB/V,EAAgB,iBAAiB,EACnE+V,EAAO,MAAM,uBAAwB/V,EAAgB,oBAAoB,EACzE+V,EAAO,MAAM,2BAA4B/V,EAAgB,wBAAwB,EAGjF,SAAS,iBAAiB,cAAe,IAAM,CACtC+V,EAAA,KAAK,oBAAqB,IAAIG,IAAsB,CACnD,MAAAC,EAAS,IAAI/R,GACZ,MAAA,CACL,GAAG+R,EACH,OAAQA,EAAO,OACf,SAAUA,EAAO,SACjB,YAAaA,EAAO,YACpB,OAAQA,EAAO,OACf,MAAOA,EAAO,KAChB,CAAA,CACD,EACMJ,EAAA,KAAK,eAAgB,IAAIK,IAAqB,CAC7C,MAAAzT,EAAOyT,EAAiB,CAAC,EACzBD,EAAS,IAAIE,GAAa1T,CAAI,EAC7B,MAAA,CACL,GAAGwT,EACH,KAAMA,EAAO,KACb,SAAUA,EAAO,SACjB,aAAcA,EAAO,aACrB,eAAgBA,EAAO,eACvB,iBAAkBA,EAAO,iBACzB,oBAAqBA,EAAO,oBAC5B,SAAUA,EAAO,QACnB,CAAA,CACD,EACMJ,EAAA,KAAK,oBAAqB,IAAIG,IAAsB,CACnD,MAAAC,EAAS,IAAIvT,GACZ,MAAA,CACL,GAAGuT,EACH,OAAQA,EAAO,OACf,aAAcA,EAAO,aACrB,UAAWA,EAAO,UAClB,YAAaA,EAAO,YACpB,aAAcA,EAAO,aACrB,OAAQA,EAAO,OACf,eAAgBA,EAAO,eAAe,KAAKA,CAAM,CACnD,CAAA,CACD,EACMJ,EAAA,KAAK,eAAgB,IAAIK,IAAqB,CAC7C,MAAAzT,EAAOyT,EAAiB,CAAC,EACzBD,EAAS,IAAIG,GAAa3T,CAAI,EAC7B,MAAA,CACL,GAAGwT,EACH,KAAMA,EAAO,KACb,YAAaA,EAAO,YACpB,SAAUA,EAAO,SACjB,aAAcA,EAAO,aACrB,eAAgBA,EAAO,eACvB,aAAcA,EAAO,aACrB,SAAUA,EAAO,SACjB,cAAeA,EAAO,aACxB,CAAA,CACD,EACMJ,EAAA,KAAK,iBAAkB,IAAIG,IAAsB,CAChD,MAAAC,EAAS,IAAI3T,GACZ,MAAA,CACL,GAAG2T,EACH,OAAQA,EAAO,OACf,aAAcA,EAAO,aACrB,aAAcA,EAAO,YACvB,CAAA,CACD,EACMJ,EAAA,KAAK,YAAa,IAAIK,IAAqB,CAC1C,MAAAzT,EAAOyT,EAAiB,CAAC,EACzBD,EAAS,IAAII,GAAU5T,CAAI,EAC1B,MAAA,CACL,GAAGwT,EACH,KAAMA,EAAO,KACb,SAAUA,EAAO,SACjB,aAAcA,EAAO,aACrB,UAAWA,EAAO,UAClB,eAAgBA,EAAO,eACvB,eAAgBA,EAAO,eACvB,YAAaA,EAAO,YACpB,sBAAuBA,EAAO,sBAC9B,SAAUA,EAAO,SACjB,eAAgBA,EAAO,eACvB,cAAeA,EAAO,cACtB,eAAgBA,EAAO,eACvB,aAAcA,EAAO,YACvB,CAAA,CACD,EACMJ,EAAA,KAAK,oBAAqB,IAAIG,IAAsB,CACnD,MAAAC,EAAS,IAAI7T,GACZ,MAAA,CACL,GAAG6T,EACH,aAAcA,EAAO,YACvB,CAAA,CACD,EACMJ,EAAA,KAAK,eAAgB,IAAIK,IAAqB,CAC7C,MAAAzT,EAAOyT,EAAiB,CAAC,EACzBD,EAAS,IAAIK,GAAa7T,CAAI,EAC7B,MAAA,CACL,GAAGwT,EACH,KAAMA,EAAO,KACb,YAAaA,EAAO,YACpB,SAAUA,EAAO,SACjB,aAAcA,EAAO,aACrB,eAAgBA,EAAO,eACvB,YAAaA,EAAO,YACpB,SAAUA,EAAO,SACjB,UAAWA,EAAO,UAClB,cAAeA,EAAO,cACtB,mBAAoBA,EAAO,mBAC3B,oBAAqBA,EAAO,oBAC5B,gBAAiBA,EAAO,eAC1B,CAAA,CACD,EACMJ,EAAA,KAAK,iBAAkB,IAAIG,IAAsB,CAChD,MAAAC,EAAS,IAAIjB,GACZ,MAAA,CACL,GAAGiB,EACH,aAAcA,EAAO,aACrB,kBAAmBA,EAAO,kBAC1B,UAAWA,EAAO,UAClB,eAAgBA,EAAO,eACvB,aAAcA,EAAO,aACrB,WAAYA,EAAO,UACrB,CAAA,CACD,EACMJ,EAAA,KAAK,mBAAoB,IAAIK,IAAqB,CACjD,MAAAK,EAAkBL,EAAiB,CAAC,EACpCD,EAAS,IAAI1B,EAAiBgC,CAAe,EAC5C,MAAA,CACL,GAAGN,EACH,kBAAmBA,EAAO,kBAC1B,cAAeA,EAAO,cACtB,aAAcA,EAAO,aACrB,UAAWA,EAAO,UAClB,aAAcA,EAAO,YACvB,CAAA,CACD,EACMJ,EAAA,KAAK,YAAa,IAAIK,IAAqB,CAC1C,MAAAzT,EAAOyT,EAAiB,CAAC,EACzBD,EAAS,IAAIO,GAAU/T,CAAI,EAC1B,MAAA,CACL,GAAGwT,EACH,SAAUA,EAAO,SACjB,aAAcA,EAAO,aACrB,eAAgBA,EAAO,eACvB,YAAaA,EAAO,YACpB,SAAUA,EAAO,QACnB,CAAA,CACD,EACMJ,EAAA,KAAK,oBAAqB,IAAIK,IAAqB,CACpD,IAAAzT,EAAOyT,EAAiB,CAAC,EACzBD,EAAS,IAAIQ,EAAkBhU,CAAI,EAEvCoT,OAAAA,EAAO,OAAO,IAAM,CAClBpT,EAAOyT,EAAiB,CAAC,EAChBD,EAAA,IAAIQ,EAAkBhU,CAAI,CAAA,CACpC,EAEM,CACL,GAAGwT,EACH,SAAUA,EAAO,SACjB,aAAcA,EAAO,aACrB,eAAgBA,EAAO,cACzB,CAAA,CACD,EACMJ,EAAA,KAAK,2BAA4B,IAAIG,IAAsB,CAC1D,MAAAC,EAAS,IAAIV,GACZ,MAAA,CACL,GAAGU,EACH,aAAcA,EAAO,aACrB,YAAaA,EAAO,YACpB,YAAaA,EAAO,WACtB,CAAA,CACD,EACMJ,EAAA,KAAK,gCAAiC,IAAIG,IAAsB,CAC/D,MAAAC,EAAS,IAAIP,GACZ,MAAA,CACL,GAAGO,EACH,UAAWA,EAAO,SACpB,CAAA,CACD,EACMJ,EAAA,KAAK,cAAe,IAAIK,IAAqB,CAC5C,MAAAQ,EAAaR,EAAiB,CAAC,EAC/BD,EAAS,IAAIlW,GAAY2W,CAAU,EAClC,MAAA,CACL,GAAGT,EACH,cAAeA,EAAO,cACtB,oBAAqBA,EAAO,oBAC5B,aAAcA,EAAO,YACvB,CAAA,CACD,EACMJ,EAAA,KAAK,mBAAoB,IAAIG,IAAsB,CAClD,MAAAC,EAAS,IAAInV,GACZ,MAAA,CACL,GAAGmV,EACH,OAAQA,EAAO,OACf,MAAOA,EAAO,MACd,gBAAiBA,EAAO,gBACxB,YAAaA,EAAO,WACtB,CAAA,CACD,EAEMJ,EAAA,KAAK,mBAAoB,IAAIK,IAAgC,CAC5D,MAAAzU,EAAuByU,EAAiB,CAAC,EACzCxU,EAA0BwU,EAAiB,CAAC,EAE5CD,EAAS,IAAIzU,GAAiBC,EAAaC,CAAe,EACzD,MAAA,CACL,GAAGuU,EACH,OAAQA,EAAO,OACf,MAAOA,EAAO,MACd,eAAgBA,EAAO,cACzB,CAAA,CACD,EAEMJ,EAAA,KAAK,aAAc,IAAIG,IAAsB,CAC5C,MAAAC,EAAS,IAAI/T,GACZ,MAAA,CACL,GAAG+T,EACH,cAAeA,EAAO,aACxB,CAAA,CACD,EAEMJ,EAAA,KAAK,gBAAiB,IAAIG,IAAsB,CAC/C,MAAAC,EAAS,IAAI7O,GAEZ,MAAA,CACL,GAAG6O,EACH,IAAKA,EAAO,IACZ,OAAQA,EAAO,MACjB,CAAA,CACD,EAEMJ,EAAA,KAAK,SAAU,IAAIG,IAAsB,CACxC,MAAAC,EAAS,IAAI1O,GAEZ,MAAA,CACL,GAAG0O,EACH,UAAWA,EAAO,UAClB,WAAYA,EAAO,UACrB,CAAA,CACD,EAGMJ,EAAA,KAAK,yBAA0B,IAAIK,IAAqB,CAQ7D,GAAI,CAAE,kBAAAS,EAAmB,UAAAnN,EAAW,UAAAlG,EAAW,wBAAAsT,CAAwB,EAAIV,EAAiB,CAAC,EAEzFW,EAAS,CAAC,EAEV,GAAA,CAACF,GAAqB,CAACC,EAAyB,CAClD,MAAME,EAAsB;AAAA,gCACFtN,CAAS,6BAEnCqN,EAAO,KAAK,CACV,KAAM,UACN,QAASC,EACT,WAAY,MAAA,CACb,CAAA,CAgCI,MAAA,CACL,OAAAD,EACA,eA/BsBE,GAOfA,EAAM,WAAW,SAAS,MAAM,EACnCA,EAAM,SACL,IAAM,CACL,MAAMC,EAAO,SAAS,eAAeD,EAAM,OAAO,EAC5CE,EAAM,SAAS,cAAc,KAAK,EACxC,OAAAA,EAAI,YAAYD,CAAI,EACbC,EAAI,SAAA,GACV,EAkBP,sBAf4B,SAA2B,CACvD,MAAM,MAAM,qCAAsC,CAChD,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,cAAe3T,CACjB,EACA,KAAM,KAAK,UAAU,CAAE,CAAA,CAAA,CACxB,EACD,OAAO,SAAS,OAAO,CACzB,CAMA,CAAA,CACD,EAGMuS,EAAA,KAAK,aAAc,IAAIK,IAAqB,CAC3C,MAAAgB,EAAQhB,EAAiB,CAAC,EAChC,OAAOiB,GAAWD,CAAK,CAAA,CACxB,EAGMrB,EAAA,KAAK,gBAAiB,IAAIK,IAAqB,CAC9C,MAAAgB,EAAQhB,EAAiB,CAAC,EAChC,OAAOkB,GAAcF,CAAK,CAAA,CAC3B,EAGMrB,EAAA,KAAK,gBAAiB,IAAIK,IAAqB,CAC9C,MAAAmB,EAASnB,EAAiB,CAAC,EACjC,OAAOoB,GAAcD,CAAM,CAAA,CAC5B,EAGMxB,EAAA,KAAK,gBAAiB,IAAIK,IAAqB,CAC9C,MAAAmB,EAASnB,EAAiB,CAAC,EACjC,OAAOqB,GAAcF,CAAM,CAAA,CAC5B,EAGMxB,EAAA,KAAK,WAAY,IAAIK,IAAqB,CACzC,MAAAsB,EAAQtB,EAAiB,CAAC,EAChC,OAAOuB,GAASD,CAAK,CAAA,CACtB,EAGM3B,EAAA,KAAK,cAAe,IAAIK,IAAqB,CAC5C,MAAA/U,EAAO+U,EAAiB,CAAC,EAC/B,OAAOwB,GAAYvW,CAAI,CAAA,CACxB,EAGM0U,EAAA,KAAK,aAAc,IAAIK,IAAqB,CAC3C,MAAAyB,EAAUzB,EAAiB,CAAC,EAClC,OAAO0B,GAAWD,CAAO,CAAA,CAC1B,EAEM9B,EAAA,KAAK,cAAevR,EAAW,EAC/BuR,EAAA,KAAK,0BAA2B3P,EAAuB,EACvD2P,EAAA,KAAK,uCAAwCrP,EAAoC,EACjFqP,EAAA,KAAK,aAAc,IAAIK,IAAqB,CAC3C,MAAAzR,EAAcyR,EAAiB,CAAC,EACtC,OAAO1R,GAAaC,CAAW,CAAA,CAChC,EACMoR,EAAA,KAAK,yBAA0B,IAAIK,IAAqB,CACvD,MAAAxQ,EAAyBwQ,EAAiB,CAAC,EAC3CvQ,EAAkB,OAAOuQ,EAAiB,CAAC,GAAM,SAAWA,EAAiB,CAAC,EAAI,EACjF,OAAAzQ,GAAuBC,EAAwBC,CAAe,CAAA,CACtE,EAEMkQ,EAAA,KAAK,sBAAuBgC,EAAmB,EAE/ChC,EAAA,KAAK,UAAW,IAAIG,KAClB,CACL,MAAO,CACL,KAAK,kBAAkB,KAAK,IAAK,KAAK,IAAI,QAAQ,SAAW,GAAI,CAC/D,MAAO,KAAK,IAAI,QAAQ,cAAgB,QACxC,UAAW,KAAK,IAAI,QAAQ,kBAAoB,KAAA,CACjD,CACH,EACA,kBAAkBlP,EAAiB8J,EAAiBkH,EAAc,CAC3DlH,IAGF9J,EAAA,aAAa,QAAS8J,CAAO,EAG7B9J,EAAA,UAAU,IAAI,gBAAgB,EAC7BgR,EAAQ,OACVhR,EAAG,UAAU,IAAI,iBAAiBgR,EAAQ,KAAK,EAAE,EAE/CA,EAAQ,WACVhR,EAAG,UAAU,IAAI,qBAAqBgR,EAAQ,SAAS,EAAE,EAC3D,CAEJ,EACD,EACMjC,EAAA,KAAK,WAAY,IAAIK,KACnB,CAAE,SAAU,IAAI6B,GAAS,GAAI7B,CAA4E,CAAC,EAClH,EACML,EAAA,KAAK,kBAAmB,IAAIG,KAC1B,CACL,QAAS,GACT,UAAW,CAEH,MAAAgC,GADc,SAAS,OAAS,SAAS,OAAO,MAAM,IAAI,EAAI,CAAC,GAC3C,KAAYxX,GAAA,OAAOA,GAAQ,UAAYA,EAAI,WAAW,kBAAkB,CAAC,EACnG,KAAK,QAAU,CAACwX,CAClB,EACA,SAAU,CACN,SAAS,OAAS,yCAA4C,GAAK,GAAK,GAAK,GAC7E,KAAK,QAAU,EAAA,CAEvB,EACC,EAEMnC,EAAA,KAAK,gBAAiB,KAAO,CAClC,WAAY,GACZ,WAAY,CACV,GAAI,KAAK,WAAY,OACrB,KAAK,WAAa,GAClB,MAAMoC,EAAM,SAAS,eAAe,eAAe,GAAG,aAAa,iBAAiB,GAAK,GACzF,MAAMA,EAAK,CACT,OAAQ,OACR,QAAS,CACP,cAAgB,SAAS,cAAc,4BAA4B,EAAuB,MAC1F,eAAgB,kBAAA,CAClB,CACD,EACE,KAAKzV,GAAYA,EAAS,MAAM,EAChC,KAAaC,GAAA,CACRA,EAAK,SAAW,WAClB,KAAK,UAAU,SAAU,CACvB,QAASA,EAAK,QACd,KAAM,UACN,gBAAiB,GAAA,CAClB,EACD,WAAW,IAAM,CACf,OAAO,SAAS,OAAO,GACtB,GAAI,GAEP,KAAK,UAAU,SAAU,CACvB,QAASA,EAAK,QACd,KAAM,QACN,gBAAiB,GAAA,CAClB,CACH,CACD,EACA,MAAamG,GAAA,CACZ,QAAQ,MAAMA,CAAG,EACjB,MAAM,yBAAyB,CAAA,CAChC,EACA,QAAQ,IAAM,CACb,KAAK,WAAa,EAAA,CACnB,CAAA,CACL,EACA,EAGKiN,EAAA,KAAK,kBAAmB,IAAIK,KAE1B,CACL,IAFkBA,EAAiB,CAAC,GAAgB,GAGpD,OAAQ,GACR,SAAU,GACV,SAAU,CACJ,KAAK,UAEP,KAAK,OAAS,GACJ,UAAA,UAAU,UAAU,KAAK,GAAG,EACtC,WAAW,IAAM,CAAE,KAAK,OAAS,IAAU,GAAI,GAG/C,KAAK,SAAW,EAClB,CAEJ,EACD,EAGML,EAAA,KAAK,WAAYxK,EAAiB,EAElCwK,EAAA,KAAK,aAAcpO,EAAU,EAG7BoO,EAAA,KAAK,oBAAqBhC,EAAiB,CACpD,CAAC,EAEDgC,EAAO,MAAM,EASb,OAAO,iBAAiB,mBAAoB,IAAM,CACtCvB,GAAA,EACO7J,EAAA,CACnB,CAAC,EACD2J,GAAW,SAAS,cAAiC,eAAe,CAAE,EAGtE,OAAO,OAASyB"}