dns-worker 1.0.2-3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +662 -0
  2. package/README.md +294 -0
  3. package/dist/serverfull.mjs +11777 -0
  4. package/migrations/0000_init.sql +80 -0
  5. package/migrations/0001_move_lists_to_d1.sql +12 -0
  6. package/migrations/0002_activity_tracking.sql +7 -0
  7. package/migrations/0003_fix_profiles_cascade.sql +21 -0
  8. package/migrations/0004_system_settings.sql +12 -0
  9. package/migrations/0005_add_bloom_storage.sql +3 -0
  10. package/migrations/0006_cleanup_profiles_table.sql +18 -0
  11. package/migrations/0007_user_activity_and_totp.sql +37 -0
  12. package/migrations/0008_add_profile_key.sql +8 -0
  13. package/migrations/0009_add_profile_blooms.sql +5 -0
  14. package/migrations/0010_session_device_info.sql +3 -0
  15. package/migrations/0011_session_created_at.sql +2 -0
  16. package/migrations/0012_profile_bloom_chunks.sql +9 -0
  17. package/migrations/0013_add_session_revoked_to_activity_log.sql +29 -0
  18. package/migrations/0014_add_session_geo.sql +3 -0
  19. package/migrations/0015_add_signup_to_activity_log.sql +30 -0
  20. package/migrations/0016_add_session_rotation_counter.sql +2 -0
  21. package/migrations/0017_add_access_points.sql +31 -0
  22. package/migrations/0018_add_list_updated_at.sql +2 -0
  23. package/migrations/0019_add_list_sync_error.sql +2 -0
  24. package/migrations/0020_add_session_last_active.sql +5 -0
  25. package/migrations/0021_add_user_timezone.sql +2 -0
  26. package/migrations/0022_add_user_locale.sql +2 -0
  27. package/migrations/0023_add_user_password_version.sql +2 -0
  28. package/migrations/0024_session_pin_and_pause.sql +37 -0
  29. package/migrations/0025_add_secret_table.sql +10 -0
  30. package/migrations/0026_session_lock_config.sql +2 -0
  31. package/migrations/0027_add_session_id_to_activity_log.sql +2 -0
  32. package/migrations/0028_rename_session_id_to_session_id_hash.sql +2 -0
  33. package/migrations/0029_profile_blooms_staging.sql +12 -0
  34. package/migrations/0030_add_list_blooms.sql +7 -0
  35. package/migrations/0031_list_blooms_chunks.sql +13 -0
  36. package/migrations/0032_profile_blooms_cascade.sql +40 -0
  37. package/migrations/0033_remove_system_secrets.sql +2 -0
  38. package/migrations/0034_remove_list_entries.sql +2 -0
  39. package/migrations/0035_add_envelope_encryption_columns.sql +5 -0
  40. package/migrations/0036_add_cf_proxy_cidrs_setting.sql +7 -0
  41. package/migrations/0037_optimize_logs_composite_indexes.sql +25 -0
  42. package/migrations/0038_optimize_logs_table_and_indexes.sql +49 -0
  43. package/migrations/0039_add_lists_profile_id_index.sql +5 -0
  44. package/migrations/0040_reduce_logs_indexes_write_cost.sql +9 -0
  45. package/migrations/0041_create_log_hourly_rollups.sql +21 -0
  46. package/migrations/0042_add_rule_created_at.sql +3 -0
  47. package/migrations/0043_create_client_hourly_rollups.sql +26 -0
  48. package/migrations/0044_create_destination_hourly_rollups.sql +29 -0
  49. package/migrations/0045_transform_logs_without_rowid.sql +38 -0
  50. package/migrations/0046_add_passkeys.sql +19 -0
  51. package/migrations/0047_add_passkey_actions_to_activity_log.sql +35 -0
  52. package/migrations/0048_add_recovery_key_rotated_to_activity_log.sql +35 -0
  53. package/migrations/0049_optimize_rollups_and_add_domain_rollups.sql +26 -0
  54. package/migrations/0050_add_dest_columns_to_logs.sql +6 -0
  55. package/migrations/0051_add_registration_enabled_setting.sql +2 -0
  56. package/package.json +71 -0
  57. package/static/assets/AccountView-BvRvODjN.js +4 -0
  58. package/static/assets/AnalyticsView-DQ7hDChh.js +2 -0
  59. package/static/assets/AuthView-Bwv6hbdi.js +2 -0
  60. package/static/assets/DestinationMap-BEQNbcb-.js +1 -0
  61. package/static/assets/FilteringView-BWD3e-DS.js +1 -0
  62. package/static/assets/LogsView-kQy7qTGd.js +5 -0
  63. package/static/assets/QRCodeCanvas-X07w5x_G.js +2 -0
  64. package/static/assets/RulesView-3d5hga0L.js +1 -0
  65. package/static/assets/SettingsView-B9D0kPUF.js +1 -0
  66. package/static/assets/SetupView-D7d-Gsdr.js +1 -0
  67. package/static/assets/SwipeableDrawer-B-MfxTWM.js +1 -0
  68. package/static/assets/TrendChart-B20w7SzD.js +53 -0
  69. package/static/assets/allPaths-BEI3QvIM.js +1 -0
  70. package/static/assets/allPathsLoader-DM2JAMeC.js +1 -0
  71. package/static/assets/browser-icErLjuM.js +1 -0
  72. package/static/assets/date-C4b8kvr-.js +1 -0
  73. package/static/assets/de-DE-CXKS_pep.js +10 -0
  74. package/static/assets/es-ES-B2e3ea35.js +10 -0
  75. package/static/assets/formatCountryName-CSBD8pP8.js +1 -0
  76. package/static/assets/fr-FR-1qQHEpoW.js +10 -0
  77. package/static/assets/getFlagEmoji-_Wxhq0lT.js +1 -0
  78. package/static/assets/index-7FKlsF79.js +16 -0
  79. package/static/assets/index-DdQuGqR5.css +2 -0
  80. package/static/assets/ja-JP-CCVeJXwX.js +10 -0
  81. package/static/assets/ko-KR-bQ1okpC2.js +10 -0
  82. package/static/assets/obex_cat_eye_logo-256-CgYNvUIC.webp +0 -0
  83. package/static/assets/paths-CfqdBnl8.js +1 -0
  84. package/static/assets/paths-cc-gUzxh.js +1 -0
  85. package/static/assets/rolldown-runtime-C4Xdq4VV.js +1 -0
  86. package/static/assets/ru-RU-DeRsms_o.js +10 -0
  87. package/static/assets/services-fIMx5oSx.js +1 -0
  88. package/static/assets/splitPathsBySizeLoader-BgBwSA38.js +1 -0
  89. package/static/assets/vendor-i18next-cO7FDf_e.js +1 -0
  90. package/static/assets/vendor-icons-16-BgwRBCeU.js +1 -0
  91. package/static/assets/vendor-icons-20-X5NPN60g.js +1 -0
  92. package/static/assets/vendor-icons-other-Bme3ywH9.js +2 -0
  93. package/static/assets/vendor-react-Kt98jRfM.js +11 -0
  94. package/static/assets/vendor-ui-core-BpucEp_q.js +1 -0
  95. package/static/assets/vendor-utils-CfYGGC23.js +9 -0
  96. package/static/assets/vi-VN-BcXfqmzH.js +10 -0
  97. package/static/assets/zh-CN-D8YK7j27.js +12 -0
  98. package/static/assets/zh-TW-C2_-uaZk.js +12 -0
  99. package/static/favicon.webp +0 -0
  100. package/static/index.html +27 -0
  101. package/static/manifest.webmanifest +1 -0
  102. package/static/registerSW.js +1 -0
  103. package/static/sw.js +1 -0
@@ -0,0 +1,16 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/SetupView-D7d-Gsdr.js","assets/vendor-icons-other-Bme3ywH9.js","assets/vendor-icons-16-BgwRBCeU.js","assets/rolldown-runtime-C4Xdq4VV.js","assets/vendor-icons-20-X5NPN60g.js","assets/vendor-react-Kt98jRfM.js","assets/vendor-ui-core-BpucEp_q.js","assets/vendor-utils-CfYGGC23.js","assets/SwipeableDrawer-B-MfxTWM.js","assets/FilteringView-BWD3e-DS.js","assets/RulesView-3d5hga0L.js","assets/SettingsView-B9D0kPUF.js","assets/AnalyticsView-DQ7hDChh.js","assets/getFlagEmoji-_Wxhq0lT.js","assets/LogsView-kQy7qTGd.js","assets/formatCountryName-CSBD8pP8.js","assets/AuthView-Bwv6hbdi.js","assets/vendor-i18next-cO7FDf_e.js","assets/QRCodeCanvas-X07w5x_G.js","assets/AccountView-BvRvODjN.js"])))=>i.map(i=>d[i]);
2
+ import{i as e}from"./rolldown-runtime-C4Xdq4VV.js";import{$t as t,A as n,At as r,C as i,Dt as a,Et as o,G as s,K as c,Mt as l,N as u,Nt as d,Ot as f,Q as p,Qt as m,R as h,T as g,Tt as _,V as v,W as y,Xt as b,Y as x,Z as S,at as C,b as w,ft as ee,ht as te,jt as ne,kt as re,lt as ie,nt as T,ot as E,q as ae,st as oe,tt as D,ut as se,v as ce,w as le,z as ue}from"./vendor-react-Kt98jRfM.js";import{S as de,b as fe,g as pe,x as O}from"./vendor-icons-other-Bme3ywH9.js";import{n as k,t as me}from"./vendor-i18next-cO7FDf_e.js";import{A as he,B as ge,E as _e,F as ve,H as A,I as ye,N as j,P as M,S as be,T as xe,U as Se,V as N,c as Ce,f as we,i as Te,k as Ee,n as De,r as Oe,s as ke,t as Ae,v as je,w as P,x as F}from"./vendor-ui-core-BpucEp_q.js";import{_t as Me,vt as Ne}from"./vendor-utils-CfYGGC23.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var Pe=t(),Fe={common:{account:`Account`,logout:`Logout`,selectProfile:`Select Profile`,add:`Add`,newProfileName:`New Profile Name...`,profileNameFormatTip:`Profile Name tip: 1-30 characters, duplicates not allowed`,profileLimitExceeded:`Profile limit exceeded (max {{max}})`,profileNameExists:`The profile name already exists`,profileNameFormatError:`Invalid Profile Name format`,create:`Create`,welcome:`Welcome`,createProfileToStart:`Create a profile to get started.`,loading:`Loading...`,errorNetwork:`Network Error`,confirmDelete:`Are you sure you want to delete this profile?`,confirmLogout:`Are you sure you want to log out?`,notFound:`404 - Not Found`,notFoundDesc:`The page you are looking for does not exist or has been removed.`,backToHome:`Back to Home`,apac:`Asia Pacific`,mainlandChina:`Mainland China`,HongKong:`Hong Kong`,Singapore:`Singapore`,Tokyo:`Tokyo`,NorthAmerica:`North America`,nae:`North America East`,naw:`North America West`,eu:`Europe`,invalidFormat:`Invalid file format`,import:`Import`,importSuccess:`Profile imported successfully`,importError:`Failed to import profile. Please ensure the format is correct and try again.`,save:`Save`,saveSuccess:`Settings saved`},nav:{setup:`Setup`,rules:`Rules`,stats:`Analytics`,logs:`Logs`,filter:`Filters`,settings:`Settings`},theme:{light:`Light`,dark:`Dark`,system:`System`},auth:{keepLoggedIn:`Keep me logged in for {{days}} days`,login:`Login to DNS Worker`,signup:`Create an account to start`,welcomeBack:`Welcome back, please enter your credentials`,protectInternet:`Protect your first hop on the internet`,error:`Error`,username:`Username`,usernamePlaceholder:`Your username`,password:`Password`,passwordPlaceholder:`Your password`,loginBtn:`Login`,signupBtn:`Sign Up`,totpVerification:`TOTP Verification`,noAccount:`Don't have an account? Sign up now`,haveAccount:`Already have an account? Back to login`,formatTipUsername:`Username tip: 5-32 chars, Unix format (starts with lowercase letter/underscore, containing lowercase letters, numbers, hyphens and underscores)`,formatTipPassword:`Password tip: 12-100 characters`,authFailed:`Authentication failed, check username or password`,networkError:`Network error, please try again later`,turnstileRequired:`Please complete the human verification`,turnstileError:`Verification service failed to load, please reload the page and try again`,verifying:`Verifying security check...`,passwordLeaked:`Your password was found in a public data breach. For your security, please use a strong random password.`,usernameExists:`This username is already taken. Please try another one.`,skip:`Skip`,showPassword:`Show password`,hidePassword:`Hide password`,geolocationRequired:`Geolocation failed. Please try re-entering.`,unauthorizedDefault:`Your session has ended. Please log in again.`,unauthorizedGeo:`Session invalidated due to geographic location change (exceeded distance limit).`,unauthorizedExpired:`Your session has expired. Please log in again.`,unauthorizedReuse:`Security notice: Multiple logins detected. Session terminated.`,unauthorizedRevoked:`Your session has been revoked or deleted. Please log in again.`,sessionLockTitle:`Idle Session Lock`,sessionLockDesc:`Lock the interface with a 4-digit PIN when the application is idle to protect active sessions from unauthorized physical access.`,enableSessionLock:`Enable Session Lock`,inactivityTimeout:`Inactivity Timeout`,timeout1m:`1 Minute`,timeout2m:`2 Minutes`,timeout5m:`5 Minutes`,timeout15m:`15 Minutes`,timeout30m:`30 Minutes`,timeout60m:`60 Minutes`,changePin:`Change PIN`,disablePin:`Disable Session Lock`,configurePin:`Configure PIN`,newPin:`New 4-Digit PIN`,pinHelper:`Digits only, e.g., 1234`,confirmPin:`Confirm New PIN`,verifyIdentity:`Verify Identity`,usePassword:`Use Password`,use2fa:`Use TOTP Code`,totpCode:`TOTP Code`,currentPassword:`Current Password`,disablePinWarning:`Disabling the PIN will disable the inactivity session locking feature completely.`,pinFormatTip:`PIN must be exactly 4 digits`,pinMatchTip:`PINs do not match`,passwordRequired:`Password is required for verification`,sessionLocked:`Session Locked due to inactivity`,sessionExpired:`Too many failed attempts. Session terminated.`,pinIncorrect:`Incorrect PIN`,attemptsRemaining:`{{count}} attempts remaining`,logoutAndReturn:`Log Out Session`,lockNow:`Lock Now`,cfErrorWithDetails:`Cloudflare Edge error (Error {{code}}: {{desc}}). Service is temporarily unavailable, please try again later. {{rayId}}`,cfErrorCodeOnly:`Cloudflare Edge error (Error {{code}}). Service is temporarily unavailable, please try again later. {{rayId}}`,cfErrorGeneric:`Cloudflare Edge error, service is temporarily unavailable. Please try again later. {{rayId}}`,htmlErrorGeneric:`Server returned an unexpected page response (HTTP {{status}}). Please try again later.`,tooManyAttempts:`Too many requests or attempts, temporarily rate limited. Please try again later.`,dbQuotaExceeded:`Database daily read quota has been exceeded. Please wait for the daily reset or upgrade.`,noUsersRegistered:`No accounts registered yet. Please sign up to become an administrator.`,registerAdminTitle:`Register Administrator Account`,registerAdminDesc:`No accounts in the system. The first user will become the system administrator.`,goToRegisterAdmin:`Register Admin`,dbNotInitialized:`Database is not initialized or missing tables. Please run npm run db:migrate:prod in terminal.`,verifyWithPasskey:`Verify with Passkey`,orUseTotp:`Or use authenticator code`,passwordRequiredFirst:`Please enter your password first`,passkeyVerification:`Passkey Verification`,passkeyPromptDesc:`Verify using your registered biometric or security key`,forgotPassword:`Forgot password?`,forgotPasswordTitle:`Reset Password`,forgotPasswordDesc:`Recover your account securely using multi-factor authentication (Passkey or TOTP).`,noMfaContactAdmin:`This account has not configured any multi-factor authentication (Passkey or TOTP) and cannot self-recover. Please contact a system administrator to reset your password.`,chooseMfaForReset:`Choose an authentication method to verify your identity:`,authViaPasskey:`Verify with Passkey`,authViaPasskeyDesc:`1-click authentication using biometrics or a hardware security key`,authViaTotp:`Verify with Authenticator App (TOTP)`,authViaTotpDesc:`Enter the 6-digit dynamic code from your authenticator app`,authViaRecoveryKey:`Use Emergency Recovery Key`,authViaRecoveryKeyDesc:`Enter a 10-character emergency recovery key`,verifyAndProceed:`Verify and Continue`,setNewPassword:`Set New Password`,setNewPasswordDesc:`Identity verified. Please set a new password for your account.`,newPassword:`New Password`,confirmNewPassword:`Confirm New Password`,passwordMismatch:`New passwords do not match`,saveAndReset:`Save and Reset Password`,resetSuccessTitle:`Password Reset Successfully`,resetSuccessDesc:`Your password has been updated and all existing login sessions have been terminated. Please log in with your new password.`,goToLogin:`Proceed to Login`,mfaSetupTitle:`Enhance Account Security`,mfaSetupDesc:`Configuring Multi-Factor Authentication (MFA) safeguards your account, unlocks passwordless login, and enables self-service password recovery.`,mfaRecommended:`Recommended`,passkeySignupDesc:`Use Touch ID, Face ID, Windows Hello, or a security key. Lightning-fast and phishing-resistant.`,bindPasskeyNow:`Register Passkey Now`,mfaUniversal:`Universal`,totpSignupDesc:`Use Google Authenticator, 1Password, or any standard authenticator app.`,setupTotpBtn:`Set Up Authenticator App`,skipMfaSetup:`Skip for now, complete signup`,backToMfaOptions:`Back to options`,otherOptions:`Other options`,next:`Next`,mfaVerification:`Multi-Factor Authentication`,totpPrompt:`Enter the 6-digit dynamic code from your authenticator app`,recoveryPrompt:`Enter your 30-digit recovery key (5 groups of 6 digits)`,recoveryChecksumError:`Checksum error: this group is not divisible by 11`,recoveryChecksumErrorDesc:`Checksum error in group {{groups}}, please check and try again`,backToPasskey:`Back to Passkey verification`,recoveryKeyRequired:`Please enter your recovery key`,totpFormatError:`Please enter a valid 6-digit code`,registrationDisabledTitle:`Registration Disabled`,registrationDisabledDesc:`New user registration is currently closed. Please contact a system administrator to obtain an account.`,backToLogin:`Back to login`,jwtSecretPreset:`Default preset JWT_SECRET detected. Please update and customize JWT_SECRET in environment variables before deploying.`,jwtSecretMissing:`JWT_SECRET is missing. Please configure a secure key in environment variables before deploying.`,jwtSecretInvalid:`JWT_SECRET format is invalid, please check configuration.`},setup:{title:`Setup Guide`,subtitle:`Configure your devices to use DNS Worker and master your internet security.`,regionOptimization:`Region Optimization (Windows)`,otherRegion:`Other Region`,copied:`Copied to clipboard`,verifyConnection:`Verify Your Connection`,verifying:`Verifying...`,connected:`Connected`,notConnected:`Not Connected`,profileMatch:`Filtering through this profile.`,profileMismatch:`Using Obex, but Profile ID mismatch.`,verifyHint:`Click to verify after configuration.`,refreshStatus:`Refresh Status`,egressIp:`Egress IP Address`,currentLocation:`Current Location`,edgeServer:`Edge Server`,dohUrlTitle:`Current Config DoH URL`,accessPointTitle:`Access DoH URL`,defaultAccessPointName:`Device-1`,moreAccessPoints:`More Access Points ↗`,accessPointName:`Access Point Name`,accessPointToken:`Access Key`,addAccessPoint:`Add Access Point`,renameAccessPoint:`Rename`,rotateToken:`Rotate Key`,rotateTokenConfirmDesc:`Rotating the key will immediately disconnect devices using the old key. Are you sure you want to continue?`,deleteAccessPoint:`Delete`,deleteAccessPointConfirm:`Are you sure you want to delete this access point?`,manageAccessPoints:`Manage Access Points`,searchAccessPoints:`Search Access Points...`,accessPointNameExists:`Access Point name already exists`,accessPointCreated:`Access Point created successfully`,accessPointRenamed:`Access Point renamed successfully`,accessPointDeleted:`Access Point deleted successfully`,accessPointNameFormatTip:`Access Point Name tip: 1-30 characters, letters, numbers, hyphens and underscores only`,accessPointLimitExceeded:`Access Point limit exceeded (max {{max}})`,tokenRotated:`Access Key rotated successfully`,whatIsDoh:`What is DoH?`,dohDesc:`DNS over HTTPS (DoH) is a protocol for performing remote DNS resolution via the HTTPS protocol.`,dohBenefit1:`Prevents ISP hijacking and eavesdropping`,dohBenefit2:`Enhances DNS resolution and overall security`,learnMore:`Learn more`,copyUrl:`Copy URL`,browsers:`Browsers`,browserTitle:`Browser Configuration (Chrome/Edge)`,browserSteps:`Settings > Privacy and security > Security > Use secure DNS > Custom > Paste URL.`,browserTips:`Or paste this into your address bar:`,apple:`Apple`,appleTitle:`macOS / iOS / iPadOS / tvOS`,appleDesc:`Apple devices support quick configuration via profiles.`,appleWarning:`Profiles cannot be installed in 'Lockdown Mode'. Please ensure your system is not in this state.`,downloadConfig:`Download Profile`,appleInstallHint:`After downloading, go to 'Settings' > 'Profile Downloaded' to install.`,windows:`MS Windows`,windowsTitle:`Windows 11 Config [Region: {{region}}]`,windowsStep0:`Settings > Network & internet`,windowsStep1:`Properties > DNS server assignment > Edit > Manual.`,windowsStep2:`Fill in DNS IPs:`,windowsStep3:`Enable DoH (manual template) and paste URL.`,windowsStep4:`Disable Fallback to plaintext.`,android:`Android`,androidTitle:`Android 9+`,androidDesc:`Supports native system Private DNS (DoT) or third-party apps for DoH.`,androidDotTitle:`Private DNS (DoT - Serverfull Mode)`,androidDotDesc:`Settings > Network & internet > Private DNS > Private DNS provider hostname:`,androidWarning:`Note: Android's native 'Private DNS' uses the DoT protocol. When deployed on Cloudflare Workers, use apps like Intra for DoH. When running in Serverfull mode with TLS configured, you can directly use the DoT hostname above.`,dynamicFromDomain:`Dynamic (from {{domain}})`,dynamicFromDomainV6:`Dynamic IPv6 (from {{domain}})`,linux:`Linux`,linuxTitle:`Linux (Cloudflared DoH Proxy)`,linuxDesc:`Run a local DNS proxy to forward queries to Obex via DoH.`,linuxStep1:`Run this script to install cloudflared and setup systemd service (listening on 127.0.0.1:53).`,linuxStep2:`Change your system DNS to 127.0.0.1.`,routeros:`MikroTik`,routerosTitle:`MikroTik RouterOS`,routerosDesc:`Use this resolver for every device on your network by setting it as the router's DoH server.`,routerosStep1:`Run in the RouterOS terminal (RouterOS 7):`,routerosNote:`Queries forwarded by the router show up in the logs as the router, not as individual devices. Set up devices directly if you need per-device logs.`,routerosDocs:`MikroTik DNS documentation`,accessPointsCardTitle:`Access Points`,currentAccessPoint:`Current Access Point`,selectAccessPointToConfigure:`Select Access Point to Configure`},rules:{title:`Custom Rules`,subtitle:`Manually control DNS behavior for specific domains (Allow, Block, or Redirect).`,action:`Action`,typeBlock:`BLOCK`,typeAllow:`ALLOW`,typeRedirect:`REDIRECT`,pattern:`Domain Pattern`,patternPlaceholder:`example.com or *.test.com`,addRule:`Add Rule`,redirectSettings:`Redirect Settings`,aRecord:`A Record (IPv4)`,aaaaRecord:`AAAA Record (IPv6)`,cnameRecord:`CNAME Record`,txtRecord:`TXT Record`,optional:`(optional)`,ipv4Placeholder:`e.g. 1.2.3.4`,ipv6Placeholder:`e.g. 2001:db8::1`,cnamePlaceholder:`e.g. target.com`,txtPlaceholder:`Enter text content...`,saveRedirectRule:`Save Redirect Rule`,noRulesTitle:`No Custom Rules`,noRulesDesc:`You haven't added any manual rules yet.`,tableAction:`Action`,tablePattern:`Pattern`,tableDetails:`Details`,tableOps:`Ops`,labelBlock:`Block`,labelAllow:`Allow`,labelRedirect:`Redirect`,detailBlock:`Resolves to`,detailAllow:`Forward to upstream`,patternEmpty:`Domain pattern cannot be empty`,duplicatePattern:`Rule for this domain already exists`,addSuccess:`Rule added successfully`,addFailed:`Failed to add rule`,updateSuccess:`Rule updated successfully`,updateFailed:`Failed to update rule`,tableCreatedAt:`Added Time`,clickToSort:`Click to sort`},analytics:{customRange:`Custom Range`,startTime:`Start Time`,endTime:`End Time`,apply:`Apply`,custom:`Custom`,totalQueries:`Total Queries`,blocked:`Blocked`,redirected:`Redirected`,blockRate:`Block Rate`,activeDevices:`Active Devices`,activeIPs:`Active IP addresses`,queryTrend:`Query Trend`,noRecords:`No records in this period`,topAllowed:`Top Allowed Domains`,topBlocked:`Top Blocked Domains`,noData:`No data`,clientActivity:`Client Activity`,ipAddress:`IP Address`,location:`Location`,queries:`Queries`,destinationDistribution:`Destination Distribution`,requests:`Requests`,topIsps:`Top ISPs`,pressToShowMore:`Press to show more`,maximize:`Maximize`,minimize:`Minimize`},logs:{title:`Query Logs`,subtitle:`View DNS resolution logs and block history.`,realtime:`Realtime`,allStatus:`All Status`,onlyPass:`Allowed`,onlyBlock:`Blocked`,onlyRedirect:`Redirected`,searchPlaceholder:`Search domains...`,noResults:`No results found`,noRecords:`No records yet`,noResultsDesc:`No domain records matching "{{query}}" found.`,noRecordsDesc:`No DNS queries received in the selected timeframe.`,tableTime:`Time`,tableDomain:`Domain`,tableAnswer:`Answer`,tableSource:`Source`,tableType:`Type`,tableStatus:`Status`,tableReason:`Reason`,loadedAll:`Loaded all {{count}} records`,realtimeLoadMoreTip:`Disable 'Real-time' mode to load more`,filterAccessPoint:`Access Point`,allAccessPoint:`All Access Points`,allCountry:`All Countries`,filterCountry:`Dest Country`,allIsp:`All ISPs`,filterIsp:`ISP`,timeRange:`Time Range`,clearFilters:`Clear Filters`,details:`Query Details`,detailAccessPoint:`Access Point`,basicInfo:`Basic Info`,detailDomain:`Domain`,detailType:`Type`,detailTime:`Time`,detailLatency:`Latency`,detailProfile:`Profile Used`,detailStatus:`Status`,detailUpstream:`Upstream`,detailReason:`Reason`,detailNoReason:`None (Allowed)`,detailECS:`ECS`,resolutionResult:`Resolution Result`,noResult:`No result`,networkDetails:`Network Details`,clientSource:`Client (Source)`,destination:`Destination (Parsed)`,quickActions:`Quick Actions`,actionAllow:`Allow`,actionBlock:`Block`,actionRedirect:`Redirect`,statusPass:`PASS`,statusBlock:`BLOCK`,statusRedirect:`REDIRECT`,export:`Export Logs`,rewritten:`Rewritten`,logDetails:`Log Details`,searchCountry:`Search country...`,noMatchingCountries:`No matching countries found`,searchIsp:`Search ISP...`,noMatchingIsps:`No matching ISPs found`,loadingIsps:`Loading ISPs...`,loggingDisabledTitle:`Logging Disabled`,loggingDisabledDesc:`Log retention for this profile is set to 'Disabled'. No query logs are recorded. To view logs, enable log retention in Settings.`},filtering:{title:`External Filters`,subtitle:`Subscribe to third-party blocklists (e.g., AdGuard).`,formatDisclaimer:`This system only supports a limited set of AdGuard format lists and plain domain lists. Only basic blocking rules (e.g., ||example.com^) are supported, and "@@" whitelist rules will be bypassed. "$" rewrite rules and "*" wildcard/omit rules are temporarily not supported. The system will automatically match all subdomains of the domains.`,syncAll:`Sync All Lists`,urlPlaceholder:`Enter list URL...`,addSubscription:`Add List`,supportedFormats:`Supported Formats:`,formatAdGuard:`Compatible with ||domain.com^ rules.`,formatHosts:`Compatible with standard hosts files.`,noListsTitle:`No Lists Added`,noListsDesc:`You haven't subscribed to any external blocklists yet.`,tableUrl:`List URL`,tableLastSync:`Last Sync`,tableStatus:`Status`,tableOps:`Ops`,neverSynced:`Never`,enabled:`Active`,disabled:`Error`,statusNormal:`Active`,statusDisabled:`Disabled`,statusOutdated:`Outdated`,statusMissing:`Missing`,presetOisdBig:`OISD Big (Ads/Malware etc.)`,presetOisdNsfw:`OISD NSFW (Adult/Shock content)`,presetAdGuard:`AdGuard AdServers`,presetStevenBlack:`StevenBlack Hosts`,syncTaskStarted:`Sync Task Started`,syncCheckComplete:`Sync Check Completed`,syncTaskFailed:`Sync Task Failed`,syncing:`Syncing...`,syncSuccess:`List synced successfully`,syncError:`Failed to sync list`,syncErrorDesc:`Failed to download or parse the filter list. Please check the URL and ensure it is accessible.`,deleteConfirm:`Are you sure you want to delete this list subscription?`,deleteSuccess:`List deleted successfully`,deleteError:`Failed to delete list`,addSuccess:`List added successfully`,addError:`Failed to add list`,listEnabled:`List active`,listEnabledHint:`Disable to stop filtering with this list without deleting it. Its subscription and sync history are kept.`,listEnabledToast:`List enabled - rebuilding filter`,listDisabledToast:`List disabled - rebuilding filter`,checkDomain:`Check a domain`,checkDomainHint:`Lists are stored as compact filters, so their entries cannot be browsed. You can test any domain against this list instantly.`,check:`Check`,checkBlocked:`Blocked by this list`,checkNotBlocked:`Not blocked by this list`,checkViaParent:`(matched a parent domain)`,checkNotSynced:`This list has not finished syncing yet, so there is nothing to check against.`,checkListDisabled:`This list is currently disabled, so it is not filtering anything right now.`,checkProbabilisticRate:`Filters are probabilistic: roughly 1 match in {{odds}} is a false positive. Adding an exception also covers every subdomain of it.`,checkProbabilistic:`Filters are probabilistic, so a small share of matches are false positives. Adding an exception also covers every subdomain of it.`,checkAllowAction:`Allow anyway`,checkAllowed:`Exception added - this domain now resolves`,allowRuleAdded:`Exception added for {{domain}}`},settings:{title:`Settings`,subtitle:`Manage resolution policies and advanced options.`,saveChanges:`Save Changes`,saveSuccess:`Settings saved successfully`,saveError:`Failed to save settings`,upstreamTitle:`Upstream Services`,dohUrl:`DoH URL`,dnsIP:`DNS IP`,classicDns:`Classic DNS`,httpsOnly:`HTTPS Only`,upstreamDesc:`All unblocked queries will be forwarded to this upstream server. Supports DoH (HTTPS), DoT (tls://), DNS Stamp (sdns://), or Classic DNS. Classic DNS is forwarded via TCP.`,defaultPolicyTitle:`Default Policy`,onNoMatch:`On No Match`,allowAll:`Allow all queries`,blockAll:`Block all queries`,logRetentionTitle:`Log Retention`,retentionDuration:`Duration`,retentionDesc:`Logs are cleared automatically.`,skipLogOnPass:`Do not log allowed queries`,skipLogOnPassDesc:`When enabled, normal allowed queries will not be recorded. Only blocked, redirected, or failed queries are logged, significantly reducing storage and write operations.`,ecsTitle:`EDNS Client Subnet (ECS)`,ecsUpstreamHint:`Not all upstream DNS servers support ECS. For recursive resolvers like ControlD, ECS affects internal routing only.`,sendEcs:`Send ECS`,customSubnet:`Custom Subnet`,customIpv4:`Custom IPv4 Subnet`,customIpv6:`Custom IPv6 Subnet`,ipv4Hint:`(e.g., 1.2.3.0/24)`,ipv6Hint:`(e.g., 2001:db8::/32)`,testToolTitle:`Resolution Test Tool`,testDomain:`Test Domain`,recordType:`Record Type`,runTest:`Run Test`,domainPlaceholder:`e.g., google.com`,hitRule:`Rule / Reason`,defaultAllow:`Default Allow`,parseLatency:`Latency`,sourceIp:`Source IP`,answerSection:`Answer Section`,noRecordsReturned:`No records returned for this query.`,diagnostics:`Diagnostics`,errorDetail:`Error Details`,upstreamResponse:`Upstream Response`,presetCloudflareSecurity:`Cloudflare Security`,presetCloudflareFamilies:`Cloudflare Families`,presetQuad9:`Quad9 (No Log/No ECS)`,presetQuad9Ecs:`Quad9 ECS (No Log/With ECS)`,presetControlDFree:`ControlD Free (Remove ads/tracking/malicious/phishing)`,presetControlDUncensored:`ControlD Uncensored`,presetAdGuard:`AdGuard (Anti-track)`,presetAdGuardFamily:`AdGuard Family`,retention10m:`10 Minutes`,retention1h:`1 Hour`,retention24h:`24 Hours`,retention7d:`7 Days`,retention30d:`30 Days`,retention90d:`90 Days (Maximum)`,blockModeTitle:`Block Response Mode`,blockModeDesc:`Response content when a domain is blocked`,default:`Default`,NXDOMAIN:`NXDOMAIN`,NODATA:`NODATA`,customIP:`Custom IP`,export:`Export Config`,exportSuccess:`Config exported successfully`,exportError:`Export failed`,nameUpdateSuccess:`Profile name updated`,saving:`Saving...`,echTitle:`Rewrite ECH`,enableEch:`Enable ECH Rewrite`,echDesc:`For Cloudflare-proxied domains, automatically injects and rewrites ECH parameters and outer SNI on HTTPS (Type 65) / SVCB (Type 64) queries to protect domain privacy.`,echFrontingTitle:`Outer SNI (ECH Fronting)`,echFrontingDesc:`Domain name visible in plaintext on the outer TLS handshake`,echFrontingCustomPlaceholder:`Enter custom fronting domain, e.g. crypto.cloudflare.com`,echPreferred:`Recommended`,whatIsEch:`What is ECH (Encrypted Client Hello)?`,echHelpDesc:`ECH (Encrypted Client Hello) is a crucial TLS 1.3 privacy extension that fully encrypts the real Server Name Indication (Inner SNI), exposing only a fronting domain (Outer SNI) to network observers.`,echHelpBenefit1:`Prevents ISPs and eavesdroppers from inspecting the exact domain or subdomain you are visiting`,echHelpBenefit2:`Combines with DoH and ECH Fronting to eliminate plaintext SNI leakage and filtering`,retentionDisabled:`Disabled (Privacy Concerns)`,retentionDisabledDesc:`Logging is disabled. The system will not record any DNS query logs and will immediately clear historical logs.`},account:{title:`Account Settings`,subtitle:`Manage your security credentials and system users.`,jwtSecretWarningTitle:`Security Notice: Weak JWT Secret`,jwtSecretWarningDesc:`The current JWT_SECRET is shorter than 32 characters, which introduces potential security risks. Please configure the KEK_v1 environment variable before rotating JWT_SECRET to ensure existing envelope-encrypted TOTP and recovery keys remain decryptable.`,roleAdmin:`Administrator`,roleUser:`User`,personalInfo:`Personal Info`,username:`Username`,userId:`User ID`,changePassword:`Change Password`,currentPassword:`Current Password`,newPassword:`New Password`,updatePassword:`Update Password`,userManagement:`User Management (Admin)`,createUser:`Create User`,role:`Role`,createdAt:`Created At`,lastActive:`Last Active`,lastResolve:`Last Resolve`,actions:`Actions`,dangerZone:`Danger Zone`,clearLogs:`Clear All Logs`,clearLogsDesc:`This will delete all resolution logs for all your profiles. This cannot be undone.`,clearLogsBtn:`Clear Logs Now`,deleteAccount:`Delete Account`,deleteAccountDesc:`Permanently delete your account and all associated data. You will lose all DNS configurations.`,deleteAccountBtn:`Delete Account Now`,createNewUser:`Create New User`,initialPassword:`Initial Password`,userRole:`User Role`,cancel:`Cancel`,createNow:`Create Now`,formatTipUsername:`Username tip: 5-32 chars, Unix format`,formatTipPassword:`Password tip: 12-100 characters`,passwordSuccess:`Password updated successfully`,updateFailed:`Update failed`,confirmDeleteUser:`Are you sure you want to delete this user? All their profiles will be removed.`,confirmClearLogs:`Are you sure you want to clear all logs? This cannot be undone.`,clearLogsSuccess:`Logs cleared successfully`,confirmDeleteAccount:`WARNING: Are you sure you want to delete your account?
3
+
4
+ All DNS profiles, custom rules, and logs will be permanently deleted. This is irreversible!`,inactivityPolicy:`Inactivity Policy`,inactivityDesc:`To protect user privacy and save resources, all query logs and DNS configurations for accounts with no resolution activity for 30 days will be cleared. The account itself will be removed after 90 days of no login activity.`,systemSettings:`System Settings (Admin)`,adminOnlyView:`Visible to admins only`,featureToggle:`Feature Toggle`,enableTurnstileSignup:`Enable verification on Signup`,enableTurnstileLogin:`Enable verification on Login`,totp:{title:`Authenticator App (TOTP)`,enabled:`Enabled`,disabled:`Disabled`,setupDesc:`Add an extra layer of security to your account. Use Google Authenticator, Authy, or any TOTP-compatible app.`,setupBtn:`Set Up Authenticator App (TOTP)`,scanQR:`Scan this QR code with your authenticator app:`,orEnterManually:`Or enter the key manually:`,enterCode:`Verify with your authenticator code:`,enterCodeHint:`Enter the 6-digit code to confirm the key was scanned correctly.`,activate:`Activate TOTP`,skipPassword:`Passwordless login — hide password field at login (TOTP only)`,disable:`Disable Authenticator App (TOTP)`,disableTitle:`Disable Authenticator App (TOTP)`,disableWarning:`After disabling TOTP, if no Passkeys are configured, your account will only be protected by password.`,confirmDisable:`Disable TOTP`,recoveryKeysTitle:`Save Your Recovery Keys`,recoveryKeysWarning:`Store your recovery key safely (e.g., in a password manager). Each key can only be used once.`,copyKeys:`Copy All Keys`,copied:`Copied!`,done:`Done — I've saved my keys`,activeDesc:`Authenticator app (TOTP) is active and generating 6-digit verification codes for your account.`},sessions:{session:`Session`,title:`Active Sessions`,device:`Device`,ip:`IP Address`,loginTime:`Login Time`,expires:`Expires`,action:`Action`,current:`Current`,revoke:`Revoke`,revokeFailed:`Failed to revoke session.`,empty:`No active sessions found.`,unknownDevice:`Unknown Device`,revokeOthers:`Revoke Other Sessions`,confirmRevokeOthers:`Revoke Other Sessions`,revokeOthersConfirmText:`Are you sure you want to revoke all other active sessions? All other logged-in devices will be signed out immediately.`},activity:{title:`Account Activity`,action:`Event`,time:`Time`,session:`Session`,ip:`IP Address`,empty:`No activity recorded yet.`,loadMore:`Load More`,signup:`Register`,loginSuccess:`Login`,loginFail:`Login Failed`,logout:`Logout`,pwChangeSuccess:`Password Changed`,pwChangeFail:`Password Change Failed`,totpVerifySuccess:`TOTP Verification Succeeded`,totpVerifyFail:`TOTP Verification Failed`,totpSetup:`Configured TOTP Authenticator`,totpRemoved:`Disabled TOTP Authenticator`,recoveryKeyUsed:`Recovery Key Used`,sessionRevoked:`Session Revoked`,reasons:{user_active:`Active logout`,user_revoke:`Session revoked`,expired:`Session expired`,geolocation_mismatch:`Geographic location mismatch`,geolocation_missing:`Geolocation missing`,token_reuse:`Token reused (security warning)`},passkeyRegistered:`Passkey Registered`,passkeyDeleted:`Passkey Deleted`,passkeyVerifySuccess:`Passkey Verified`,passkeyVerifyFail:`Passkey Verification Failed`,recoveryKeyRotated:`Recovery key rotated`},passkey:{title:`Passkeys`,addBtn:`Add Passkey`,desc:`Use biometric authentication (Touch ID, Face ID, Windows Hello) or hardware security keys (YubiKey) for fast, phishing-resistant MFA.`,empty:`No passkeys added yet.`,addTitle:`Add Passkey`,nameLabel:`Passkey Name`,namePlaceholder:`e.g. my_passkey`,promptNotice:`After clicking continue, your browser will prompt you to complete biometric or security key registration.`,continue:`Continue`,renameTitle:`Rename Passkey`,deleteTitle:`Delete Passkey`,deleteConfirm:`Are you sure you want to delete passkey "{{name}}"? You will no longer be able to use it for multi-factor authentication.`,defaultName:`Passkey`,notSupported:`Your browser or current environment does not support passkeys (WebAuthn).`,regFailed:`Passkey registration failed`,count:`{{count}} configured`,none:`Not configured`,created:`Created`,lastUsed:`Last used`,neverUsed:`Never used`,updated:`Passkey updated successfully`,registered:`Passkey registered successfully`,deleted:`Passkey deleted`,appNameLabel:`Domain`,appNameHelper:`The passkey will be bound to this application domain`,formatTip:`Passkey name tip: 1-30 characters, letters, numbers, hyphens and underscores only`,verifyPrompt:`Authenticate using your device's biometric sensor (Face ID, Touch ID, Windows Hello) or security key.`,changePwNotice:`You will be prompted to verify via biometric authentication or your security key when submitting.`,submitNotice:`You will be prompted to verify via biometric authentication or your security key when submitting.`},mfaNone:`None`,resetUserPassword:`Reset Password`,resetPasswordTitle:`Reset User Password`,resetPasswordWarning:`After reset, all existing login sessions for this user will be invalidated immediately. The user must sign in with the new password.`,resetPasswordSuccess:`Password reset successfully. The user's active sessions have been terminated.`,confirmReset:`Confirm Reset`,mfa:{title:`Multi-Factor Authentication (MFA)`,enabled:`Configured`,notConfigured:`Not Configured`,desc:`Passkeys and Authenticator Apps (TOTP) both serve as MFA authentication methods. Configuring at least one factor protects your account and enables passwordless login and self-service password recovery.`,passwordlessTitle:`Passwordless Login`,passwordlessDesc:`When enabled, logging in will skip the password requirement and verify your identity directly via Passkey or TOTP.`,unconfiguredHint:`No MFA method configured yet. Set up either a Passkey or Authenticator App below to safeguard your account and unlock passwordless login and account recovery.`},recoveryKey:{title:`Emergency Recovery Key`,desc:`An emergency recovery key allows you to regain access or reset your password if you lose all registered Passkeys or Authenticator Apps. Store it securely offline.`,configured:`Configured`,notConfigured:`Not Configured`,kekProtected:`KEK Encrypted`,kekTooltip:`Protected with AES-256-GCM Envelope Encryption backed by Key Encryption Key (KEK).`,viewBtn:`View Recovery Key`,rotateBtn:`Rotate Key`,yourKey:`Your 30-Digit Recovery Key`,securityTip:`Keep this recovery key secret. Anyone with access to this key can regain access to your account.`,rotateConfirm:`Rotating your recovery key will immediately invalidate the current recovery key. You will need to verify your identity to complete this action.`,confirmRotateBtn:`Proceed to Rotate`,viewVerifyTitle:`Verify Identity to View Key`,rotateVerifyTitle:`Verify Identity to Rotate Key`,rotateSuccess:`Recovery key rotated successfully! Please store your new key in a safe place immediately.`,legacyNotice:`Your recovery key is stored as a legacy one-way hash and cannot be decrypted for display. Please rotate your recovery key to generate a new KEK envelope-encrypted key.`},verifyIdentity:`Security Verification`,verifyIdentityDesc:`To protect your account security, please verify your identity before proceeding.`,usePasskeyInstead:`Authenticate with Passkey`,changePasswordWithPasskey:`Verify with Passkey & Update`,enableRegistration:`Enable user registration`},intro:{item1Title:`Obex Protective DNS`,item1Desc:`Cloudflare Workers & D1 based DNS resolver, optimized for speed and security.`,item2Title:`DoH Privacy`,item2Desc:`Prevent hijacking and enhance privacy via DNS over HTTPS (RFC 8484) encryption.`,item3Title:`Global Edge Network`,item3Desc:`Extreme speed and ultra-low latency powered by Cloudflare's edge network.`,item4Title:`Fine-grained Filtering`,item4Desc:`Full support for whitelist/blacklist, AdGuard rules, and custom DNS redirects.`,item5Title:`Real-time Analytics`,item5Desc:`Gain insights into network health with detailed logs and comprehensive dashboards.`,item6Title:`Modern UI & Dark Mode`,item6Desc:`High-density dashboard designed for power users, built with Blueprint UI.`,item7Title:`Cloud Native Architecture`,item7Desc:`Serverless architecture ensures zero maintenance and infinite scalability.`,item8Title:`Multi-Profile Management`,item8Desc:`Manage independent configurations for different devices or environments.`,item9Title:`Multiple Access Points`,item9Desc:`Configure unique sub-URLs for different devices to monitor logs and statistics independently.`},deploymentGuide:{title:`DNS Worker Setup & Deployment Guide`,subtitle:`Your instance is not fully configured yet. Please complete the setup below to start using DNS Worker.`,dbStatus:`D1 Database Binding (env.DB)`,jwtStatus:`JWT Secret Key (env.JWT_SECRET)`,configured:`Configured`,missing:`Missing / Not Configured`,refresh:`Refresh & Verify`,methodCli:`CLI Deployment`,methodDash:`Cloudflare Dashboard Deployment`,copy:`Copy`,copied:`Copied!`,stepDbTitle:`1. Bind D1 Database`,stepDbDesc:`Create a D1 database and bind it to your worker. In your terminal, run:`,stepDbCommand1:`wrangler d1 create dns_worker_db`,stepDbDesc2:`Copy the output D1 database details and paste them into your wrangler.toml under [[d1_databases]]:`,stepDbCommand2:`[[d1_databases]]
5
+ binding = "DB"
6
+ database_name = "dns_worker_db"
7
+ database_id = "<YOUR_D1_DATABASE_ID>"
8
+ migrations_dir = "migrations"`,stepDbDashDesc:`1. Go to Cloudflare Dashboard -> Workers & Pages -> D1. Click "Create Database" and name it 'dns_worker_db'.
9
+ 2. Go to your Worker -> Settings -> Variables -> D1 Database Bindings -> Add Binding.
10
+ 3. Set Binding name to 'DB', and select 'dns_worker_db' as D1 database. Click Save.
11
+ 4. Go to your D1 database -> Console, copy and execute the SQL tables schema script from the migrations folder to set up database structure.`,stepJwtTitle:`2. Set JWT Secret Key`,stepJwtDesc:`DNS Worker requires a JWT secret for signing session tokens and API security. Configure it as a Cloudflare Secret:`,stepJwtCommand1:`wrangler secret put JWT_SECRET`,stepJwtDashDesc:`1. Go to your Worker -> Settings -> Variables -> Environment Variables -> Add Variable.
12
+ 2. Set Name to 'JWT_SECRET', choose type 'Secret', and enter a secure random string (e.g. 64 hex characters) as Value.
13
+ 3. Save and Deploy.`,stepJwtDesc2:`Cloudflare Dashboard`,stepJwtCommand2:`https://dash.cloudflare.com/`,stepDeployTitle:`3. Deploy & Apply Migrations`,stepDeployDesc:`Run the deploy command to compile frontend, apply D1 database schema migrations automatically, and publish configurations live:`,stepDeployCommand:`npm run deploy`,stepDeployDashDesc:`If you completed all configurations via the Cloudflare Dashboard, go to your Worker's Deployments tab, click 'Deploy' or 'Re-deploy' to publish the latest configurations.`,jwtGeneratorTitle:`Secure JWT_SECRET Generator`,jwtGeneratorDesc:`Use this cryptographically secure key generator to generate a random 64-character alphanumeric secret for your env.JWT_SECRET.`,regenerate:`Regenerate`}},Ie={"zh-CN":()=>O(()=>import(`./zh-CN-D8YK7j27.js`),[]).then(e=>e.default),"zh-SG":()=>O(()=>import(`./zh-CN-D8YK7j27.js`),[]).then(e=>e.default),"zh-TW":()=>O(()=>import(`./zh-TW-C2_-uaZk.js`),[]).then(e=>e.default),"zh-HK":()=>O(()=>import(`./zh-TW-C2_-uaZk.js`),[]).then(e=>e.default),"ja-JP":()=>O(()=>import(`./ja-JP-CCVeJXwX.js`),[]).then(e=>e.default),"ko-KR":()=>O(()=>import(`./ko-KR-bQ1okpC2.js`),[]).then(e=>e.default),"fr-FR":()=>O(()=>import(`./fr-FR-1qQHEpoW.js`),[]).then(e=>e.default),"de-DE":()=>O(()=>import(`./de-DE-CXKS_pep.js`),[]).then(e=>e.default),"es-ES":()=>O(()=>import(`./es-ES-B2e3ea35.js`),[]).then(e=>e.default),"ru-RU":()=>O(()=>import(`./ru-RU-DeRsms_o.js`),[]).then(e=>e.default),"vi-VN":()=>O(()=>import(`./vi-VN-BcXfqmzH.js`),[]).then(e=>e.default)};async function Le(e){if(k.hasResourceBundle(e,`translation`))return!0;let t=Ie[e];if(!t)return!1;try{let n=await t();return k.addResourceBundle(e,`translation`,n,!0,!0),!0}catch(t){return console.warn(`[i18n] Failed to load locale "${e}":`,t),!1}}k.use(me).use(m).init({resources:{"en-US":{translation:Fe},"en-GB":{translation:Fe},"en-SG":{translation:Fe}},fallbackLng:`en-US`,interpolation:{escapeValue:!1}}),Le(k.language);var Re=k,I=e(de(),1),L=e(fe(),1);const ze=()=>(0,L.jsx)(`a`,{href:`https://github.com/Obein/DNS-Worker`,target:`_blank`,rel:`noopener noreferrer`,className:`github-corner fixed bottom-0 right-0 z-1000 hidden md:block transition-all duration-300 hover:scale-125 origin-bottom-right opacity-40 hover:opacity-100`,"aria-label":`View source on GitHub`,children:(0,L.jsxs)(`svg`,{width:`60`,height:`60`,viewBox:`0 0 250 250`,style:{fill:`#151513`,color:`#fff`,transform:`rotate(90deg)`},"aria-hidden":`true`,children:[(0,L.jsx)(`path`,{d:`M0,0 L115,115 L115,115 L142,142 L250,250 L250,0 Z`}),(0,L.jsxs)(`g`,{transform:`rotate(-135 180 80)`,children:[(0,L.jsx)(`path`,{d:`M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2`,fill:`currentColor`,style:{transformOrigin:`130px 106px`},className:`octo-arm`}),(0,L.jsx)(`path`,{d:`M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.3 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.9 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z`,fill:`currentColor`,className:`octo-body`})]})]})});function R(e){let t=()=>e().catch(e=>{if(e.message?.includes(`Failed to fetch dynamically imported module`)||e.name===`TypeError`||/dynamically imported module/i.test(e.message||``)){let e=sessionStorage.getItem(`chunk_reload`),t=Date.now();(!e||t-parseInt(e,10)>1e4)&&(sessionStorage.setItem(`chunk_reload`,t.toString()),window.location.reload())}throw e}),n=(0,I.lazy)(t);return n.preload=t,n}function z(){let[e,t]=(0,I.useState)(window.innerWidth<768);return(0,I.useEffect)(()=>{let e=()=>t(window.innerWidth<768);return window.addEventListener(`resize`,e),()=>window.removeEventListener(`resize`,e)},[]),e}const Be=()=>{let e=r(),{t}=b();return(0,L.jsx)(`div`,{className:`h-full flex items-center justify-center`,children:(0,L.jsx)(ke,{icon:`search`,title:t(`common.notFound`),description:t(`common.notFoundDesc`),action:(0,L.jsx)(j,{intent:N.PRIMARY,onClick:()=>e(`/`),children:t(`common.backToHome`)})})})};var Ve=R(()=>O(()=>import(`./SetupView-D7d-Gsdr.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8])).then(e=>({default:e.SetupView}))),He=R(()=>O(()=>import(`./FilteringView-BWD3e-DS.js`),__vite__mapDeps([9,1,2,3,4,5,6,7])).then(e=>({default:e.FilteringView}))),Ue=R(()=>O(()=>import(`./RulesView-3d5hga0L.js`),__vite__mapDeps([10,1,2,3,4,5,6,7])).then(e=>({default:e.RulesView}))),We=R(()=>O(()=>import(`./SettingsView-B9D0kPUF.js`),__vite__mapDeps([11,1,2,3,4,5,6])).then(e=>({default:e.SettingsView}))),Ge=R(()=>O(()=>import(`./AnalyticsView-DQ7hDChh.js`),__vite__mapDeps([12,1,2,3,4,5,6,7,13])).then(e=>({default:e.AnalyticsView}))),Ke=R(()=>O(()=>import(`./LogsView-kQy7qTGd.js`),__vite__mapDeps([14,1,2,3,4,5,6,7,8,15,13])).then(e=>({default:e.LogsView})));const qe=()=>{Ve.preload(),Ke.preload()},Je=()=>{We.preload(),Ue.preload(),He.preload()},Ye=({selectedProfile:e,prefilledRule:t,setPrefilledRule:n,handleQuickAction:r,toasterRef:i,currentUser:o,onSavingChange:s})=>{let{profileId:c}=ne(),l=c||e?.id||``;return(0,L.jsx)(I.Suspense,{fallback:(0,L.jsx)(`div`,{className:`p-20 flex justify-center`,children:(0,L.jsx)(M,{size:40})}),children:(0,L.jsxs)(f,{children:[(0,L.jsx)(a,{path:`setup`,element:(0,L.jsx)(Ve,{profileId:l,profileKey:e?.profile_key||l,profileName:e?.name,toasterRef:i})}),(0,L.jsx)(a,{path:`filter`,element:(0,L.jsx)(He,{profileId:l,toasterRef:i})}),(0,L.jsx)(a,{path:`rules`,element:(0,L.jsx)(Ue,{profileId:l,prefill:t,onPrefillUsed:()=>n(null),toasterRef:i})}),(0,L.jsx)(a,{path:`settings`,element:(0,L.jsx)(We,{profileId:l,toasterRef:i,currentUser:o,onSavingChange:s})}),(0,L.jsx)(a,{path:`stats`,element:(0,L.jsx)(Ge,{profileId:l})}),(0,L.jsx)(a,{path:`logs`,element:(0,L.jsx)(Ke,{profileId:l,onQuickAction:r,toasterRef:i})}),(0,L.jsx)(a,{path:`*`,element:(0,L.jsx)(Be,{})})]})})};var B=class extends Error{status;bodyText;constructor(e,t){super(t),this.status=e,this.bodyText=t,this.name=`ApiError`}};async function Xe(){let e=await fetch(`/api/auth/config`);if(!e.ok)throw new B(e.status,await e.text());return e.json()}async function Ze(e){let t=await fetch(`/api/auth/check-username?username=${encodeURIComponent(e)}`);if(!t.ok)throw new B(t.status,await t.text());return(await t.json()).exists}async function Qe(e){let t=await fetch(`/api/auth/prelogin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw new B(t.status,await t.text());return t.json()}async function $e(e){let t=await fetch(`/api/auth/login`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw new B(t.status,await t.text());return t.json()}async function et(e){let t=await fetch(`/api/auth/signup`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw new B(t.status,await t.text());return t.json()}async function tt(){let e=await fetch(`/api/auth/logout`,{method:`POST`});if(!e.ok)throw new B(e.status,await e.text())}async function nt(){let e=await fetch(`/api/auth/refresh`,{method:`POST`});if(!e.ok)throw new B(e.status,await e.text());return e.json()}async function rt(){let e=await fetch(`/api/auth/unlock-session`,{method:`GET`});if(!e.ok)throw new B(e.status,await e.text());return e.json()}async function V(e,t){let n=await fetch(`/api/auth/unlock-session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pinHash:e,nonce:t})});if(!n.ok)throw new B(n.status,await n.text())}async function H(){let e=await fetch(`/api/auth/lock-session`,{method:`POST`});if(!e.ok)throw new B(e.status,await e.text())}async function U(){let e=await fetch(`/api/account/me`);if(!e.ok)throw new B(e.status,await e.text());return e.json()}async function it(e){let t=await fetch(`/api/account/me`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw Error(await t.text());return t.json()}async function at(){let e=await fetch(`/api/account/me`,{method:`DELETE`});if(!e.ok)throw Error(await e.text())}async function ot(e){let t=await fetch(`/api/account/password`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw Error(await t.text())}async function st(){let e=await fetch(`/api/account/sessions`);if(!e.ok)throw Error(`Failed to fetch sessions`);return e.json()}async function ct(e){let t=await fetch(`/api/account/sessions/${e}`,{method:`DELETE`});if(!t.ok)throw Error(await t.text());return t.json()}async function lt(){let e=await fetch(`/api/account/sessions/others`,{method:`DELETE`});if(!e.ok)throw Error(await e.text());return e.json()}async function ut(e){let t=await fetch(`/api/account/activity?${e}`);if(!t.ok)throw Error(`Failed to fetch activity log`);return t.json()}async function dt(){let e=await fetch(`/api/account/logs`,{method:`DELETE`});if(!e.ok)throw Error(await e.text())}async function ft(){let e=await fetch(`/api/account/totp/setup`);if(!e.ok)throw Error(await e.text());return e.json()}async function pt(e){let t=await fetch(`/api/account/totp/confirm`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw Error(await t.text());return t.json()}async function mt(e){let t=await fetch(`/api/account/totp`,{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify({password:e})});if(!t.ok)throw Error(await t.text())}async function ht(e){let t=await fetch(`/api/account/totp/settings`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify({skip_password:e})});if(!t.ok)throw Error(await t.text())}const gt=ht;async function _t(e){let t=await fetch(`/api/account/migrate-password`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({clientHash:e})});if(!t.ok)throw Error(await t.text())}async function vt(e,t){let n=await fetch(`/api/account/pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pinHash:e,...t})});if(!n.ok)throw new B(n.status,await n.text())}async function yt(e){let t=await fetch(`/api/account/pin`,{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw new B(t.status,await t.text())}async function bt(){let e=await fetch(`/api/account/passkeys`);if(!e.ok)throw new B(e.status,await e.text());return e.json()}async function xt(){let e=await fetch(`/api/account/passkeys/register/options`,{method:`POST`});if(!e.ok)throw new B(e.status,await e.text());return e.json()}async function St(e){let t=await fetch(`/api/account/passkeys/register/verify`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw new B(t.status,await t.text());return t.json()}async function Ct(e,t){let n=await fetch(`/api/account/passkeys/${e}`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify({name:t})});if(!n.ok)throw new B(n.status,await n.text())}async function wt(e){let t=await fetch(`/api/account/passkeys/${e}`,{method:`DELETE`});if(!t.ok)throw new B(t.status,await t.text())}async function Tt(){let e=await fetch(`/api/account/passkeys/auth-options`,{method:`POST`});if(!e.ok)throw new B(e.status,await e.text());return e.json()}async function Et(e){let t=await fetch(`/api/account/recovery-keys/view`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw new B(t.status,await t.text());return t.json()}async function Dt(e){let t=await fetch(`/api/account/recovery-keys/rotate`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw new B(t.status,await t.text());return t.json()}async function W(e,t){let n=await fetch(e,t);return n.status===404&&(window.location.href=`/404`),n}async function Ot(){let e=await W(`/api/profiles`);if(!e.ok)throw Error(`Failed to fetch profiles`);return e.json()}async function kt(e){let t=await W(`/api/profiles/${e}`);if(!t.ok)throw Error(`Failed to fetch profile details`);return t.json()}async function At(e){let t=await W(`/api/profiles`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({name:e})});if(!t.ok)throw Error(await t.text());return t.json()}async function jt(e){let t=await W(`/api/profiles/${e}`,{method:`DELETE`});if(!t.ok)throw Error(await t.text())}async function Mt(e,t){let n=await W(`/api/profiles/${e}/settings`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok)throw Error(await n.text())}async function Nt(e){let t=await W(`/api/profiles/${e}/lists`);if(!t.ok)throw Error(`Failed to fetch lists`);return t.json()}async function Pt(e,t,n){let r=await W(`/api/profiles/${e}/lists/${t}/check?domain=${encodeURIComponent(n)}`);if(!r.ok)throw Error(await r.text());return r.json()}async function Ft(e,t,n){let r=await W(`/api/profiles/${e}/lists/${t}`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify({enabled:n})});if(!r.ok)throw Error(await r.text())}async function It(e,t){let n=await W(`/api/profiles/${e}/lists`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({url:t})});if(!n.ok)throw Error(await n.text())}async function Lt(e,t){let n=await W(`/api/profiles/${e}/lists`,{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:t})});if(!n.ok)throw Error(await n.text())}async function Rt(e){let t=await W(`/api/profiles/${e}/lists/sync`,{method:`POST`});if(!t.ok)throw Error(await t.text())}async function zt(e){let t=await W(`/api/profiles/${e}/rules`);if(!t.ok)throw Error(`Failed to fetch rules`);return t.json()}async function Bt(e,t){let n=await W(`/api/profiles/${e}/rules`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok)throw Error(await n.text())}async function Vt(e,t){let n=await W(`/api/profiles/${e}/rules`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok)throw Error(await n.text());return n.json()}async function Ht(e,t){let n=await W(`/api/profiles/${e}/lists`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok)throw Error(await n.text());return n.json()}async function Ut(e,t){let n=await W(`/api/profiles/${e}/rules`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok)throw Error(await n.text())}async function Wt(e,t){let n=await W(`/api/profiles/${e}/rules`,{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:t})});if(!n.ok)throw Error(await n.text())}async function Gt(e){let t=await W(`/api/profiles/${e}/access_points`);if(!t.ok)throw Error(`Failed to fetch access points`);return t.json()}async function Kt(e,t){let n=await W(`/api/profiles/${e}/access_points`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({name:t})});if(!n.ok)throw Error(await n.text());return n.json()}async function qt(e,t){let n=await W(`/api/profiles/${e}/access_points/${t}`,{method:`DELETE`});if(!n.ok)throw Error(await n.text())}async function Jt(e,t,n){let r=await W(`/api/profiles/${e}/access_points/${t}`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify({name:n})});if(!r.ok)throw Error(await r.text())}async function Yt(e,t){let n=await W(`/api/profiles/${e}/access_points/${t}/rotate_token`,{method:`POST`});if(!n.ok)throw Error(await n.text());return n.json()}async function Xt(e,t,n){let r=await W(`/api/profiles/${e}/logs?${t.startsWith(`?`)?t.slice(1):t}`,{signal:n?.signal});if(!r.ok)throw Error(`Failed to fetch logs`);return r.json()}async function Zt(e,t){let n=await W(`/api/profiles/${e}/logs/export?${t.startsWith(`?`)?t.slice(1):t}`);if(!n.ok)throw Error(`Failed to export logs`);return n.json()}async function Qt(e,t,n,r){let i=await W(`/api/profiles/${e}/logs/${t}${n===void 0?``:`?timestamp=${n}`}`,{signal:r?.signal});if(!i.ok)throw Error(`Failed to fetch log details`);return i.json()}async function $t(e,t,n,r){let i=await W(`/api/profiles/${e}/analytics/${t}?${n.startsWith(`?`)?n.slice(1):n}`,{signal:r?.signal});if(!i.ok)throw Error(`Failed to fetch analytics for ${t}`);return i.json()}async function en(e,t){let n=await W(`/api/profiles/${e}/test`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok)throw Error(`Resolution test failed`);return n.json()}async function tn(e,t){let n=await W(`/api/profiles/${e}`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify({name:t})});if(!n.ok)throw Error(await n.text())}async function nn(){let e=await fetch(`/api/clientinfo`);if(!e.ok)throw Error(`Failed to fetch client info`);return e.json()}async function rn(){let e=await fetch(`/api/regions`);if(!e.ok)throw Error(`Failed to fetch regions`);return e.json()}async function an(){let e=await fetch(`/api/substitute`);if(!e.ok)throw Error(`Failed to fetch substitute info`);return e.json()}async function on(){try{let e=await fetch(`/cdn-cgi/trace`);if(!e.ok)return null;let t=await e.text(),n=t.split(`
14
+ `),r={};for(let e of n){let t=e.indexOf(`=`);if(t!==-1){let n=e.slice(0,t).trim();r[n]=e.slice(t+1).trim()}}return{colo:r.colo||`UNKNOWN`,raw:t}}catch(e){return console.warn(`Failed to fetch /cdn-cgi/trace:`,e),null}}async function sn(){let e=await fetch(`/world-110m.json`);if(!e.ok)throw Error(`Failed to load map topology`);return e.json()}async function cn(e,t,n){let r=await fetch(`https://${e}/dns-query?name=${encodeURIComponent(t)}&type=${n}`,{headers:{Accept:`application/dns-json`}});if(!r.ok)throw Error(`DoH query failed: ${r.statusText}`);return r.json()}async function ln(){let e=await fetch(`/api/presets/upstreams`);if(!e.ok)throw Error(`Failed to fetch preset upstreams`);return e.json()}async function un(){let e=await fetch(`/api/presets/filters`);if(!e.ok)throw Error(`Failed to fetch preset filters`);return e.json()}async function dn(){let e=await fetch(`/api/presets/ech-fronting-domains`);if(!e.ok)throw Error(`Failed to fetch preset ECH fronting domains`);return e.json()}async function fn(){let e=await fetch(`/api/admin/users`);if(!e.ok)throw Error(`Failed to fetch users`);return e.json()}async function pn(e){let t=await fetch(`/api/admin/users`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw Error(await t.text())}async function mn(e){let t=await fetch(`/api/admin/users/${e}`,{method:`DELETE`});if(!t.ok)throw Error(await t.text())}async function hn(){let e=await fetch(`/api/admin/settings`);if(!e.ok)throw Error(`Failed to fetch system settings`);return e.json()}async function gn(e){let t=await fetch(`/api/admin/settings`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw Error(await t.text())}const _n=e=>{let{t}=b(),n=(0,I.useRef)(null),[r,i]=(0,I.useState)(!1);return{fileInputRef:n,importing:r,handleImportClick:()=>n.current?.click(),handleFileChange:async r=>{let a=r.target.files?.[0];if(!a)return;i(!0);let o=null;try{let n=await a.text(),r;try{r=JSON.parse(n)}catch{alert(t(`common.invalidFormat`,`无效文件格式`));return}if(!r||typeof r!=`object`||!r.settings||!r.name){alert(t(`common.invalidFormat`,`无效文件格式`));return}let i=typeof r.version==`number`?r.version:1;i>2&&console.warn(`[ProfileImport] File version (${i}) is newer than supported version (2). Proceeding with backward-compatible import.`);let s=await Ot().catch(()=>[]),c=new Set(s.map(e=>e.name.trim().toLowerCase())),l=String(r.name).trim();l=l.replace(/[^\p{L}\p{N}_ ()-]/gu,``).trim()||`Imported`;let u=new Date,d=`${String(u.getMonth()+1).padStart(2,`0`)}-${String(u.getDate()).padStart(2,`0`)}`,f=` (${d})`,p=`${l.slice(0,Math.max(1,30-f.length)).trim()}${f}`,m=1;for(;c.has(p.toLowerCase())&&m<100;){let e=` (${d}-${m})`;p=`${l.slice(0,Math.max(1,30-e.length)).trim()}${e}`,m++}if(o=(await At(p)).id,await Mt(o,r.settings),r.rules&&Array.isArray(r.rules)&&r.rules.length>0){let e=new Set,t=[];for(let n of r.rules)if(n&&typeof n.pattern==`string`&&(n.type===`ALLOW`||n.type===`BLOCK`||n.type===`REDIRECT`)){let r=n.pattern.trim().toLowerCase();if(!r||e.has(r))continue;e.add(r),t.push({type:n.type,pattern:n.pattern.trim(),v_a:n.v_a||void 0,v_aaaa:n.v_aaaa||void 0,v_cname:n.v_cname||void 0,v_txt:n.v_txt||void 0,created_at:typeof n.created_at==`number`?n.created_at:void 0})}if(t.length>0)try{await Vt(o,t)}catch(e){console.warn(`[ProfileImport] Bulk rules failed, falling back to sequential:`,e);for(let e of t)try{await Bt(o,e)}catch(e){if(!(e instanceof Error?e.message:String(e)).includes(`Rule for this domain already exists`))throw e}}}let h=e=>{if(!e||typeof e!=`object`)return[];let t=e.filters??e.filter??e.lists??e.list??e.blocklists??e.blocklist??e.subscriptions??e.subscription??e.external_filters??e.settings?.filters??e.settings?.filter??e.settings?.lists??e.settings?.list??e.settings?.blocklists??e.settings?.blocklist;if(!t)return[];if(Array.isArray(t))return t;if(typeof t==`string`)return[t];if(typeof t==`object`){let e=[];for(let[n,r]of Object.entries(t))typeof r==`string`?e.push(r):typeof r==`boolean`||typeof r==`number`?e.push({url:n,enabled:!!r}):r&&typeof r==`object`&&e.push(r);return e}return[]},g=e=>{if(!e)return null;let t=``,n=!0;if(typeof e==`string`)t=e.trim();else if(typeof e==`object`){let r=e;if(r.enabled!==void 0&&(n=!!r.enabled),typeof r.url==`string`)t=r.url.trim();else if(typeof r.link==`string`)t=r.link.trim();else if(typeof r.uri==`string`)t=r.uri.trim();else if(typeof r.address==`string`)t=r.address.trim();else if(typeof r.source==`string`)t=r.source.trim();else if(typeof r.target==`string`)t=r.target.trim();else if(typeof r.download_url==`string`)t=r.download_url.trim();else for(let e of Object.values(r))if(typeof e==`string`&&(e.startsWith(`http://`)||e.startsWith(`https://`)||e.startsWith(`//`))){t=e.trim();break}}if(t=t.replace(/^["']|["']$/g,``).trim(),t.startsWith(`//`))t=`https:${t}`;else if(!t.startsWith(`http://`)&&!t.startsWith(`https://`))if(t.includes(`.`)&&!t.includes(` `)&&t.length>3)t=`https://${t}`;else return null;return{url:t,enabled:n}},_=h(r);if(_.length>0){let e=new Set,t=[];for(let n of _){let r=g(n);if(!r)continue;let i=r.url.toLowerCase();e.has(i)||(e.add(i),t.push(r))}if(t.length>0)try{await Ht(o,t)}catch(e){console.warn(`[ProfileImport] Bulk filter import failed, falling back to sequential:`,e);for(let e of t)try{await It(o,e.url)}catch(t){console.warn(`[ProfileImport] Failed to sequentially import filter:`,e.url,t)}}}alert(t(`common.importSuccess`,`配置成功导入`)),e?.()}catch(e){console.error(`[ProfileImport]`,e),o&&await jt(o).catch(()=>{});let n=e?.message||String(e||``);if(n.startsWith(`Profile limit exceeded`)){let e=n.match(/\(max (\d+)\)/),r=e?e[1]:`10`;alert(t(`common.profileLimitExceeded`,{max:r,defaultValue:`Profile limit exceeded (max ${r})`}))}else n===`The profile name already exists`?alert(t(`common.profileNameExists`,`该配置名称已存在`)):n===`Invalid Profile Name format`?alert(t(`common.profileNameFormatError`,`配置名称格式不正确`)):alert(n?`${t(`common.importError`,`配置导入失败`)}: ${n}`:t(`common.importError`,`配置导入失败`))}finally{i(!1),r.target&&(r.target.value=``),n.current&&(n.current.value=``)}}}};var G=new Map,vn=void 0,yn=typeof navigator<`u`?navigator.language:`en-US`;function bn(e){vn=e||void 0,G.clear()}function xn(e){yn=e||(typeof navigator<`u`?navigator.language:`en-US`),G.clear()}function Sn(e,t){let n=`${e||``}:${t?JSON.stringify(t):``}`,r=G.get(n);return r||(r=new Intl.DateTimeFormat(e,t),G.set(n,r)),r}function Cn(e,t){let n={timeZone:vn,timeZoneName:`short`,...t||{year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`}};return Sn(yn,n).format(e)}async function wn(e){let t=e||`en-US`,n=await Le(t);Re.changeLanguage(t),xn(t);try{return await it({locale:t}),{loaded:n,persisted:!0}}catch(e){return console.error(`Failed to persist locale to server:`,e),{loaded:n,persisted:!1}}}const Tn=[{label:`English`,value:`en-US`,flag:`🇺🇸`},{label:`English`,value:`en-GB`,flag:`🇬🇧`},{label:`English`,value:`en-SG`,flag:`🇸🇬`},{label:`中文 (简体)`,value:`zh-CN`,flag:`🇨🇳`},{label:`中文 (简体)`,value:`zh-SG`,flag:`🇸🇬`},{label:`中文 (正體)`,value:`zh-TW`,flag:`🇹🇼`},{label:`中文 (繁體)`,value:`zh-HK`,flag:`🇭🇰`},{label:`日本語`,value:`ja-JP`,flag:`🇯🇵`},{label:`한국어`,value:`ko-KR`,flag:`🇰🇷`},{label:`Tiếng Việt`,value:`vi-VN`,flag:`🇻🇳`},{label:`Español`,value:`es-ES`,flag:`🇪🇸`},{label:`Русский`,value:`ru-RU`,flag:`🇷🇺`},{label:`Français`,value:`fr-FR`,flag:`🇫🇷`},{label:`Deutsch`,value:`de-DE`,flag:`🇩🇪`}],K=({minimal:e=!0,size:t=`small`})=>{let{i18n:n}=b(),[r,i]=(0,I.useState)(null),a=Tn.find(e=>e.value===n.language)||Tn[0],o=async e=>{if(!(e===n.language||r!==null)){i(e);try{await wn(e)}finally{i(null)}}},s=r!==null;return(0,L.jsx)(xe,{placement:`bottom-start`,disabled:s,content:(0,L.jsx)(_e,{style:{maxHeight:`300px`,overflowY:`auto`},children:Tn.map(e=>(0,L.jsx)(P,{text:e.label+` [`+e.flag+`]`,active:n.language===e.value,disabled:s,labelElement:r===e.value?(0,L.jsx)(M,{size:12}):void 0,onClick:()=>o(e.value)},e.value))}),children:(0,L.jsxs)(j,{variant:e?`minimal`:void 0,size:t,icon:s?(0,L.jsx)(M,{size:14}):(0,L.jsx)(D,{size:14}),children:[(0,L.jsx)(`span`,{className:`hidden sm:inline ml-1`,children:a.label}),(0,L.jsx)(`span`,{className:`inline sm:hidden ml-1`,children:a.flag})]})})},En=({currentUser:e,minimal:t=!0,size:n=`small`})=>{let{t:r}=b(),[i,a]=(0,I.useState)(!1);return e?.pin_enabled?(0,L.jsx)(j,{variant:t?`minimal`:void 0,size:n,icon:i?(0,L.jsx)(M,{size:14}):(0,L.jsx)(S,{size:14}),onClick:async()=>{if(!i){a(!0);try{await H()}catch(e){console.warn(`Failed to lock session on server`,e)}finally{sessionStorage.setItem(`obex_session_locked`,`true`),window.dispatchEvent(new Event(`session_paused`)),a(!1)}}},disabled:i,title:r(`auth.lockNow`,`Lock Now`),"aria-label":r(`auth.lockNow`,`Lock Now`)}):null};var q=`/assets/obex_cat_eye_logo-256-CgYNvUIC.webp`;const Dn=({isMobile:e,navigate:t,handleLogout:n,currentUser:r})=>{let{t:i}=b(),a=typeof window<`u`?window.location.host||window.location.hostname:``;return(0,L.jsxs)(`div`,{className:`sticky top-0 z-30 h-14 border-b border-gray-200/50 dark:border-gray-800/50 bg-white/70 dark:bg-gray-900/70 backdrop-blur-lg flex items-center justify-between px-4 md:px-6 shrink-0`,style:{transform:`translateZ(0)`},children:[(0,L.jsxs)(`div`,{className:`flex items-center gap-2.5`,children:[(0,L.jsx)(`img`,{src:q,alt:`DNS Worker`,className:`w-8 h-8 object-contain shrink-0`}),(0,L.jsxs)(`div`,{className:`flex flex-col justify-center`,children:[(0,L.jsx)(`span`,{className:`font-bold text-base leading-tight tracking-tight dark:text-white`,children:`DNS Worker`}),a&&(0,L.jsx)(`span`,{className:`text-xs text-gray-500 dark:text-gray-400 font-mono leading-tight mt-0.5 select-all`,title:a,children:a})]})]}),(0,L.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,L.jsx)(En,{currentUser:r}),(0,L.jsx)(K,{}),(0,L.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,L.jsx)(j,{variant:`minimal`,icon:(0,L.jsx)(w,{size:18}),text:e?``:i(`common.account`),onClick:()=>t(`/account`)}),(0,L.jsx)(xe,{content:(0,L.jsxs)(`div`,{className:`p-4 space-y-3`,children:[(0,L.jsx)(`div`,{className:`font-bold text-sm`,children:i(`common.confirmLogout`)}),(0,L.jsx)(j,{fill:!0,intent:N.DANGER,text:i(`common.logout`),onClick:n})]}),children:(0,L.jsx)(j,{variant:`minimal`,intent:N.DANGER,icon:(0,L.jsx)(x,{size:18}),text:e?``:i(`common.logout`)})})]})]})]})},On=/^[a-z_][a-z0-9_-]{4,31}$/,kn=/^[a-zA-Z\d~`!@#$%^&*()_\-+={[}\]|\\:;"'<,>.?\/]{12,100}$/,An=/^[\p{L}\p{N}_ ()-]{1,30}$/u,jn=/^[a-zA-Z0-9_-]{1,30}$/,Mn=/^[a-zA-Z0-9_-]{1,30}$/,Nn=/^\d{4}$/;function Pn(e){return Mn.test(e)}function Fn(e){return On.test(e)}function In(e){return kn.test(e)}function Ln(e,t){return!!(t===`password_leaked`||e.status===403&&(t.includes(`password_leaked`)||t.includes(`password breached`)))}function Rn(e){if(!e||typeof e!=`string`)return null;let t=e.trim(),n=t.startsWith(`<!DOCTYPE`)||t.startsWith(`<html`)||/<[a-z][\s\S]*>/i.test(t),r=t.includes(`cf-error-details`)||t.includes(`cf-wrapper`)||t.includes(`cf.errors.css`)||t.includes(`Cloudflare Ray ID`)||/Worker threw exception/i.test(t);if(!n&&!r)return null;let i=t.match(/class=["']cf-error-code["'][^>]*>([^<]+)</i)||t.match(/Error\s+([0-9]{3,4})/i),a=i?i[1].trim():null,o=t.match(/data-translate=["']error_desc["'][^>]*>([^<]+)</i)||t.match(/class=["']cf-subheadline["'][^>]*>([^<]+)</i)||t.match(/<title>([^<|]+)/i),s=o?o[1].trim():null,c=t.match(/Ray ID:\s*<strong[^>]*>([a-f0-9]+)<\/strong>/i)||t.match(/Ray ID:\s*([a-f0-9]+)/i)||t.match(/Cloudflare Ray ID:\s*<strong[^>]*>([a-f0-9]+)<\/strong>/i);return{isCf:r,isHtml:n,errorCode:a,errorDesc:s,rayId:c?c[1].trim():null}}function zn(e,t){if(!e)return t(`auth.authFailed`,`Authentication failed`);let n=typeof e==`string`?e:e.bodyText||e.message||``,r=Rn(n);if(r){let n=r.rayId?` (Ray ID: ${r.rayId})`:``;return r.errorCode&&r.errorDesc?t(`auth.cfErrorWithDetails`,{defaultValue:`Cloudflare 边缘节点异常 (错误代码 ${r.errorCode}: ${r.errorDesc})。服务暂时不可用,请稍后重试。${n}`,code:r.errorCode,desc:r.errorDesc,rayId:n}):r.errorCode?t(`auth.cfErrorCodeOnly`,{defaultValue:`Cloudflare 边缘服务异常 (错误代码 ${r.errorCode})。服务暂时不可用,请稍后重试。${n}`,code:r.errorCode,rayId:n}):r.isCf?t(`auth.cfErrorGeneric`,{defaultValue:`Cloudflare 边缘服务异常,服务暂时不可用,请稍后重试。${n}`,rayId:n}):t(`auth.htmlErrorGeneric`,{defaultValue:`服务器返回异常网页响应 (HTTP ${e.status||500}),请稍后重试。`,status:e.status||500})}return e?.status===429||n.toLowerCase().includes(`too many`)||n===`rate_limited`?t(`auth.tooManyAttempts`,{defaultValue:`请求过于频繁或尝试次数过多,已被临时限制,请稍后再试。`}):n.includes(`row read limit`)||n.includes(`exceeded D1`)||n===`database_unavailable`?t(`auth.dbQuotaExceeded`,{defaultValue:`数据库每日免费读取配额已用尽,请等待次日自动重置或升级配额。`}):n===`no_users_registered`||n.includes(`no_users_registered`)?t(`auth.noUsersRegistered`,`系统尚无账号,请注册成为管理员。`):n.includes(`no such table`)||n.includes(`SQLITE_ERROR`)?t(`auth.dbNotInitialized`,{defaultValue:`数据库未初始化或缺少数据表,请在终端执行 'npm run db:migrate:prod' 应用数据库迁移。`}):n===`invalid_credentials`||n===`user_not_found`?t(`auth.authFailed`,`Authentication failed, please check your username or password.`):n===`invalid_totp`?t(`auth.invalidTotp`,`Invalid TOTP verification code.`):n===`invalid_turnstile`||n===`turnstile_failed`?t(`auth.turnstileRequired`,`Please complete Turnstile verification.`):n===`geolocation_missing`?t(`auth.geolocationRequired`,`Geolocation retrieval failed, please re-enter.`):n===`username_exists`?t(`auth.usernameExists`,`Username already exists.`):n===`password_leaked`?t(`auth.passwordLeaked`,`Your password has been leaked.`):n===`jwt_secret_preset`||n.includes(`jwt_secret_preset`)||n.includes(`is a documentation placeholder`)?t(`auth.jwtSecretPreset`,`检测到正在使用预设的 JWT_SECRET,请在环境变量中修改并替换为自定义安全密钥后重新部署。`):n===`jwt_secret_missing`||n.includes(`jwt_secret_missing`)||n.includes(`JWT_SECRET is missing`)?t(`auth.jwtSecretMissing`,`缺少 JWT_SECRET,请在环境变量中配置安全密钥后重新部署。`):n===`jwt_secret_invalid`?t(`auth.jwtSecretInvalid`,`JWT_SECRET 密钥格式无效,请检查配置。`):n&&n.length<200&&!n.includes(`<`)&&!n.includes(`>`)?n:t(`auth.authFailed`,`Authentication failed, please check your username or password.`)}function Bn(e){if(window.turnstile){e();return}if(window.onloadTurnstileCallback=e,!document.querySelector(`script[src*="turnstile/v0/api.js"]`)){let e=document.createElement(`script`);e.src=`https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=onloadTurnstileCallback`,e.async=!0,e.defer=!0;let t=window.DNS_WORKER_CONFIG?.nonce;t&&(e.nonce=t),document.head.appendChild(e)}}async function Vn(e,t){let n=new TextEncoder().encode(e+t),r=await crypto.subtle.digest(`SHA-256`,n);return Array.from(new Uint8Array(r)).map(e=>e.toString(16).padStart(2,`0`)).join(``)}async function Hn(e,t,n=6e5){let r=new TextEncoder,i=r.encode(e),a=r.encode(t.toLowerCase()),o=await crypto.subtle.importKey(`raw`,i,`PBKDF2`,!1,[`deriveBits`,`deriveKey`]),s=await crypto.subtle.deriveBits({name:`PBKDF2`,salt:a,iterations:n,hash:`SHA-256`},o,256);return Array.from(new Uint8Array(s)).map(e=>e.toString(16).padStart(2,`0`)).join(``)}function Un(e){let t=new Uint8Array(e.length/2);for(let n=0;n<t.length;n++)t[n]=parseInt(e.substring(n*2,n*2+2),16);return t}async function Wn(e,t){let n=new TextEncoder().encode(e),r=Un(t),i=await crypto.subtle.importKey(`raw`,n,`PBKDF2`,!1,[`deriveBits`,`deriveKey`]),a=await crypto.subtle.deriveBits({name:`PBKDF2`,salt:r,iterations:1e5,hash:`SHA-256`},i,256),o=new Uint8Array(r.length+a.byteLength);return o.set(r),o.set(new Uint8Array(a),r.length),btoa(String.fromCharCode(...o))}async function Gn(e,t){let n=new TextEncoder,r=n.encode(e),i=n.encode(t),a=await crypto.subtle.importKey(`raw`,r,{name:`HMAC`,hash:`SHA-256`},!1,[`sign`]),o=await crypto.subtle.sign(`HMAC`,a,i);return Array.from(new Uint8Array(o)).map(e=>e.toString(16).padStart(2,`0`)).join(``)}async function Kn(e,t){return Hn(e,t)}async function qn(e,t){return Hn(e,t,1e4)}function Jn(e){return/^\d{6}$/.test(e.trim())?parseInt(e.trim(),10)%11==0:!1}const Yn=({newName:e,setNewName:t,onCreate:n,setShowCreate:r,error:i})=>{let{t:a}=b(),[o,s]=(0,I.useState)(!1);return(0,L.jsxs)(F,{elevation:A.TWO,className:`mb-6 p-4 dark:bg-gray-900 dark:border-gray-800 rounded-xl`,children:[(0,L.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,L.jsx)(je,{content:a(`common.profileNameFormatTip`,`Profile Name tip: 1-30 characters, duplicates not allowed`),isOpen:o,position:ge.TOP,intent:N.PRIMARY,className:`flex-1`,children:(0,L.jsx)(`div`,{className:`w-full block`,children:(0,L.jsx)(we,{fill:!0,placeholder:a(`common.newProfileName`),value:e,onChange:e=>t(e.target.value),onFocus:()=>s(!0),onBlur:()=>s(!1),autoFocus:!0})})}),(0,L.jsx)(j,{intent:N.SUCCESS,onClick:n,text:a(`common.create`),className:`whitespace-nowrap`,disabled:!An.test(e)}),(0,L.jsx)(j,{variant:`minimal`,onClick:()=>r(!1),icon:`cross`})]}),i&&(0,L.jsx)(`div`,{className:`mt-2 text-red-500 text-xs`,children:(e=>{if(!e)return``;if(e.startsWith(`Profile limit exceeded`)){let t=e.match(/\(max (\d+)\)/),n=t?t[1]:`10`;return a(`common.profileLimitExceeded`,{max:n,defaultValue:`Profile limit exceeded (max ${n})`})}return e===`The profile name already exists`?a(`common.profileNameExists`,`The profile name already exists`):e===`Invalid Profile Name format`?a(`common.profileNameFormatError`,`Invalid Profile Name format`):e})(i)})]})},Xn=({profiles:e,onSelect:t,onDelete:r})=>{let{t:a}=b();return(0,L.jsxs)(`div`,{className:`grid gap-3`,children:[e.map(e=>(0,L.jsxs)(F,{interactive:!0,onClick:()=>t(e),className:`flex justify-between items-center p-4 dark:bg-gray-900 dark:border-gray-800 rounded-xl border border-gray-200`,children:[(0,L.jsxs)(`div`,{className:`flex flex-col`,children:[(0,L.jsx)(`span`,{className:`font-bold text-base dark:text-white`,children:e.name}),(0,L.jsx)(`code`,{className:`text-gray-400 text-[10px] font-mono uppercase mt-0.5`,children:e.id})]}),(0,L.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,L.jsx)(j,{variant:`minimal`,intent:N.DANGER,icon:(0,L.jsx)(i,{size:16}),onClick:t=>{t.stopPropagation(),r(t,e.id)}}),(0,L.jsx)(ee,{size:18,className:`text-gray-300`})]})]},e.id)),e.length===0&&(0,L.jsx)(ke,{icon:(0,L.jsx)(n,{size:48,className:`text-gray-300`}),title:a(`common.welcome`),description:a(`common.createProfileToStart`)})]})},Zn=({profiles:e,onSelect:t,onCreate:n,showCreate:r,setShowCreate:i,newName:a,setNewName:o,error:s,onDelete:c,handleLogout:l,navigate:u,onRefresh:d,currentUser:f})=>{let p=z(),{t:m}=b(),{fileInputRef:h,importing:g,handleImportClick:_,handleFileChange:v}=_n(d);return(0,I.useEffect)(()=>{qe();let e=setTimeout(Je,2e3);return()=>clearTimeout(e)},[]),(0,L.jsxs)(`div`,{className:`min-h-screen bg-gray-50 dark:bg-gray-950 flex flex-col`,children:[(0,L.jsx)(`input`,{type:`file`,ref:h,className:`hidden`,accept:`.json`,onChange:v}),(0,L.jsx)(Dn,{isMobile:p,navigate:u,handleLogout:l,currentUser:f}),(0,L.jsx)(`div`,{className:`flex-1 flex flex-col items-center justify-start md:justify-center p-4 pt-8 md:pt-4`,children:(0,L.jsxs)(`div`,{className:`w-full max-w-md`,children:[(0,L.jsxs)(`div`,{className:`flex justify-between items-center mb-6`,children:[(0,L.jsx)(he,{className:`dark:text-white font-bold`,style:{marginBottom:0},children:m(`common.selectProfile`)}),(0,L.jsxs)(`div`,{className:`flex gap-1`,children:[(0,L.jsx)(j,{variant:`minimal`,icon:(0,L.jsx)(E,{size:16}),onClick:_,text:p?``:m(`common.import`,`导入`),loading:g}),(0,L.jsx)(j,{variant:`minimal`,intent:N.PRIMARY,icon:(0,L.jsx)(ue,{size:18}),onClick:()=>i(!0),text:m(`common.add`),disabled:r})]})]}),r&&(0,L.jsx)(Yn,{newName:a,setNewName:o,onCreate:n,setShowCreate:i,error:s}),(0,L.jsx)(Xn,{profiles:e,onSelect:t,onDelete:c})]})})]})},Qn=({isSidebarOpen:e,setIsSidebarOpen:t,isProfileActive:n,activeId:r,location:i,navigate:a,handleLogout:o,currentUser:s,navItems:c})=>{let{t:l}=b();return(0,L.jsxs)(`aside`,{className:Me(`flex flex-col border-r border-gray-200 dark:border-gray-800 transition-all duration-300 bg-white dark:bg-gray-900`,e?`w-64`:`w-16`),children:[(0,L.jsxs)(`div`,{className:`h-14 flex items-center px-4 shrink-0`,children:[(0,L.jsx)(`img`,{src:q,alt:`DNS Worker`,className:`w-8 h-8 object-contain shrink-0`}),e&&(0,L.jsxs)(`div`,{className:`ml-3 flex flex-col justify-center min-w-0`,children:[(0,L.jsx)(`span`,{className:`font-bold text-base leading-tight dark:text-white truncate`,children:`DNS Worker`}),(0,L.jsx)(`span`,{className:`text-xs text-gray-500 dark:text-gray-400 font-mono leading-tight mt-0.5 truncate select-all`,title:typeof window<`u`?window.location.host||window.location.hostname:``,children:typeof window<`u`?window.location.host||window.location.hostname:``})]})]}),(0,L.jsx)(`div`,{className:`flex-1 py-4 px-2 overflow-y-auto overflow-x-hidden`,children:(0,L.jsxs)(_e,{className:`bg-transparent p-0`,children:[c.map(t=>(0,L.jsx)(P,{icon:t.icon,text:e?t.label:``,disabled:!n,active:i.pathname.endsWith(t.id===`stats`?`/stats`:`/${t.id}`),onClick:()=>a(t.path)},t.id)),(0,L.jsx)(P,{icon:(0,L.jsx)(p,{size:18}),text:e?l(`nav.filter`):``,disabled:!n,active:i.pathname.endsWith(`/filter`),onClick:()=>a(`/dash/${r}/filter`)}),(0,L.jsx)(P,{icon:(0,L.jsx)(u,{size:18}),text:e?l(`nav.settings`):``,disabled:!n,active:i.pathname.endsWith(`/settings`),onClick:()=>a(`/dash/${r}/settings`)}),(0,L.jsx)(`li`,{className:`my-4 border-t border-gray-100 dark:border-gray-800`}),(0,L.jsx)(P,{icon:(0,L.jsx)(w,{size:18}),text:e?l(`common.account`):``,active:i.pathname===`/account`,onClick:()=>a(`/account`)}),(0,L.jsx)(xe,{className:`w-full`,placement:`right-end`,content:(0,L.jsxs)(`div`,{className:`p-4 space-y-3`,children:[(0,L.jsx)(`div`,{className:`font-bold text-sm`,children:l(`common.confirmLogout`)}),(0,L.jsx)(j,{fill:!0,intent:N.DANGER,text:l(`common.logout`),onClick:o})]}),children:(0,L.jsx)(P,{icon:(0,L.jsx)(x,{size:18}),text:e?l(`common.logout`):``,intent:N.DANGER,shouldDismissPopover:!1})})]})}),(0,L.jsxs)(`div`,{className:`p-4 border-t border-gray-100 dark:border-gray-800 flex items-center justify-between`,children:[(0,L.jsx)(j,{variant:`minimal`,icon:(0,L.jsx)(ae,{size:18}),onClick:()=>t(!e)}),e&&(0,L.jsx)(Oe,{minimal:!0,round:!0,children:s?.username.toUpperCase()||`USER`})]})]})},$n=({theme:e,setTheme:t,selectedProfile:n,isProfileActive:r,location:i,navigate:a,isSaving:o,currentUser:c})=>{let{t:l}=b();return(0,L.jsxs)(Ce,{className:`absolute! top-0 left-0 right-0 border-b! border-gray-200/50 dark:border-gray-800/50 shadow-none! bg-white/70! dark:bg-gray-900/70! backdrop-blur-lg! h-14 items-center px-4 shrink-0`,style:{zIndex:10,transform:`translateZ(0)`,willChange:`transform`},children:[(0,L.jsxs)(Ce.Group,{align:Se.LEFT,children:[(0,L.jsxs)(`button`,{onClick:()=>a(`/dash`),className:`font-bold text-blue-600 dark:text-blue-400 bg-transparent border-none p-0 cursor-pointer flex items-center gap-1`,children:[(0,L.jsx)(ve,{icon:`caret-left`}),(0,L.jsx)(`span`,{className:`truncate max-w-30 md:max-w-none`,children:i.pathname===`/account`?l(`common.account`):r?n?.name||l(`common.loading`):l(`common.selectProfile`)})]}),r&&i.pathname!==`/account`&&(0,L.jsx)(`button`,{onClick:()=>{let e=n?.id||i.pathname.split(`/`)[2];e&&a(`/dash/${e}/settings`)},className:Ne(`md:hidden ml-2 hover:text-gray-700 dark:hover:text-gray-200 bg-transparent border-none p-1 cursor-pointer flex items-center transition-colors`,i.pathname.includes(`/settings`)?`text-blue-500 dark:text-blue-400`:`text-gray-500 dark:text-gray-400`),title:l(`nav.settings`),children:(0,L.jsx)(u,{size:18})})]}),(0,L.jsx)(Ce.Group,{align:Se.RIGHT,children:(0,L.jsxs)(`div`,{className:`flex items-center gap-2`,children:[o&&(0,L.jsxs)(`div`,{className:`flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium text-blue-600 dark:text-blue-400 bg-blue-50/80 dark:bg-blue-950/50 border border-blue-200/50 dark:border-blue-800/50 rounded-full animate-pulse mr-1`,children:[(0,L.jsx)(M,{size:12}),(0,L.jsx)(`span`,{children:l(`settings.saving`)})]}),(0,L.jsx)(En,{currentUser:c}),(0,L.jsx)(K,{}),(0,L.jsxs)(`div`,{className:`flex items-center gap-1 bg-gray-100/50 dark:bg-gray-800/50 p-1 rounded-lg`,children:[(0,L.jsx)(j,{variant:`minimal`,icon:(0,L.jsx)(g,{size:14}),size:`small`,active:e===`light`,onClick:()=>t(`light`)}),(0,L.jsx)(j,{variant:`minimal`,icon:(0,L.jsx)(y,{size:14}),size:`small`,active:e===`dark`,onClick:()=>t(`dark`)}),(0,L.jsx)(j,{variant:`minimal`,icon:(0,L.jsx)(s,{size:14}),size:`small`,active:e===`system`,onClick:()=>t(`system`)})]})]})})]})},er=({isProfileActive:e,navItems:t,location:n,navigate:r})=>{let{t:i}=b();return e?(0,L.jsxs)(`div`,{className:`fixed bottom-0 left-0 right-0 h-16 bg-white/80 dark:bg-gray-900/80 backdrop-blur-xl border-t border-gray-200/50 dark:border-gray-800/50 flex items-center justify-around px-2 z-50 pb-safe`,children:[t.map(e=>(0,L.jsxs)(`button`,{onClick:()=>r(e.path),className:Me(`flex flex-col items-center justify-center gap-1 w-16 h-full transition-colors`,(e.id===`rules`?n.pathname.includes(`/rules`)||n.pathname.includes(`/filter`):n.pathname.includes(e.id===`stats`?`/stats`:`/${e.id}`))?`text-blue-500`:`text-gray-400`),children:[e.icon,(0,L.jsx)(`span`,{className:`text-[10px] font-medium`,children:e.label})]},e.id)),(0,L.jsxs)(`button`,{onClick:()=>r(`/account`),className:Me(`flex flex-col items-center justify-center gap-1 w-16 h-full transition-colors`,n.pathname===`/account`?`text-blue-500`:`text-gray-400`),children:[(0,L.jsx)(w,{size:20}),(0,L.jsx)(`span`,{className:`text-[10px] font-medium`,children:i(`common.account`)})]})]}):null},tr=({children:e,isSidebarOpen:t,setIsSidebarOpen:n,theme:r,setTheme:i,selectedProfile:a,profiles:o,setSelectedProfile:s,location:c,navigate:l,handleLogout:u,currentUser:d,isSaving:f})=>{let{profileId:m}=ne(),h=z(),{t:g}=b(),_=m||a?.id,y=!!_;(0,I.useEffect)(()=>{if(m&&o.length>0&&a?.id!==m){let e=o.find(e=>e.id===m);e&&s(e)}},[m,o,a,s]);let x=[{id:`setup`,label:g(`nav.setup`),icon:(0,L.jsx)(E,{size:20}),path:`/dash/${_}/setup`},{id:`rules`,label:h&&c.pathname.includes(`/filter`)?g(`nav.filter`):g(`nav.rules`),icon:h&&c.pathname.includes(`/filter`)?(0,L.jsx)(p,{size:20}):(0,L.jsx)(v,{size:20}),path:h&&c.pathname.includes(`/filter`)?`/dash/${_}/filter`:`/dash/${_}/rules`},{id:`stats`,label:g(`nav.stats`),icon:(0,L.jsx)(te,{size:20}),path:`/dash/${_}/stats`},{id:`logs`,label:g(`nav.logs`),icon:(0,L.jsx)(se,{size:20}),path:`/dash/${_}/logs`}];return(0,L.jsxs)(`div`,{className:`flex h-screen w-full bg-white dark:bg-gray-950 overflow-hidden flex-col md:flex-row`,children:[!h&&(0,L.jsx)(Qn,{isSidebarOpen:t,setIsSidebarOpen:n,isProfileActive:y,activeId:_,location:c,navigate:l,handleLogout:u,currentUser:d,navItems:x}),(0,L.jsxs)(`main`,{className:`flex-1 min-w-0 h-full relative bg-gray-50/20 dark:bg-gray-950/20 flex flex-col overflow-hidden`,children:[(0,L.jsx)($n,{theme:r,setTheme:i,selectedProfile:a,isProfileActive:y,location:c,navigate:l,isSaving:f,currentUser:d}),(0,L.jsx)(`div`,{className:`flex-1 min-h-0 flex flex-col relative z-0 isolate`,style:{isolation:`isolate`},children:c.pathname.endsWith(`/logs`)?(0,L.jsx)(`div`,{className:`flex-1 overflow-y-auto`,children:e}):(0,L.jsx)(`div`,{className:`flex-1 overflow-y-auto pt-14`,children:(0,L.jsx)(`div`,{className:`p-2 md:p-4 pb-24 md:pb-8`,children:e})})}),h&&(0,L.jsx)(er,{isProfileActive:y,navItems:x,location:c,navigate:l})]})]})};function nr(){let[e,t]=(0,I.useState)(`dark`);return(0,I.useEffect)(()=>{let t=window.document.documentElement;(e=>{t.classList.remove(`light`,`dark`,`bp6-dark`),t.classList.add(e),e===`dark`&&t.classList.add(`bp6-dark`)})(e===`system`?window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`:e)},[e]),{theme:e,setTheme:t}}function rr(){let{t:e}=b();return(t=>{let n=``,r=e(`meta.defaultDesc`,`Secure, fast, and customizable DNS resolution for all your devices. Based on Cloudflare Workers. Open-source and privacy-focused.`);return t===`/dash`?n=e(`common.selectProfile`):t===`/account`?n=e(`common.account`):t.endsWith(`/setup`)?(n=e(`nav.setup`),r=e(`meta.setupDesc`,`Configure your devices to use DNS Worker.`)):t.endsWith(`/filter`)?n=e(`nav.filter`):t.endsWith(`/rules`)?n=e(`nav.rules`):t.endsWith(`/settings`)?n=e(`nav.settings`):t.endsWith(`/stats`)?n=e(`nav.stats`):t.endsWith(`/logs`)&&(n=e(`nav.logs`)),{title:n?`${n} | DNS Worker`:`DNS Worker`,description:r}})(re().pathname)}var ir=null;function J(e){ir=e}function ar(){return ir}var Y=()=>{document.cookie=`csrf_token=; Max-Age=0; path=/; Secure; SameSite=Lax`;try{sessionStorage.removeItem(`obex_session_active`),sessionStorage.removeItem(`obex_session_locked`),sessionStorage.removeItem(`obex_username`),sessionStorage.removeItem(`obex_user_id`)}catch{}};function or(e){let[t,n]=(0,I.useState)(null),[r,i]=(0,I.useState)(null),{t:a,i18n:o}=b(),s=async()=>{try{if(!document.cookie.includes(`csrf_token=`)){n(!1);return}if(!ar())try{J((await nt()).accessToken)}catch{Y(),n(!1);return}try{let e=await U();i(e),e.username&&sessionStorage.setItem(`obex_username`,e.username),e.id&&sessionStorage.setItem(`obex_user_id`,e.id),e.timezone&&bn(e.timezone),e.locale&&(xn(e.locale),o.changeLanguage(e.locale)),n(!0)}catch(e){if(e instanceof B&&e.status===403&&e.bodyText===`session_paused`){n(!0),window.dispatchEvent(new Event(`session_paused`));return}e instanceof B&&e.status===401&&Y(),n(!1)}}catch{n(!1)}};return(0,I.useEffect)(()=>{s()},[]),(0,I.useEffect)(()=>{let e=async()=>{try{i(await U())}catch(e){console.warn(`Failed to refresh user on user_updated event`,e)}};return window.addEventListener(`user_updated`,e),()=>{window.removeEventListener(`user_updated`,e)}},[]),(0,I.useEffect)(()=>{let t=t=>{Y(),n(!1);let r=t.detail?.reason;if(r===`missing`)return;let i=a(`auth.unauthorizedDefault`);r===`geolocation_mismatch`||r===`geolocation_missing`?i=a(`auth.unauthorizedGeo`):r===`expired`?i=a(`auth.unauthorizedExpired`):r===`token_reuse`?i=a(`auth.unauthorizedReuse`):r===`session_not_found`&&(i=a(`auth.unauthorizedRevoked`)),e.current&&e.current.show({message:i,intent:`danger`,icon:`error`,timeout:5e3})};return window.addEventListener(`auth_unauthorized`,t),()=>{window.removeEventListener(`auth_unauthorized`,t)}},[a,e]),{isLoggedIn:t,currentUser:r,checkAuth:s,handleLogout:async()=>{try{await tt()}catch(e){console.error(`Logout failed`,e)}finally{if(typeof window<`u`&&`caches`in window)try{await caches.delete(`dns-worker-logs-v1`)}catch{}try{sessionStorage.removeItem(`dns_worker_session_active`)}catch{}Y(),n(!1),window.location.reload()}}}}function sr(e){let[t,n]=(0,I.useState)([]),[i,a]=(0,I.useState)(null),[o,s]=(0,I.useState)(!1),[c,l]=(0,I.useState)(!1),[u,d]=(0,I.useState)(``),[f,p]=(0,I.useState)(``),[m,h]=(0,I.useState)(null),g=r(),_=re(),{t:v}=b(),y=async()=>{try{n(await Ot())}catch(e){console.error(`Failed to fetch profiles`,e)}finally{s(!0)}};return(0,I.useEffect)(()=>{e===!0?y():(n([]),a(null),s(!1))},[e]),(0,I.useEffect)(()=>{e===!0&&_.pathname===`/dash`&&y()},[_.pathname]),{profiles:t,selectedProfile:i,setSelectedProfile:a,showCreateDialog:c,setShowCreateDialog:l,newProfileName:u,setNewProfileName:d,createError:f,setCreateError:p,prefilledRule:m,setPrefilledRule:h,fetchProfiles:y,handleCreateProfile:async()=>{if(u)try{await At(u),d(``),l(!1),await y()}catch(e){p(zn(e,v))}},handleDeleteProfile:async(e,t)=>{if(e.stopPropagation(),confirm(v(`common.confirmDelete`)))try{await jt(t),await y(),i?.id===t&&a(null)}catch(e){console.error(e)}},handleQuickAction:(e,t,n)=>{h({domain:e,type:t,recordType:n});let r=i?.id||_.pathname.split(`/`)[2];r&&g(`/dash/${r}/rules`)},loaded:o}}const cr=(0,I.forwardRef)(({length:e,value:t,onChange:n,disabled:r=!1,type:i=`text`,error:a=!1,autoFocus:o=!1,onComplete:s},c)=>{let l=(0,I.useRef)([]);(0,I.useImperativeHandle)(c,()=>({focus:()=>{l.current[0]?.focus()}})),(0,I.useEffect)(()=>{l.current=l.current.slice(0,e),o&&setTimeout(()=>{l.current[0]?.focus()},50)},[e,o]);let u=(r,i)=>{let a=r.target.value.replace(/\D/g,``);if(!a){let e=t.split(``);e[i]=``,n(e.join(``));return}let o=t.split(``);o[i]=a[a.length-1];let c=o.join(``);n(c),i<e-1?l.current[i+1]?.focus():c.length===e&&s?.(c)},d=(r,i)=>{if(r.key===`Backspace`){r.preventDefault();let e=t.split(``);e[i]?(e[i]=``,n(e.join(``))):i>0&&(e[i-1]=``,n(e.join(``)),l.current[i-1]?.focus())}else r.key===`ArrowLeft`&&i>0?l.current[i-1]?.focus():r.key===`ArrowRight`&&i<e-1&&l.current[i+1]?.focus()},f=t=>{t.preventDefault();let r=t.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,e);if(r){n(r);let t=Math.min(r.length,e-1);l.current[t]?.focus(),r.length===e&&s?.(r)}};return(0,L.jsx)(`div`,{className:`flex gap-2 justify-center my-2`,children:Array.from({length:e},(e,n)=>t[n]||``).map((e,t)=>(0,L.jsx)(`input`,{ref:e=>{l.current[t]=e},type:i===`password`?`password`:`text`,pattern:`\\d*`,inputMode:`numeric`,maxLength:1,value:e,disabled:r,onChange:e=>u(e,t),onKeyDown:e=>d(e,t),onPaste:f,autoComplete:`one-time-code`,className:`w-10 h-12 text-center text-xl font-bold rounded-lg border-2 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 transition-all duration-150 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 ${a?`border-red-500 focus:border-red-500 focus:ring-red-500/20`:`border-slate-200 dark:border-slate-700 focus:border-indigo-500 dark:focus:border-indigo-400`} ${r?`opacity-60 cursor-not-allowed bg-slate-50 dark:bg-slate-900`:``}`},t))})});cr.displayName=`DigitInput`;const lr=({currentUser:e,handleLogout:t,onUnlock:n,children:r})=>{let{t:i}=b(),[a,o]=(0,I.useState)(()=>sessionStorage.getItem(`obex_session_locked`)===`true`),[s,c]=(0,I.useState)(``),[l,u]=(0,I.useState)(!1),[d,f]=(0,I.useState)(``),[p,m]=(0,I.useState)(null),h=(0,I.useRef)(0),g=(0,I.useRef)(null),_=e?.session_lock_timeout??15,v=!!e?.pin_enabled,y=v;(0,I.useEffect)(()=>{if(!y||!v||a||!e)return;h.current=Date.now();let t=()=>{h.current=Date.now()},n=[`mousemove`,`mousedown`,`keypress`,`scroll`,`touchstart`,`click`];n.forEach(e=>{window.addEventListener(e,t)});let r=setInterval(async()=>{if(Date.now()-h.current>=_*60*1e3){o(!0),sessionStorage.setItem(`obex_session_locked`,`true`);try{await H()}catch(e){console.warn(`Failed to lock session on backend`,e)}}},1e4);return()=>{n.forEach(e=>{window.removeEventListener(e,t)}),clearInterval(r)}},[y,v,a,_,e]),(0,I.useEffect)(()=>{let e=()=>{o(!0),sessionStorage.setItem(`obex_session_locked`,`true`)};return window.addEventListener(`session_paused`,e),()=>{window.removeEventListener(`session_paused`,e)}},[]),(0,I.useEffect)(()=>{a&&setTimeout(()=>{g.current?.focus()},100)},[a]);let S=async r=>{let a=r||s;if(a){u(!0),f(``);try{let r=e?.id||sessionStorage.getItem(`obex_user_id`);if(!r){f(i(`auth.sessionExpired`,`Session expired. Logging out...`)),setTimeout(()=>{t()},1500);return}let{nonce:s,legacy:l}=await rt(),u=await Kn(a,r);l?await V(u,s):await V(await qn(u,s),s),o(!1),sessionStorage.removeItem(`obex_session_locked`),c(``),f(``),m(null),h.current=Date.now(),n&&n()}catch(e){if(c(``),e instanceof B)if(e.status===401&&e.bodyText.includes(`too_many_attempts`))f(i(`auth.sessionExpired`,`Too many failed attempts. Session terminated.`)),setTimeout(()=>{t()},1500);else if(e.status===400||e.status===401){let t=3;try{let n=JSON.parse(e.bodyText);n&&typeof n.attemptsRemaining==`number`&&(t=n.attemptsRemaining)}catch(e){console.debug(`Failed to parse attemptsRemaining from body`,e)}m(t),f(i(`auth.pinIncorrect`,`Incorrect PIN`)),setTimeout(()=>{g.current?.focus()},50)}else f(i(`auth.networkError`,`Network error. Please try again.`));else e instanceof Error?f(e.message):f(i(`common.errorNetwork`))}finally{u(!1)}}};return a?(0,L.jsx)(`div`,{className:`fixed inset-0 z-9999 flex flex-col items-center justify-center p-4`,style:{background:`radial-gradient(circle at center, #1b202e 0%, #0d0f14 100%)`,fontFamily:`system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif`,userSelect:`none`},children:(0,L.jsx)(`div`,{className:`w-full max-w-md`,children:(0,L.jsxs)(F,{elevation:A.FOUR,className:`w-full p-8 rounded-2xl shadow-none! dark:bg-gray-900 border border-gray-100 dark:border-gray-800 flex flex-col items-center`,onClick:()=>g.current?.focus(),children:[(0,L.jsxs)(`div`,{className:`flex flex-col items-center mb-8`,children:[(0,L.jsx)(`img`,{src:q,alt:`DNS Worker Logo`,className:`w-20 h-20 object-contain`}),(()=>{let t=e?.username||sessionStorage.getItem(`obex_username`)||``;return t?(0,L.jsx)(`h3`,{className:`font-bold tracking-tight text-2xl mt-4 text-slate-900 dark:text-slate-100`,children:t}):null})(),(0,L.jsx)(`p`,{className:`text-gray-500 mt-2 text-center text-sm leading-relaxed`,children:i(`auth.sessionLocked`,`Session Locked due to inactivity`)})]}),d&&(0,L.jsxs)(be,{intent:N.DANGER,className:`w-full mb-6 rounded-xl text-center`,children:[(0,L.jsx)(`div`,{className:`text-sm font-medium`,children:d}),p!==null&&(0,L.jsx)(`div`,{className:`text-xs mt-1 opacity-80`,children:i(`auth.attemptsRemaining`,`{{count}} attempts remaining`,{count:p})})]}),(0,L.jsx)(`div`,{className:`w-full flex justify-center mb-6`,children:(0,L.jsx)(cr,{ref:g,length:4,value:s,onChange:c,disabled:l,type:`password`,error:!!d,autoFocus:!0,onComplete:e=>S(e)})}),l&&(0,L.jsx)(`div`,{className:`mb-4`,children:(0,L.jsx)(M,{size:24})}),(0,L.jsx)(`div`,{className:`w-full flex justify-center mt-4`,children:(0,L.jsx)(j,{minimal:!0,intent:N.NONE,icon:(0,L.jsx)(x,{size:16}),onClick:e=>{e.stopPropagation(),t()},className:`text-gray-400 hover:text-gray-700 dark:hover:text-gray-200`,children:i(`auth.logoutAndReturn`,`Log Out Session`)})})]})})}):(0,L.jsx)(L.Fragment,{children:r})},ur=({itemCount:e})=>{let t=(0,I.useRef)(null),[n,r]=(0,I.useState)(-1),[i,a]=(0,I.useState)(!1),o=(0,I.useRef)(!1),s=(0,I.useRef)(0),c=(0,I.useRef)(0),l=(0,I.useRef)(null),u=t=>{let n=Array.from(t.children);if(n.length>=e*3){let r=n[0].offsetTop,i=n[e].offsetTop-r;i>0&&(t.scrollTop>=i*2?t.scrollTop-=i:t.scrollTop<i&&(t.scrollTop+=i))}};return(0,I.useEffect)(()=>{let n=t.current;if(!n)return;requestAnimationFrame(()=>{let t=Array.from(n.children);if(t.length>=e*3){let r=t[0].offsetTop,i=t[e].offsetTop-r;i>0&&n.scrollTop===0&&(n.scrollTop=i)}});let r=e=>{e.button===0&&(o.current=!0,s.current=e.clientY,c.current=n.scrollTop,a(!0))},i=e=>{if(!o.current)return;e.preventDefault();let t=e.clientY-s.current;n.scrollTop=c.current-t,u(n)},d=()=>{o.current&&(o.current=!1,a(!1))},f=e=>{e.touches.length===1&&(o.current=!0,s.current=e.touches[0].clientY,c.current=n.scrollTop,a(!0))},p=e=>{if(!o.current||e.touches.length!==1)return;e.preventDefault();let t=e.touches[0].clientY-s.current;n.scrollTop=c.current-t,u(n)},m=()=>{o.current&&(o.current=!1,a(!1))},h=()=>{a(!0),l.current&&window.clearTimeout(l.current),l.current=window.setTimeout(()=>{a(!1)},1200),u(n)};return n.addEventListener(`mousedown`,r),window.addEventListener(`mousemove`,i),window.addEventListener(`mouseup`,d),n.addEventListener(`touchstart`,f,{passive:!0}),n.addEventListener(`touchmove`,p,{passive:!1}),n.addEventListener(`touchend`,m),n.addEventListener(`touchcancel`,m),n.addEventListener(`wheel`,h,{passive:!0}),()=>{n.removeEventListener(`mousedown`,r),window.removeEventListener(`mousemove`,i),window.removeEventListener(`mouseup`,d),n.removeEventListener(`touchstart`,f),n.removeEventListener(`touchmove`,p),n.removeEventListener(`touchend`,m),n.removeEventListener(`touchcancel`,m),n.removeEventListener(`wheel`,h),l.current&&window.clearTimeout(l.current)}},[e]),(0,I.useEffect)(()=>{let n=t.current;if(!n)return;let a,s=()=>{!i&&!o.current&&(n.scrollTop+=.5,u(n));let t=n.getBoundingClientRect(),c=t.top+t.height/3,l=Array.from(n.children),d=-1;for(let t=0;t<l.length;t++){let n=l[t].getBoundingClientRect();if(n.top<=c&&n.bottom>=c){d=t%e;break}}r(d),a=requestAnimationFrame(s)};return a=requestAnimationFrame(s),()=>cancelAnimationFrame(a)},[i,e]),{containerRef:t,activeIdx:n,isPaused:i,setIsPaused:a}};var X=[{icon:n,colorClass:`text-blue-500`,titleKey:`intro.item1Title`,descKey:`intro.item1Desc`},{icon:S,colorClass:`text-purple-500`,titleKey:`intro.item2Title`,descKey:`intro.item2Desc`},{icon:D,colorClass:`text-green-500`,titleKey:`intro.item3Title`,descKey:`intro.item3Desc`},{icon:T,colorClass:`text-orange-500`,titleKey:`intro.item4Title`,descKey:`intro.item4Desc`},{icon:te,colorClass:`text-red-500`,titleKey:`intro.item5Title`,descKey:`intro.item5Desc`},{icon:ce,colorClass:`text-yellow-500`,titleKey:`intro.item6Title`,descKey:`intro.item6Desc`},{icon:oe,colorClass:`text-cyan-500`,titleKey:`intro.item7Title`,descKey:`intro.item7Desc`},{icon:c,colorClass:`text-indigo-500`,titleKey:`intro.item9Title`,descKey:`intro.item9Desc`},{icon:v,colorClass:`text-pink-500`,titleKey:`intro.item8Title`,descKey:`intro.item8Desc`}];const dr=()=>{let{t:e}=b(),{containerRef:t,activeIdx:n,setIsPaused:r}=ur({itemCount:X.length});return(0,L.jsx)(`div`,{className:`flex flex-col h-full overflow-y-auto no-scrollbar py-[50vh] px-8 lg:px-16 relative select-none cursor-grab active:cursor-grabbing bg-transparent`,ref:t,onMouseEnter:()=>r(!0),onMouseLeave:()=>r(!1),style:{scrollbarWidth:`none`},children:[...X,...X,...X].map((t,r)=>{let i=r%X.length===n,a=t.icon,o=(r%X.length+1).toString().padStart(2,`0`);return(0,L.jsx)(`div`,{className:`transition-[opacity,transform,border-color,filter] duration-300 ease-out shrink-0 border-l-4 mb-8 pl-6 transform-gpu ${i?`border-blue-600 scale-[1.03] opacity-100 grayscale-0`:`border-gray-200 dark:border-gray-800 scale-100 opacity-30 grayscale`}`,children:(0,L.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,L.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,L.jsxs)(`span`,{className:`font-mono text-xs font-bold tracking-widest transition-colors duration-300 ${i?`text-blue-600`:`text-gray-400`}`,children:[`/`,o]}),(0,L.jsx)(`div`,{className:`transition-transform duration-300 ${i?`rotate-0 scale-110`:`rotate-12 opacity-50`}`,children:(0,L.jsx)(a,{size:24,className:t.colorClass})})]}),(0,L.jsxs)(`div`,{className:`space-y-2`,children:[(0,L.jsx)(`h2`,{className:`text-4xl font-black leading-none tracking-tighter uppercase transition-colors duration-300 ${i?`text-gray-900 dark:text-white`:`text-gray-300 dark:text-gray-700`}`,children:e(t.titleKey)}),(0,L.jsx)(`p`,{className:`max-w-md text-lg font-medium leading-snug transition-colors duration-300 ${i?`text-gray-600 dark:text-gray-400`:`text-transparent`}`,children:e(t.descKey)})]}),i&&(0,L.jsx)(`div`,{className:`flex gap-1 mt-2 transition-all duration-300`,children:(0,L.jsx)(`div`,{className:`h-1 w-2 bg-gray-200 dark:bg-gray-800`})})]})},r)})})},Z=({code:e,copyText:t,copiedText:n})=>{let[r,i]=(0,I.useState)(!1);return(0,L.jsxs)(`div`,{className:`relative group my-2 bg-zinc-950 dark:bg-black text-zinc-200 rounded-lg p-4 font-mono text-sm border border-zinc-800/80 overflow-x-auto shadow-inner`,children:[(0,L.jsx)(`pre`,{className:`whitespace-pre`,children:e}),(0,L.jsx)(`button`,{onClick:async()=>{try{await navigator.clipboard.writeText(e),i(!0),setTimeout(()=>i(!1),2e3)}catch(e){console.error(`Failed to copy text:`,e)}},className:`absolute top-2 right-2 px-2.5 py-1 text-xs rounded bg-zinc-850 hover:bg-zinc-800 text-zinc-300 hover:text-white transition duration-200 border border-zinc-700/60 flex items-center gap-1.5`,children:r?(0,L.jsxs)(L.Fragment,{children:[(0,L.jsx)(`svg`,{className:`w-3.5 h-3.5 text-emerald-400`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:`2.5`,children:(0,L.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M5 13l4 4L19 7`})}),(0,L.jsx)(`span`,{children:n})]}):(0,L.jsxs)(L.Fragment,{children:[(0,L.jsx)(`svg`,{className:`w-3.5 h-3.5`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:`2`,children:(0,L.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3`})}),(0,L.jsx)(`span`,{children:t})]})})]})},fr=()=>{let{t:e}=b();return(0,L.jsxs)(L.Fragment,{children:[(0,L.jsxs)(`div`,{children:[(0,L.jsxs)(`h3`,{className:`text-sm font-bold text-gray-900 dark:text-zinc-100 mb-1 flex items-center gap-2 mt-0`,children:[(0,L.jsx)(`span`,{className:`flex items-center justify-center w-5 h-5 rounded bg-blue-500/10 text-blue-600 dark:text-blue-400 text-xs font-bold`,children:`1`}),e(`deploymentGuide.stepDbTitle`)]}),(0,L.jsx)(`p`,{className:`text-gray-600 dark:text-zinc-400 text-xs mb-2`,children:e(`deploymentGuide.stepDbDesc`)}),(0,L.jsx)(Z,{code:e(`deploymentGuide.stepDbCommand1`),copyText:e(`deploymentGuide.copy`),copiedText:e(`deploymentGuide.copied`)}),(0,L.jsx)(`p`,{className:`text-gray-600 dark:text-zinc-400 text-xs mt-3 mb-2`,children:e(`deploymentGuide.stepDbDesc2`)}),(0,L.jsx)(Z,{code:e(`deploymentGuide.stepDbCommand2`),copyText:e(`deploymentGuide.copy`),copiedText:e(`deploymentGuide.copied`)})]}),(0,L.jsxs)(`div`,{className:`border-t border-gray-100 dark:border-zinc-800 pt-4`,children:[(0,L.jsxs)(`h3`,{className:`text-sm font-bold text-gray-900 dark:text-zinc-100 mb-1 flex items-center gap-2 mt-0`,children:[(0,L.jsx)(`span`,{className:`flex items-center justify-center w-5 h-5 rounded bg-blue-500/10 text-blue-600 dark:text-blue-400 text-xs font-bold`,children:`2`}),e(`deploymentGuide.stepJwtTitle`)]}),(0,L.jsx)(`p`,{className:`text-gray-600 dark:text-zinc-400 text-xs mb-2`,children:e(`deploymentGuide.stepJwtDesc`)}),(0,L.jsx)(Z,{code:e(`deploymentGuide.stepJwtCommand1`),copyText:e(`deploymentGuide.copy`),copiedText:e(`deploymentGuide.copied`)})]}),(0,L.jsxs)(`div`,{className:`border-t border-gray-100 dark:border-zinc-800 pt-4`,children:[(0,L.jsxs)(`h3`,{className:`text-sm font-bold text-gray-900 dark:text-zinc-100 mb-1 flex items-center gap-2 mt-0`,children:[(0,L.jsx)(`span`,{className:`flex items-center justify-center w-5 h-5 rounded bg-blue-500/10 text-blue-600 dark:text-blue-400 text-xs font-bold`,children:`3`}),e(`deploymentGuide.stepDeployTitle`)]}),(0,L.jsx)(`p`,{className:`text-gray-600 dark:text-zinc-400 text-xs mb-2`,children:e(`deploymentGuide.stepDeployDesc`)}),(0,L.jsx)(Z,{code:e(`deploymentGuide.stepDeployCommand`),copyText:e(`deploymentGuide.copy`),copiedText:e(`deploymentGuide.copied`)})]})]})},pr=()=>{let{t:e}=b();return(0,L.jsxs)(L.Fragment,{children:[(0,L.jsxs)(`div`,{children:[(0,L.jsxs)(`h3`,{className:`text-sm font-bold text-gray-900 dark:text-zinc-100 mb-1 flex items-center gap-2 mt-0`,children:[(0,L.jsx)(`span`,{className:`flex items-center justify-center w-5 h-5 rounded bg-blue-500/10 text-blue-600 dark:text-blue-400 text-xs font-bold`,children:`1`}),e(`deploymentGuide.stepDbTitle`)]}),(0,L.jsx)(`div`,{className:`text-gray-600 dark:text-zinc-400 text-xs space-y-2 leading-relaxed mb-3`,children:e(`deploymentGuide.stepDbDashDesc`).split(`
15
+ `).map((e,t)=>(0,L.jsx)(`p`,{className:`m-0`,children:e},t))}),(0,L.jsxs)(`a`,{href:e(`deploymentGuide.stepJwtCommand2`),target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex items-center gap-1.5 text-xs text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300 font-bold transition duration-200`,children:[(0,L.jsx)(`span`,{children:e(`deploymentGuide.stepJwtDesc2`)}),(0,L.jsx)(C,{size:12})]})]}),(0,L.jsxs)(`div`,{className:`border-t border-gray-100 dark:border-zinc-800 pt-4`,children:[(0,L.jsxs)(`h3`,{className:`text-sm font-bold text-gray-900 dark:text-zinc-100 mb-1 flex items-center gap-2 mt-0`,children:[(0,L.jsx)(`span`,{className:`flex items-center justify-center w-5 h-5 rounded bg-blue-500/10 text-blue-600 dark:text-blue-400 text-xs font-bold`,children:`2`}),e(`deploymentGuide.stepJwtTitle`)]}),(0,L.jsx)(`div`,{className:`text-gray-600 dark:text-zinc-400 text-xs space-y-2 leading-relaxed mb-3`,children:e(`deploymentGuide.stepJwtDashDesc`).split(`
16
+ `).map((e,t)=>(0,L.jsx)(`p`,{className:`m-0`,children:e},t))}),(0,L.jsxs)(`a`,{href:e(`deploymentGuide.stepJwtCommand2`),target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex items-center gap-1.5 text-xs text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300 font-bold transition duration-200`,children:[(0,L.jsx)(`span`,{children:e(`deploymentGuide.stepJwtDesc2`)}),(0,L.jsx)(C,{size:12})]})]}),(0,L.jsxs)(`div`,{className:`border-t border-gray-100 dark:border-zinc-800 pt-4`,children:[(0,L.jsxs)(`h3`,{className:`text-sm font-bold text-gray-900 dark:text-zinc-100 mb-1 flex items-center gap-2 mt-0`,children:[(0,L.jsx)(`span`,{className:`flex items-center justify-center w-5 h-5 rounded bg-blue-500/10 text-blue-600 dark:text-blue-400 text-xs font-bold`,children:`3`}),e(`deploymentGuide.stepDeployTitle`)]}),(0,L.jsx)(`p`,{className:`text-gray-600 dark:text-zinc-400 text-xs mb-0 leading-relaxed`,children:e(`deploymentGuide.stepDeployDashDesc`)})]})]})};var mr=()=>{let e=new Uint32Array(64);window.crypto.getRandomValues(e);let t=``;for(let n=0;n<e.length;n++)t+=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`[e[n]%62];return t};const hr=()=>{let{t:e}=b(),[t,n]=(0,I.useState)(mr),[r,i]=(0,I.useState)(!1);return(0,L.jsxs)(`div`,{className:`mb-6 border border-zinc-200 dark:border-zinc-800 rounded-xl p-4 bg-zinc-50 dark:bg-zinc-950/60 shadow-inner`,children:[(0,L.jsxs)(`h3`,{className:`text-sm font-bold text-gray-900 dark:text-zinc-100 mb-1 flex items-center gap-2 mt-0`,children:[(0,L.jsx)(`span`,{className:`w-2 h-2 rounded-full bg-emerald-500 animate-pulse`}),e(`deploymentGuide.jwtGeneratorTitle`)]}),(0,L.jsx)(`p`,{className:`text-gray-500 dark:text-zinc-400 text-xs mb-3`,children:e(`deploymentGuide.jwtGeneratorDesc`)}),(0,L.jsxs)(`div`,{className:`flex gap-2 items-center`,children:[(0,L.jsx)(`div`,{className:`flex-1 font-mono text-xs p-3 bg-zinc-900 dark:bg-black text-zinc-100 rounded-lg select-all overflow-x-auto border border-zinc-800/80 shadow-inner leading-relaxed break-all whitespace-nowrap scrollbar-thin`,children:t}),(0,L.jsxs)(`div`,{className:`flex flex-col sm:flex-row gap-1.5 shrink-0`,children:[(0,L.jsx)(j,{intent:r?N.SUCCESS:N.NONE,icon:r?`tick`:`duplicate`,text:e(r?`deploymentGuide.copied`:`deploymentGuide.copy`),onClick:async()=>{try{await navigator.clipboard.writeText(t),i(!0),setTimeout(()=>i(!1),2e3)}catch(e){console.error(`Failed to copy text:`,e)}},size:`small`}),(0,L.jsx)(j,{icon:`refresh`,text:e(`deploymentGuide.regenerate`),onClick:()=>{n(mr()),i(!1)},size:`small`})]})]})]})},gr=()=>{let{t:e}=b(),[t,n]=(0,I.useState)(`cli`),[r,i]=(0,I.useState)(!0),a=window.DNS_WORKER_CONFIG?.isDbMissing??!0,o=window.DNS_WORKER_CONFIG?.isJwtSecretMissing??!0;return(0,L.jsxs)(`div`,{className:`flex flex-row min-h-screen bg-white dark:bg-gray-950 overflow-hidden relative`,children:[(0,L.jsx)(`div`,{className:`hidden lg:block w-1/2 h-screen overflow-hidden border-r border-gray-100 dark:border-gray-900`,children:(0,L.jsx)(dr,{})}),(0,L.jsx)(`div`,{className:`lg:hidden absolute inset-0 z-0 transition-opacity duration-500 cursor-pointer ${r?`opacity-25`:`opacity-70`}`,onClick:()=>i(!0),children:(0,L.jsx)(dr,{})}),!r&&(0,L.jsx)(`div`,{className:`lg:hidden fixed bottom-12 left-1/2 -translate-x-1/2 z-50 animate-bounce`,children:(0,L.jsx)(j,{large:!0,intent:`primary`,icon:`manual`,text:e(`deploymentGuide.title`),onClick:()=>i(!0),className:`shadow-2xl px-8 py-4 rounded-full`})}),(0,L.jsxs)(`div`,{className:`flex-1 flex items-center justify-center p-4 relative z-10 bg-gray-50/50 dark:bg-gray-900/30 lg:bg-gray-50 lg:dark:bg-gray-900/50 transition-all duration-500 ease-in-out ${r?`translate-x-0 opacity-100`:`max-lg:translate-x-full max-lg:opacity-0 max-lg:pointer-events-none`}`,onClick:e=>{window.innerWidth<1024&&e.target===e.currentTarget&&i(!1)},children:[(0,L.jsx)(`div`,{className:`absolute top-4 right-4 z-50`,children:(0,L.jsx)(K,{})}),(0,L.jsx)(`div`,{className:`w-full max-w-2xl transition-all duration-200 ease-in-out transform-gpu`,children:(0,L.jsxs)(F,{elevation:A.FOUR,className:`w-full max-h-[90vh] flex flex-col p-6 md:p-8 rounded-2xl border border-gray-100 dark:border-gray-800 dark:bg-gray-900 shadow-xl`,onClick:e=>e.stopPropagation(),children:[(0,L.jsxs)(`div`,{className:`flex items-center gap-4 mb-6 shrink-0`,children:[(0,L.jsx)(`img`,{src:q,alt:`DNS Worker Logo`,className:`w-10 h-10 object-contain rounded-xl shadow-lg shadow-blue-500/10`}),(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`h1`,{className:`text-xl font-extrabold text-gray-900 dark:text-zinc-50 tracking-tight m-0`,children:`DNS Worker`}),(0,L.jsx)(`p`,{className:`text-xs text-gray-500 dark:text-zinc-400 font-medium m-0 mt-0.5`,children:`Advanced Agentic DNS Server`})]})]}),(0,L.jsxs)(`div`,{className:`flex-1 overflow-y-auto pr-1.5 min-h-0 space-y-6 scrollbar-thin`,children:[(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`h2`,{className:`text-lg md:text-xl font-bold text-gray-900 dark:text-zinc-50 mb-1 mt-0`,children:e(`deploymentGuide.title`)}),(0,L.jsx)(`p`,{className:`text-gray-600 dark:text-zinc-400 text-xs md:text-sm leading-relaxed m-0`,children:e(`deploymentGuide.subtitle`)})]}),(0,L.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-4`,children:[(0,L.jsx)(be,{intent:a?N.DANGER:N.SUCCESS,icon:a?`warning-sign`:`tick`,title:e(`deploymentGuide.dbStatus`),className:`flex-1`,children:(0,L.jsx)(`span`,{className:`font-semibold text-xs`,children:e(a?`deploymentGuide.missing`:`deploymentGuide.configured`)})}),(0,L.jsx)(be,{intent:o?N.DANGER:N.SUCCESS,icon:o?`warning-sign`:`tick`,title:e(`deploymentGuide.jwtStatus`),className:`flex-1`,children:(0,L.jsx)(`span`,{className:`font-semibold text-xs`,children:e(o?`deploymentGuide.missing`:`deploymentGuide.configured`)})})]}),(0,L.jsx)(hr,{}),(0,L.jsx)(`div`,{children:(0,L.jsxs)(De,{id:`deploy-methods`,selectedTabId:t,onChange:e=>n(e),className:`border-b border-gray-200 dark:border-zinc-800 pb-2`,children:[(0,L.jsx)(Te,{id:`cli`,title:(0,L.jsxs)(`div`,{className:`flex items-center gap-2 font-bold py-1.5 px-1`,children:[(0,L.jsx)(le,{size:14}),(0,L.jsx)(`span`,{children:e(`deploymentGuide.methodCli`)})]})}),(0,L.jsx)(Te,{id:`dash`,title:(0,L.jsxs)(`div`,{className:`flex items-center gap-2 font-bold py-1.5 px-1`,children:[(0,L.jsx)(ie,{size:14}),(0,L.jsx)(`span`,{children:e(`deploymentGuide.methodDash`)})]})})]})}),(0,L.jsx)(`div`,{className:`space-y-6 pb-2`,children:t===`cli`?(0,L.jsx)(fr,{}):(0,L.jsx)(pr,{})})]}),(0,L.jsx)(`div`,{className:`flex items-center justify-end border-t border-gray-200 dark:border-zinc-800 pt-4 shrink-0 mt-4`,children:(0,L.jsx)(j,{large:!0,intent:N.PRIMARY,icon:(0,L.jsx)(h,{size:14,className:`animate-spin-hover`}),text:e(`deploymentGuide.refresh`),onClick:()=>{window.location.reload()}})})]})})]})]})};var _r=R(()=>O(()=>import(`./AuthView-Bwv6hbdi.js`),__vite__mapDeps([16,1,2,3,4,5,6,7,17,18])).then(e=>({default:e.AuthView}))),vr=R(()=>O(()=>import(`./AccountView-BvRvODjN.js`),__vite__mapDeps([19,1,2,3,4,5,6,7,17,18])).then(e=>({default:e.AccountView})));function yr(){let[e,t]=(0,I.useState)(!0),n=r(),i=re(),s=(0,I.useRef)(null),{i18n:c}=b(),{theme:u,setTheme:d}=nr(),p=rr(),{isLoggedIn:m,currentUser:h,checkAuth:g,handleLogout:_}=or(s),{profiles:v,selectedProfile:y,setSelectedProfile:x,showCreateDialog:S,setShowCreateDialog:C,newProfileName:w,setNewProfileName:ee,createError:te,prefilledRule:ne,setPrefilledRule:ie,fetchProfiles:T,handleCreateProfile:E,handleDeleteProfile:ae,handleQuickAction:oe}=sr(m),[D,se]=(0,I.useState)(!1),[ce,le]=(0,I.useState)(!1);if((0,I.useEffect)(()=>{Le(c.language).finally(()=>{le(!0)})},[c.language]),!ce)return(0,L.jsx)(`div`,{className:`h-screen flex items-center justify-center`,children:(0,L.jsx)(M,{size:50})});let ue=window.DNS_WORKER_CONFIG?.isDbMissing,de=window.DNS_WORKER_CONFIG?.isJwtSecretMissing;return ue||de?(0,L.jsx)(gr,{}):m===null?(0,L.jsxs)(`div`,{className:`h-screen flex items-center justify-center`,children:[(0,L.jsx)(ze,{}),(0,L.jsx)(M,{size:50})]}):m?(0,L.jsxs)(I.Suspense,{fallback:(0,L.jsx)(`div`,{className:`h-screen flex items-center justify-center`,children:(0,L.jsx)(M,{size:50})}),children:[(0,L.jsxs)(l,{children:[(0,L.jsx)(`title`,{children:p.title}),(0,L.jsx)(`meta`,{name:`description`,content:p.description}),(0,L.jsx)(`html`,{lang:c.language})]}),(0,L.jsx)(ze,{}),(0,L.jsx)(Ae,{position:`bottom`,ref:s}),(0,L.jsx)(lr,{currentUser:h,handleLogout:_,onUnlock:T,children:(0,L.jsxs)(f,{children:[(0,L.jsx)(a,{path:`/`,element:(0,L.jsx)(o,{to:`/dash`,replace:!0})}),(0,L.jsx)(a,{path:`/dash`,element:(0,L.jsx)(Zn,{profiles:v,onSelect:e=>{x(e),n(`/dash/${e.id}/setup`)},onCreate:E,showCreate:S,setShowCreate:C,newName:w,setNewName:ee,error:te,onDelete:ae,handleLogout:_,navigate:n,onRefresh:T,currentUser:h})}),(0,L.jsx)(a,{path:`/dash/:profileId/*`,element:(0,L.jsx)(tr,{isSidebarOpen:e,setIsSidebarOpen:t,theme:u,setTheme:d,selectedProfile:y,profiles:v,setSelectedProfile:x,location:i,navigate:n,handleLogout:_,currentUser:h,isSaving:D,children:(0,L.jsx)(Ye,{selectedProfile:y,prefilledRule:ne,setPrefilledRule:ie,handleQuickAction:oe,toasterRef:s,currentUser:h,onSavingChange:se})})}),(0,L.jsx)(a,{path:`/account`,element:(0,L.jsx)(tr,{isSidebarOpen:e,setIsSidebarOpen:t,theme:u,setTheme:d,selectedProfile:y,profiles:v,setSelectedProfile:x,location:i,navigate:n,handleLogout:_,currentUser:h,children:(0,L.jsx)(vr,{})})}),(0,L.jsx)(a,{path:`*`,element:(0,L.jsx)(Be,{})})]})})]}):(0,L.jsxs)(I.Suspense,{fallback:(0,L.jsx)(`div`,{className:`h-screen flex items-center justify-center`,children:(0,L.jsx)(M,{size:50})}),children:[(0,L.jsxs)(l,{children:[(0,L.jsx)(`title`,{children:p.title}),(0,L.jsx)(`meta`,{name:`description`,content:p.description}),(0,L.jsx)(`html`,{lang:c.language})]}),(0,L.jsx)(ze,{}),(0,L.jsx)(Ae,{position:`bottom`,ref:s}),(0,L.jsx)(_r,{onSuccess:g})]})}var br=yr;pe.setLoaderOptions({loader:`split-by-size`}),ye.onlyShowFocusOnTabs(),pe.loadAll();var xr=!1,Q=`unknown`,Sr=[];function Cr(e){Sr.push(e)}function $(e){Sr.forEach(t=>t(e)),Sr=[]}var wr=window.fetch;window.fetch=async function(e,t){let n=``;typeof e==`string`?n=e:e instanceof URL?n=e.href:e&&typeof e==`object`&&`url`in e&&(n=e.url);let r=n.startsWith(`/api/`)||n.includes(window.location.host+`/api/`);if(r){t||={};let e=new Headers(t.headers),r=t.method?.toUpperCase()||`GET`;if([`POST`,`PUT`,`PATCH`,`DELETE`].includes(r)){let t=document.cookie.match(/(?:^|;\s*)csrf_token=([^;]*)/),n=t?t[1]:null;n&&e.set(`X-CSRF-Token`,n)}let i=ar();i&&!n.includes(`/api/auth/refresh`)&&e.set(`Authorization`,`Bearer ${i}`),t.headers=e}let i=await wr(e,t);if(r&&i.status===403&&!n.includes(`/api/auth/`))try{await i.clone().text()===`session_paused`&&window.dispatchEvent(new Event(`session_paused`))}catch{}if(r&&i.status===401&&(!n.includes(`/api/auth/`)||n.includes(`/api/auth/unlock-session`)||n.includes(`/api/auth/lock-session`))){xr||(xr=!0,wr(`/api/auth/refresh`,{method:`POST`}).then(async e=>{if(e.ok)try{let t=await e.json();J(t.accessToken),$(t.accessToken)}catch{J(null),Q=`invalid_payload`,$(``)}else{J(null);let t=`unknown`;try{let n=await e.text();if(n===`Refresh token missing`)t=`missing`;else{let e=JSON.parse(n);e&&e.reason&&(t=e.reason)}}catch{}Q=t,$(``)}}).catch(()=>{J(null),Q=`network_error`,$(``)}).finally(()=>{xr=!1}));let n=await new Promise(e=>{Cr(e)});if(n){let r=new Headers(t?.headers);r.set(`Authorization`,`Bearer ${n}`),i=await wr(e,{...t,headers:r})}else window.dispatchEvent(new CustomEvent(`auth_unauthorized`,{detail:{reason:Q}}))}return i},typeof window<`u`&&`caches`in window&&(sessionStorage.getItem(`dns_worker_session_active`)||(caches.delete(`dns-worker-logs-v1`).catch(()=>{}),sessionStorage.setItem(`dns_worker_session_active`,`true`))),(0,Pe.createRoot)(document.getElementById(`root`)).render((0,L.jsx)(Ee,{children:(0,L.jsx)(d,{children:(0,L.jsx)(_,{children:(0,L.jsx)(br,{})})})}));export{$t as $,gn as A,Dt as At,It as B,Ze as Bt,Cn as C,xt as Ct,mn as D,Ct as Dt,pn as E,_t as Et,ln as F,ot as Ft,Pt as G,tt as Gt,Ht as H,rt as Ht,rn as I,ht as It,jt as J,et as Jt,At as K,Qe as Kt,an as L,St as Lt,sn as M,ft as Mt,dn as N,it as Nt,hn as O,lt as Ot,un as P,gt as Pt,Gt as Q,on as R,Et as Rt,K as S,Tt as St,bn as T,st as Tt,Bt as U,H as Ut,Kt as V,Xe as Vt,Vt as W,$e as Wt,Wt as X,z as Xt,qt as Y,V as Yt,Zt as Z,Pn as _,at as _t,kn as a,Ot as at,Fn as b,ut as bt,On as c,Yt as ct,Hn as d,Ft as dt,kt as et,Kn as f,Ut as ft,Bn as g,pt as gt,Ln as h,yt as ht,jn as i,zt as it,nn as j,vt as jt,fn as k,ct as kt,Wn as l,Rt as lt,Gn as m,dt as mt,cr as n,Qt as nt,Nn as o,tn as ot,Vn as p,Mt as pt,Lt as q,nt as qt,J as r,Xt as rt,An as s,Jt as st,dr as t,Nt as tt,zn as u,en as ut,In as v,wt as vt,xn as w,bt as wt,q as x,U as xt,Jn as y,mt as yt,cn as z,B as zt};