brew-tui 0.3.1 → 0.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.
- package/build/{brewbar-installer-H5MLNNTD.js → brewbar-installer-SFVZEIA6.js} +2 -2
- package/build/{chunk-PTLSNG2N.js → chunk-PPSKR6PA.js} +19 -1
- package/build/chunk-PPSKR6PA.js.map +1 -0
- package/build/index.js +149 -33
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/build/chunk-PTLSNG2N.js.map +0 -1
- /package/build/{brewbar-installer-H5MLNNTD.js.map → brewbar-installer-SFVZEIA6.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
fetchWithTimeout,
|
|
3
3
|
t
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PPSKR6PA.js";
|
|
5
5
|
|
|
6
6
|
// src/lib/brewbar-installer.ts
|
|
7
7
|
import { rm, access, readFile } from "fs/promises";
|
|
@@ -115,4 +115,4 @@ export {
|
|
|
115
115
|
isBrewBarInstalled,
|
|
116
116
|
uninstallBrewBar
|
|
117
117
|
};
|
|
118
|
-
//# sourceMappingURL=brewbar-installer-
|
|
118
|
+
//# sourceMappingURL=brewbar-installer-SFVZEIA6.js.map
|
|
@@ -51,6 +51,7 @@ var en = {
|
|
|
51
51
|
hint_force: "force uninstall (ignore deps)",
|
|
52
52
|
hint_rescan: "rescan",
|
|
53
53
|
hint_deactivate: "deactivate",
|
|
54
|
+
hint_promo: "promo code",
|
|
54
55
|
hint_importProfile: "import this profile",
|
|
55
56
|
hint_lang: "lang",
|
|
56
57
|
hint_replay: "replay",
|
|
@@ -247,6 +248,14 @@ var en = {
|
|
|
247
248
|
account_licenseExpired: "Your license has expired. Renew to continue using Pro features.",
|
|
248
249
|
account_deactivating: "Deactivating...",
|
|
249
250
|
account_loading: "Loading license status...",
|
|
251
|
+
account_promoTitle: "Redeem Promo Code",
|
|
252
|
+
account_promoLabel: "Code:",
|
|
253
|
+
account_promoValidating: "Validating promo code...",
|
|
254
|
+
account_promoSuccess: "Promo code redeemed! Pro access until {{expires}}.",
|
|
255
|
+
account_promoInvalid: "Invalid or expired promo code.",
|
|
256
|
+
account_promoError: "Could not validate promo code. Check your connection.",
|
|
257
|
+
account_promoEsc: "esc: cancel",
|
|
258
|
+
account_promoHint: "p: redeem promo code",
|
|
250
259
|
// ── Upgrade Prompt ──
|
|
251
260
|
upgrade_proFeature: "{{title}} \u2014 Pro Feature",
|
|
252
261
|
upgrade_profiles: "Package Profiles",
|
|
@@ -399,6 +408,7 @@ var es = {
|
|
|
399
408
|
hint_force: "forzar (ignorar deps)",
|
|
400
409
|
hint_rescan: "re-escanear",
|
|
401
410
|
hint_deactivate: "desactivar",
|
|
411
|
+
hint_promo: "c\xF3digo promo",
|
|
402
412
|
hint_importProfile: "importar este perfil",
|
|
403
413
|
hint_lang: "idioma",
|
|
404
414
|
hint_replay: "repetir",
|
|
@@ -595,6 +605,14 @@ var es = {
|
|
|
595
605
|
account_licenseExpired: "Tu licencia ha expirado. Renueva para seguir usando las funciones Pro.",
|
|
596
606
|
account_deactivating: "Desactivando...",
|
|
597
607
|
account_loading: "Cargando estado de la licencia...",
|
|
608
|
+
account_promoTitle: "Canjear C\xF3digo Promocional",
|
|
609
|
+
account_promoLabel: "C\xF3digo:",
|
|
610
|
+
account_promoValidating: "Validando c\xF3digo promocional...",
|
|
611
|
+
account_promoSuccess: "\xA1C\xF3digo canjeado! Acceso Pro hasta {{expires}}.",
|
|
612
|
+
account_promoInvalid: "C\xF3digo inv\xE1lido o expirado.",
|
|
613
|
+
account_promoError: "No se pudo validar el c\xF3digo. Comprueba tu conexi\xF3n.",
|
|
614
|
+
account_promoEsc: "esc: cancelar",
|
|
615
|
+
account_promoHint: "p: canjear c\xF3digo promocional",
|
|
598
616
|
// ── Upgrade Prompt ──
|
|
599
617
|
upgrade_proFeature: "{{title}} \u2014 Funci\xF3n Pro",
|
|
600
618
|
upgrade_profiles: "Perfiles de Paquetes",
|
|
@@ -761,4 +779,4 @@ export {
|
|
|
761
779
|
logger,
|
|
762
780
|
fetchWithTimeout
|
|
763
781
|
};
|
|
764
|
-
//# sourceMappingURL=chunk-
|
|
782
|
+
//# sourceMappingURL=chunk-PPSKR6PA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/i18n/index.ts","../src/i18n/en.ts","../src/i18n/es.ts","../src/utils/logger.ts","../src/lib/fetch-timeout.ts"],"sourcesContent":["import { create } from 'zustand';\nimport en from './en.js';\nimport es from './es.js';\nimport type { Translations, TranslationKey } from './en.js';\n\nexport type Locale = 'en' | 'es';\n\nconst locales: Record<Locale, Translations> = { en, es };\n\nfunction isLocale(s: string): s is Locale {\n return s === 'en' || s === 'es';\n}\n\nfunction detectLocale(): Locale {\n const flag = process.argv.find((a) => a.startsWith('--lang='));\n if (flag) {\n const code = flag.split('=')[1];\n if (code && isLocale(code)) return code;\n }\n const env = process.env.LANG ?? process.env.LC_ALL ?? process.env.LC_MESSAGES ?? '';\n const prefix = env.split(/[_.]/)[0] ?? '';\n if (isLocale(prefix)) return prefix;\n return 'en';\n}\n\n// ── Locale store ──\ninterface LocaleState {\n locale: Locale;\n setLocale: (locale: Locale) => void;\n}\n\nexport const useLocaleStore = create<LocaleState>((set) => ({\n locale: detectLocale(),\n setLocale: (locale) => set({ locale }),\n}));\n\nexport function getLocale(): Locale {\n return useLocaleStore.getState().locale;\n}\n\n// ── Translation function ──\nexport function t(key: TranslationKey, values?: Record<string, string | number>): string {\n const locale = useLocaleStore.getState().locale;\n let text: string = locales[locale][key] ?? locales['en'][key] ?? key;\n if (values) {\n for (const [k, v] of Object.entries(values)) {\n text = text.replaceAll(`{{${k}}}`, String(v));\n }\n }\n return text;\n}\n\n// ── Plural helper ──\nexport function tp(baseKey: string, count: number, values?: Record<string, string | number>): string {\n const suffix = count === 1 ? '_one' : '_other';\n return t(`${baseKey}${suffix}` as TranslationKey, { count, ...values });\n}\n\nexport type { TranslationKey, Translations };\n","const en = {\n // ── App chrome ──\n app_title: 'Brew-TUI',\n pro_badge: 'PRO',\n app_version: 'Brew-TUI v{{version}}',\n\n // ── View labels (header tab bar) ──\n view_dashboard: 'Dashboard',\n view_installed: 'Installed',\n view_search: 'Search',\n view_outdated: 'Outdated',\n view_packageInfo: 'Pkg Info',\n view_services: 'Services',\n view_doctor: 'Doctor',\n view_profiles: 'Profiles',\n view_smartCleanup: 'Cleanup',\n view_history: 'History',\n view_securityAudit: 'Security',\n view_account: 'Account',\n\n // ── Keyboard hint actions ──\n hint_navigate: 'navigate',\n hint_next: 'next',\n hint_quit: 'quit',\n hint_filter: 'filter',\n hint_info: 'info',\n hint_toggle: 'toggle',\n hint_typeToSearch: 'type to search',\n hint_install: 'install',\n hint_uninstall: 'uninstall',\n hint_upgrade: 'upgrade',\n hint_upgradeAll: 'upgrade all',\n hint_back: 'back',\n hint_start: 'start',\n hint_stop: 'stop',\n hint_restart: 'restart',\n hint_refresh: 'refresh',\n hint_new: 'new',\n hint_details: 'details',\n hint_import: 'import',\n hint_delete: 'delete',\n hint_clean: 'clean',\n hint_all: 'all',\n hint_search: 'search',\n hint_clear: 'clear',\n hint_scan: 'scan',\n hint_expand: 'expand',\n hint_cancel: 'cancel',\n hint_force: 'force uninstall (ignore deps)',\n hint_rescan: 'rescan',\n hint_deactivate: 'deactivate',\n hint_promo: 'promo code',\n hint_importProfile: 'import this profile',\n hint_lang: 'lang',\n hint_replay: 'replay',\n hint_edit: 'edit',\n hint_pin: 'pin/unpin',\n\n // ── Loading / progress ──\n loading_default: 'Loading...',\n loading_fetchingBrew: 'Fetching Homebrew data...',\n loading_installed: 'Loading installed packages...',\n loading_outdated: 'Checking for outdated packages...',\n loading_services: 'Loading services...',\n loading_doctor: 'Running brew doctor... (this may take a moment)',\n loading_profiles: 'Loading profiles...',\n loading_cleanup: 'Analyzing packages... (checking disk usage)',\n loading_history: 'Loading history...',\n loading_security: 'Scanning packages against OSV vulnerability database...',\n loading_searching: 'Searching...',\n loading_package: 'Loading {{name}}...',\n\n // ── Confirm dialog ──\n confirm_yes: '[Y]es',\n confirm_no: '[N]o',\n\n // ── Error ──\n error_prefix: 'Error: ',\n\n // ── Common ──\n common_andMore: '...and {{count}} more',\n common_exit: '(exit {{code}})',\n common_yes: 'yes',\n common_no: 'no',\n\n // ── Relative time ──\n time_justNow: 'just now',\n time_minutesAgo: '{{n}}m ago',\n time_hoursAgo: '{{n}}h ago',\n time_daysAgo: '{{n}}d ago',\n time_monthsAgo: '{{n}}mo ago',\n\n // ── Badges ──\n badge_outdated: 'outdated',\n badge_pinned: 'pinned',\n badge_kegOnly: 'keg-only',\n badge_dep: 'dep',\n badge_installed: 'installed',\n badge_deprecated: 'deprecated',\n badge_ok: 'ok',\n badge_fail: 'fail',\n badge_error: 'error',\n\n // ── Dashboard ──\n dashboard_overview: 'Overview',\n dashboard_formulae: 'Formulae',\n dashboard_casks: 'Casks',\n dashboard_outdated: 'Outdated',\n dashboard_services: 'Services',\n dashboard_systemInfo: 'System Info',\n dashboard_homebrew: 'Homebrew:',\n dashboard_prefix: 'Prefix:',\n dashboard_updated: 'Updated:',\n dashboard_outdatedPackages: 'Outdated Packages',\n dashboard_serviceErrors: 'Service Errors',\n dashboard_partialData: 'Some Homebrew sections failed to load:',\n dashboard_statError: 'ERR',\n\n // ── Installed ──\n installed_formulaeCount: 'Formulae ({{count}})',\n installed_casksCount: 'Casks ({{count}})',\n installed_filterDisplay: 'Filter: \"{{query}}\" ({{count}} matches)',\n installed_noPackages: 'No packages found',\n installed_confirmUninstall: 'Uninstall {{name}}?',\n\n // ── Search ──\n search_placeholder: 'Search Homebrew packages... (enter to search)',\n search_resultsFor: 'Results for',\n search_escToClear: '(esc to clear)',\n search_installing: 'Installing package...',\n search_installComplete: 'Installation complete!',\n search_confirmInstall: 'Install {{name}}?',\n search_formulaeHeader: '=== Formulae ({{count}})',\n search_casksHeader: '=== Casks ({{count}})',\n search_noResults: 'No results found',\n search_minChars: 'Type at least 2 characters to search.',\n\n // ── Outdated ──\n outdated_title: 'Outdated Packages ({{count}})',\n outdated_upgrading: 'Upgrading...',\n outdated_upgradeComplete: 'Upgrade complete!',\n outdated_pressRefresh: '(press r to refresh)',\n outdated_upToDate: 'Everything is up to date!',\n outdated_confirmAll: 'Upgrade all {{count}} packages?',\n outdated_confirmSingle: 'Upgrade {{name}}?',\n outdated_pinned: '[pinned]',\n\n // ── Package Info ──\n pkgInfo_noPackage: 'No package selected. Go to Installed and press Enter on a package.',\n pkgInfo_notFound: 'Package not found',\n pkgInfo_installing: 'Installing {{name}}...',\n pkgInfo_uninstalling: 'Uninstalling {{name}}...',\n pkgInfo_upgrading: 'Upgrading {{name}}...',\n pkgInfo_done: 'Done!',\n pkgInfo_confirmInstall: 'install {{name}}?',\n pkgInfo_confirmUninstall: 'uninstall {{name}}?',\n pkgInfo_confirmUpgrade: 'upgrade {{name}}?',\n pkgInfo_details: 'Details',\n pkgInfo_homepage: 'Homepage:',\n pkgInfo_license: 'License:',\n pkgInfo_tap: 'Tap:',\n pkgInfo_stable: 'Stable:',\n pkgInfo_installed: 'Installed:',\n pkgInfo_bottle: 'Bottle:',\n pkgInfo_onRequest: 'On request:',\n pkgInfo_noDependency: 'no (dependency)',\n pkgInfo_dependencies: 'Dependencies ({{count}})',\n pkgInfo_caveats: 'Caveats',\n\n // ── Services ──\n services_title: 'Homebrew Services',\n services_titleCount: 'Homebrew Services ({{count}})',\n services_noServices: 'No services found',\n services_name: 'Name',\n services_status: 'Status',\n services_user: 'User',\n services_processing: 'Processing...',\n services_confirmStop: 'Stop service {{name}}?',\n services_confirmRestart: 'Restart service {{name}}?',\n\n // ── Doctor ──\n doctor_title: 'Homebrew Doctor',\n doctor_clean: 'Your system is ready to brew.',\n doctor_warningsNotCaptured: 'Doctor finished with warnings but none were captured.',\n\n // ── Profiles ──\n profiles_title: 'Package Profiles ({{count}})',\n profiles_importTitle: 'Importing profile...',\n profiles_importComplete: 'Import complete. Press any key.',\n profiles_importPartial: 'Import finished with errors. Check the log above.',\n profiles_createName: 'Create Profile \\u2014 Name:',\n profiles_namePlaceholder: 'e.g. work, personal, project-x',\n profiles_createDesc: 'Create Profile \"{{name}}\" \\u2014 Description:',\n profiles_descPlaceholder: 'Brief description of this setup',\n profiles_created: 'Created: {{date}}',\n profiles_formulaeCount: 'Formulae ({{count}})',\n profiles_casksCount: 'Casks ({{count}})',\n profiles_confirmDelete: 'Delete profile \"{{name}}\"?',\n profiles_noProfiles: 'No profiles saved yet.',\n profiles_press: 'Press',\n profiles_exportHint: 'to export your current setup as a profile.',\n profiles_editName: 'Edit Profile \\u2014 Name:',\n profiles_editDesc: 'Edit Profile \"{{name}}\" \\u2014 Description:',\n\n // ── Smart Cleanup ──\n cleanup_title: 'Smart Cleanup',\n cleanup_cleaning: 'Cleaning up...',\n cleanup_complete: 'Cleanup complete! Press r to re-analyze.',\n cleanup_orphans: 'Orphans',\n cleanup_reclaimable: 'Reclaimable',\n cleanup_selected: 'Selected',\n cleanup_confirmUninstall: 'Uninstall {{count}} packages?',\n cleanup_confirmForce: 'Some packages have dependencies. Force uninstall {{count}} packages? (ignores dependencies)',\n cleanup_depError: 'Some packages could not be removed due to dependencies.',\n cleanup_systemClean: 'No orphaned packages found. Your system is clean!',\n\n // ── History ──\n history_title: 'Action History ({{count}})',\n history_filterLabel: 'filter: {{filter}}',\n history_searchPlaceholder: 'Search packages...',\n history_confirmClear: 'Clear all {{count}} history entries?',\n history_noEntries: 'No history entries',\n history_noEntriesFor: 'No history entries for \"{{filter}}\"',\n history_all: '(all)',\n history_actionInstall: 'install',\n history_actionUninstall: 'uninstall',\n history_actionUpgrade: 'upgrade',\n history_actionUpgradeAll: 'upgrade-all',\n history_confirmReplay: 'Re-run: {{action}} {{name}}?',\n history_replayAll: 'Re-run: upgrade all packages?',\n\n // ── Security Audit ──\n security_title: 'Security Audit',\n security_scanned: 'Scanned',\n security_vulnerable: 'Vulnerable',\n security_critical: 'Critical',\n security_high: 'High',\n security_medium: 'Medium',\n security_noVulns: 'No known vulnerabilities found in your installed packages!',\n security_fixedIn: 'Fixed in: {{version}}',\n security_confirmUpgrade: 'Upgrade {{name}} to fix vulnerabilities?',\n\n // ── Account ──\n account_title: 'Account & License',\n account_confirmDeactivate: 'Deactivate your Pro license on this machine?',\n account_statusLabel: 'Status:',\n account_pro: '[Pro]',\n account_free: '[Free]',\n account_expired: '[Expired]',\n account_validating: '[Validating...]',\n account_emailLabel: 'Email:',\n account_nameLabel: 'Name:',\n account_planLabel: 'Plan:',\n account_monthlyPrice: '9\\u20AC/month',\n account_lifetimePrice: '29\\u20AC lifetime',\n account_keyLabel: 'Key:',\n account_expiresLabel: 'Expires:',\n account_activatedLabel: 'Activated:',\n account_upgradeTitle: 'Upgrade to Brew-TUI Pro',\n account_unlockDesc: 'Unlock Profiles, Smart Cleanup, History, Security Audit, and BrewBar (macOS menu bar companion).',\n account_pricing: '9\\u20AC/month or 29\\u20AC lifetime',\n account_runActivate: 'Run:',\n account_activateCmd: 'brew-tui activate <key>',\n account_licenseExpired: 'Your license has expired. Renew to continue using Pro features.',\n account_deactivating: 'Deactivating...',\n account_loading: 'Loading license status...',\n account_promoTitle: 'Redeem Promo Code',\n account_promoLabel: 'Code:',\n account_promoValidating: 'Validating promo code...',\n account_promoSuccess: 'Promo code redeemed! Pro access until {{expires}}.',\n account_promoInvalid: 'Invalid or expired promo code.',\n account_promoError: 'Could not validate promo code. Check your connection.',\n account_promoEsc: 'esc: cancel',\n account_promoHint: 'p: redeem promo code',\n\n // ── Upgrade Prompt ──\n upgrade_proFeature: '{{title}} \\u2014 Pro Feature',\n upgrade_profiles: 'Package Profiles',\n upgrade_profilesDesc: 'Export and import your Homebrew setup across machines. Save named profiles for work, personal, or project-specific configurations.',\n upgrade_cleanup: 'Smart Cleanup',\n upgrade_cleanupDesc: 'Find orphaned packages, analyze disk usage per package, and reclaim disk space with one-click intelligent cleanup.',\n upgrade_history: 'Action History',\n upgrade_historyDesc: 'Track every install, uninstall, and upgrade with timestamps. Search and filter your package management history.',\n upgrade_security: 'Security Audit',\n upgrade_securityDesc: 'Scan installed packages against known vulnerabilities (CVEs). See severity levels, affected versions, and available fixes.',\n upgrade_pricing: '9\\u20AC/month or 29\\u20AC lifetime',\n upgrade_buyAt: 'Buy at:',\n upgrade_buyUrl: 'https://buy.polar.sh/polar_cl_QW1ZJ9887bU74drGr7JfujQfm3RKYnn1fuvc53DqD6D',\n upgrade_activateWith: 'Then activate with:',\n upgrade_activateCmd: 'brew-tui activate <your-license-key>',\n upgrade_proLabel: 'Brew-TUI Pro \\u2014 9\\u20AC/month or 29\\u20AC lifetime \\u2014 Includes BrewBar for macOS',\n\n // ── Progress Log ──\n progress_noOutput: 'No output yet',\n\n // ── Search Input ──\n searchInput_placeholder: 'Type to filter...',\n\n // ── Profile Manager ──\n profileMgr_tapping: 'Tapping {{name}}...',\n profileMgr_installing: 'Installing {{name}}...',\n profileMgr_installingCask: 'Installing cask {{name}}...',\n profileMgr_importDone: 'Done! Installed {{count}} packages.',\n\n // ── CLI ──\n cli_usageActivate: 'Usage: brew-tui activate <license-key>',\n cli_activated: '\\u2714 Pro activated for {{email}}',\n cli_plan: ' Plan: {{plan}}',\n cli_expires: ' Expires: {{date}}',\n cli_activationFailed: '\\u2718 Activation failed: {{error}}',\n cli_noLicense: 'No active license found.',\n cli_deactivated: '\\u2714 License deactivated.',\n cli_planFree: 'Plan: Free',\n cli_planPro: 'Plan: Pro',\n cli_planExpired: 'Plan: Expired',\n cli_confirmDeactivate: 'Deactivate your Pro license on this machine? (y/N): ',\n cli_deactivateCancelled: 'Deactivation cancelled.',\n cli_upgradeHint: 'Run `brew-tui activate <key>` to upgrade to Pro.',\n cli_revalidateHint: 'Run `brew-tui revalidate` to refresh your current license.',\n cli_email: 'Email: {{email}}',\n cli_status: 'Status: {{status}}',\n cli_revalidated: '\\u2714 License revalidated.',\n cli_revalidateGrace: '\\u26A0 Could not reach the server. Your current license remains usable within the offline grace period.',\n cli_revalidateFailed: '\\u2718 License revalidation failed. Renew your subscription or activate a valid key.',\n cli_rateLimited: 'Too many activation attempts. Try again in {{minutes}} minutes.',\n cli_cooldown: 'Please wait before trying again.',\n cli_brewbarInstalling: 'Downloading BrewBar...',\n cli_brewbarInstalled: '\\u2714 BrewBar installed to /Applications/BrewBar.app',\n cli_brewbarAlreadyInstalled: 'BrewBar is already installed. Use --force to reinstall.',\n cli_brewbarUninstalled: '\\u2714 BrewBar removed from /Applications.',\n cli_brewbarNotInstalled: 'BrewBar is not installed.',\n cli_brewbarProRequired: '\\u2718 BrewBar requires a Pro license.\\n Run: brew-tui activate <key>',\n cli_brewbarRevalidateRequired: '\\u2718 BrewBar requires a valid Pro license.\\n Run: brew-tui revalidate',\n cli_brewbarMacOnly: '\\u2718 BrewBar is only available on macOS.',\n cli_brewbarDownloadFailed: '\\u2718 Failed to download BrewBar: {{error}}',\n cli_deactivateRemoteFailed: '\\u26A0 Warning: Could not reach the server to deactivate remotely. The license was removed locally but may still count as active.',\n\n // ── License degradation (Layer 15) ──\n license_offlineWarning: 'Your license has not been validated for {{days}} days. Please connect to the internet.',\n\n // ── Plurals ──\n plural_vulns_one: '({{count}} vuln)',\n plural_vulns_other: '({{count}} vulns)',\n plural_warnings_one: '{{count}} warning',\n plural_warnings_other: '{{count}} warnings',\n\n // ── Scroll indicators ──\n scroll_moreAbove: '\\u2191 {{count}} more',\n scroll_moreBelow: '\\u2193 {{count}} more',\n\n // ── SCR-001: Cleanup warning ──\n cleanup_warning_system_tools: 'Warning: detected orphans may include dependencies of tools not managed by Homebrew. Review the list before proceeding.',\n\n // ── SCR-002: Installed column headers ──\n installed_col_package: 'Package',\n installed_col_version: 'Version',\n installed_col_status: 'Status',\n\n // ── SCR-003: Search failed ──\n search_failed: 'Search failed',\n\n // ── SCR-007: Deactivate failed ──\n deactivate_failed: 'Deactivation failed',\n\n // ── ACC-005: Version labels ──\n version_installed: 'installed:',\n version_available: 'available:',\n\n // ── SCR-006: Upgrade-all replay warning ──\n upgrade_all_warning: 'Note: this will upgrade all currently outdated packages, which may differ from the original set.',\n\n // ── SEG-007: Delete account ──\n delete_account_confirm: 'Delete all Brew-TUI data (~/.brew-tui)? This removes your license, profiles, and history. This cannot be undone.',\n delete_account_success: 'All Brew-TUI data has been removed.',\n\n // ── SCR-012: Upgrade All packages list ──\n outdated_upgradeAllList: 'Packages to upgrade: {{list}}',\n\n // ── SCR-005: Profile import summary ──\n profiles_importSummary: 'This profile contains {{formulae}} formulae and {{casks}} casks. Continue?',\n\n // ── SCR-017: Network error ��─\n security_networkError: 'Could not reach OSV.dev vulnerability database. Check your internet connection.',\n\n // ── ARQ-004: Dashboard last updated ──\n dashboard_lastUpdated: 'Last updated: {{time}}',\n\n // ── SCR-014: Services last error ──\n services_lastError: 'Last error: {{error}}',\n\n // ── SCR-010: Generic network error ──\n error_network: 'Network error: unable to reach the server.',\n\n // ── ARQ-005: Security cache ──\n security_cachedResults: 'Showing cached results ({{time}} ago). Press r to rescan.',\n};\n\nexport default en;\nexport type Translations = { [K in keyof typeof en]: string };\nexport type TranslationKey = keyof typeof en;\n","import type { Translations } from './en.js';\n\nconst es: Translations = {\n // ── App chrome ──\n app_title: 'Brew-TUI',\n pro_badge: 'PRO',\n app_version: 'Brew-TUI v{{version}}',\n\n // ── View labels (header tab bar) ──\n view_dashboard: 'Inicio',\n view_installed: 'Instalados',\n view_search: 'Buscar',\n view_outdated: 'Desactual.',\n view_packageInfo: 'Info Paq.',\n view_services: 'Servicios',\n view_doctor: 'Doctor',\n view_profiles: 'Perfiles',\n view_smartCleanup: 'Limpieza',\n view_history: 'Historial',\n view_securityAudit: 'Seguridad',\n view_account: 'Cuenta',\n\n // ── Keyboard hint actions ──\n hint_navigate: 'navegar',\n hint_next: 'siguiente',\n hint_quit: 'salir',\n hint_filter: 'filtrar',\n hint_info: 'info',\n hint_toggle: 'cambiar',\n hint_typeToSearch: 'escriba para buscar',\n hint_install: 'instalar',\n hint_uninstall: 'desinstalar',\n hint_upgrade: 'actualizar',\n hint_upgradeAll: 'actualizar todo',\n hint_back: 'volver',\n hint_start: 'iniciar',\n hint_stop: 'detener',\n hint_restart: 'reiniciar',\n hint_refresh: 'refrescar',\n hint_new: 'nuevo',\n hint_details: 'detalles',\n hint_import: 'importar',\n hint_delete: 'eliminar',\n hint_clean: 'limpiar',\n hint_all: 'todo',\n hint_search: 'buscar',\n hint_clear: 'borrar',\n hint_scan: 'escanear',\n hint_expand: 'expandir',\n hint_cancel: 'cancelar',\n hint_force: 'forzar (ignorar deps)',\n hint_rescan: 're-escanear',\n hint_deactivate: 'desactivar',\n hint_promo: 'c\\u00F3digo promo',\n hint_importProfile: 'importar este perfil',\n hint_lang: 'idioma',\n hint_replay: 'repetir',\n hint_edit: 'editar',\n hint_pin: 'fijar/desfijar',\n\n // ── Loading / progress ──\n loading_default: 'Cargando...',\n loading_fetchingBrew: 'Obteniendo datos de Homebrew...',\n loading_installed: 'Cargando paquetes instalados...',\n loading_outdated: 'Buscando paquetes desactualizados...',\n loading_services: 'Cargando servicios...',\n loading_doctor: 'Ejecutando brew doctor... (puede tardar un momento)',\n loading_profiles: 'Cargando perfiles...',\n loading_cleanup: 'Analizando paquetes... (verificando uso de disco)',\n loading_history: 'Cargando historial...',\n loading_security: 'Escaneando paquetes en la base de datos de vulnerabilidades OSV...',\n loading_searching: 'Buscando...',\n loading_package: 'Cargando {{name}}...',\n\n // ── Confirm dialog ──\n confirm_yes: '[S]\\u00ED',\n confirm_no: '[N]o',\n\n // ── Error ──\n error_prefix: 'Error: ',\n\n // ── Common ──\n common_andMore: '...y {{count}} m\\u00E1s',\n common_exit: '(salida {{code}})',\n common_yes: 's\\u00ED',\n common_no: 'no',\n\n // ── Relative time ──\n time_justNow: 'ahora',\n time_minutesAgo: 'hace {{n}}m',\n time_hoursAgo: 'hace {{n}}h',\n time_daysAgo: 'hace {{n}}d',\n time_monthsAgo: 'hace {{n}}me',\n\n // ── Badges ──\n badge_outdated: 'desactualizado',\n badge_pinned: 'fijado',\n badge_kegOnly: 'keg-only',\n badge_dep: 'dep',\n badge_installed: 'instalado',\n badge_deprecated: 'obsoleto',\n badge_ok: 'ok',\n badge_fail: 'fallo',\n badge_error: 'error',\n\n // ── Dashboard ──\n dashboard_overview: 'Resumen',\n dashboard_formulae: 'Formulae',\n dashboard_casks: 'Casks',\n dashboard_outdated: 'Desactualizados',\n dashboard_services: 'Servicios',\n dashboard_systemInfo: 'Info del Sistema',\n dashboard_homebrew: 'Homebrew:',\n dashboard_prefix: 'Prefijo:',\n dashboard_updated: 'Actualizado:',\n dashboard_outdatedPackages: 'Paquetes Desactualizados',\n dashboard_serviceErrors: 'Errores de Servicios',\n dashboard_partialData: 'Algunas secciones de Homebrew no pudieron cargarse:',\n dashboard_statError: 'ERR',\n\n // ── Installed ──\n installed_formulaeCount: 'Formulae ({{count}})',\n installed_casksCount: 'Casks ({{count}})',\n installed_filterDisplay: 'Filtro: \"{{query}}\" ({{count}} coincidencias)',\n installed_noPackages: 'No se encontraron paquetes',\n installed_confirmUninstall: '\\u00BFDesinstalar {{name}}?',\n\n // ── Search ──\n search_placeholder: 'Buscar paquetes Homebrew... (enter para buscar)',\n search_resultsFor: 'Resultados para',\n search_escToClear: '(esc para limpiar)',\n search_installing: 'Instalando paquete...',\n search_installComplete: '\\u00A1Instalaci\\u00F3n completa!',\n search_confirmInstall: '\\u00BFInstalar {{name}}?',\n search_formulaeHeader: '=== Formulae ({{count}})',\n search_casksHeader: '=== Casks ({{count}})',\n search_noResults: 'Sin resultados',\n search_minChars: 'Escribe al menos 2 caracteres para buscar.',\n\n // ── Outdated ──\n outdated_title: 'Paquetes Desactualizados ({{count}})',\n outdated_upgrading: 'Actualizando...',\n outdated_upgradeComplete: '\\u00A1Actualizaci\\u00F3n completa!',\n outdated_pressRefresh: '(presiona r para refrescar)',\n outdated_upToDate: '\\u00A1Todo est\\u00E1 al d\\u00EDa!',\n outdated_confirmAll: '\\u00BFActualizar los {{count}} paquetes?',\n outdated_confirmSingle: '\\u00BFActualizar {{name}}?',\n outdated_pinned: '[fijado]',\n\n // ── Package Info ──\n pkgInfo_noPackage: 'Ning\\u00FAn paquete seleccionado. Ve a Instalados y presiona Enter en un paquete.',\n pkgInfo_notFound: 'Paquete no encontrado',\n pkgInfo_installing: 'Instalando {{name}}...',\n pkgInfo_uninstalling: 'Desinstalando {{name}}...',\n pkgInfo_upgrading: 'Actualizando {{name}}...',\n pkgInfo_done: '\\u00A1Listo!',\n pkgInfo_confirmInstall: '\\u00BFinstalar {{name}}?',\n pkgInfo_confirmUninstall: '\\u00BFdesinstalar {{name}}?',\n pkgInfo_confirmUpgrade: '\\u00BFactualizar {{name}}?',\n pkgInfo_details: 'Detalles',\n pkgInfo_homepage: 'Web:',\n pkgInfo_license: 'Licencia:',\n pkgInfo_tap: 'Tap:',\n pkgInfo_stable: 'Estable:',\n pkgInfo_installed: 'Instalado:',\n pkgInfo_bottle: 'Bottle:',\n pkgInfo_onRequest: 'Por solicitud:',\n pkgInfo_noDependency: 'no (dependencia)',\n pkgInfo_dependencies: 'Dependencias ({{count}})',\n pkgInfo_caveats: 'Advertencias',\n\n // ── Services ──\n services_title: 'Servicios Homebrew',\n services_titleCount: 'Servicios Homebrew ({{count}})',\n services_noServices: 'No se encontraron servicios',\n services_name: 'Nombre',\n services_status: 'Estado',\n services_user: 'Usuario',\n services_processing: 'Procesando...',\n services_confirmStop: '\\u00BFDetener servicio {{name}}?',\n services_confirmRestart: '\\u00BFReiniciar servicio {{name}}?',\n\n // ── Doctor ──\n doctor_title: 'Homebrew Doctor',\n doctor_clean: 'Tu sistema est\\u00E1 listo para brew.',\n doctor_warningsNotCaptured: 'Doctor termin\\u00F3 con advertencias pero no se capturaron.',\n\n // ── Profiles ──\n profiles_title: 'Perfiles de Paquetes ({{count}})',\n profiles_importTitle: 'Importando perfil...',\n profiles_importComplete: 'Importaci\\u00F3n completa. Presiona cualquier tecla.',\n profiles_importPartial: 'Importaci\\u00F3n finalizada con errores. Revisa el registro arriba.',\n profiles_createName: 'Crear Perfil \\u2014 Nombre:',\n profiles_namePlaceholder: 'ej. trabajo, personal, proyecto-x',\n profiles_createDesc: 'Crear Perfil \"{{name}}\" \\u2014 Descripci\\u00F3n:',\n profiles_descPlaceholder: 'Breve descripci\\u00F3n de esta configuraci\\u00F3n',\n profiles_created: 'Creado: {{date}}',\n profiles_formulaeCount: 'Formulae ({{count}})',\n profiles_casksCount: 'Casks ({{count}})',\n profiles_confirmDelete: '\\u00BFEliminar perfil \"{{name}}\"?',\n profiles_noProfiles: 'A\\u00FAn no hay perfiles guardados.',\n profiles_press: 'Presiona',\n profiles_exportHint: 'para exportar tu configuraci\\u00F3n actual como perfil.',\n profiles_editName: 'Editar Perfil \\u2014 Nombre:',\n profiles_editDesc: 'Editar Perfil \"{{name}}\" \\u2014 Descripci\\u00F3n:',\n\n // ── Smart Cleanup ──\n cleanup_title: 'Limpieza Inteligente',\n cleanup_cleaning: 'Limpiando...',\n cleanup_complete: '\\u00A1Limpieza completa! Presiona r para re-analizar.',\n cleanup_orphans: 'Hu\\u00E9rfanos',\n cleanup_reclaimable: 'Recuperable',\n cleanup_selected: 'Seleccionados',\n cleanup_confirmUninstall: '\\u00BFDesinstalar {{count}} paquetes?',\n cleanup_confirmForce: 'Algunos paquetes tienen dependencias. \\u00BFForzar desinstalaci\\u00F3n de {{count}} paquetes? (ignora dependencias)',\n cleanup_depError: 'Algunos paquetes no pudieron eliminarse por dependencias.',\n cleanup_systemClean: '\\u00A1No se encontraron paquetes hu\\u00E9rfanos. Tu sistema est\\u00E1 limpio!',\n\n // ── History ──\n history_title: 'Historial de Acciones ({{count}})',\n history_filterLabel: 'filtro: {{filter}}',\n history_searchPlaceholder: 'Buscar paquetes...',\n history_confirmClear: '\\u00BFBorrar las {{count}} entradas del historial?',\n history_noEntries: 'Sin entradas en el historial',\n history_noEntriesFor: 'Sin entradas en el historial para \"{{filter}}\"',\n history_all: '(todos)',\n history_actionInstall: 'instalar',\n history_actionUninstall: 'desinstalar',\n history_actionUpgrade: 'actualizar',\n history_actionUpgradeAll: 'actualizar-todo',\n history_confirmReplay: '\\u00BFRe-ejecutar: {{action}} {{name}}?',\n history_replayAll: '\\u00BFRe-ejecutar: actualizar todos los paquetes?',\n\n // ── Security Audit ──\n security_title: 'Auditor\\u00EDa de Seguridad',\n security_scanned: 'Escaneados',\n security_vulnerable: 'Vulnerables',\n security_critical: 'Cr\\u00EDticos',\n security_high: 'Altos',\n security_medium: 'Medios',\n security_noVulns: '\\u00A1No se encontraron vulnerabilidades conocidas en tus paquetes instalados!',\n security_fixedIn: 'Corregido en: {{version}}',\n security_confirmUpgrade: '\\u00BFActualizar {{name}} para corregir vulnerabilidades?',\n\n // ── Account ──\n account_title: 'Cuenta y Licencia',\n account_confirmDeactivate: '\\u00BFDesactivar tu licencia Pro en esta m\\u00E1quina?',\n account_statusLabel: 'Estado:',\n account_pro: '[Pro]',\n account_free: '[Gratis]',\n account_expired: '[Expirada]',\n account_validating: '[Validando...]',\n account_emailLabel: 'Email:',\n account_nameLabel: 'Nombre:',\n account_planLabel: 'Plan:',\n account_monthlyPrice: '9\\u20AC/mes',\n account_lifetimePrice: '29\\u20AC de por vida',\n account_keyLabel: 'Clave:',\n account_expiresLabel: 'Expira:',\n account_activatedLabel: 'Activado:',\n account_upgradeTitle: 'Actualiza a Brew-TUI Pro',\n account_unlockDesc: 'Desbloquea Perfiles, Limpieza Inteligente, Historial, Auditor\\u00EDa de Seguridad y BrewBar (barra de men\\u00FA macOS).',\n account_pricing: '9\\u20AC/mes o 29\\u20AC de por vida',\n account_runActivate: 'Ejecuta:',\n account_activateCmd: 'brew-tui activate <clave>',\n account_licenseExpired: 'Tu licencia ha expirado. Renueva para seguir usando las funciones Pro.',\n account_deactivating: 'Desactivando...',\n account_loading: 'Cargando estado de la licencia...',\n account_promoTitle: 'Canjear C\\u00F3digo Promocional',\n account_promoLabel: 'C\\u00F3digo:',\n account_promoValidating: 'Validando c\\u00F3digo promocional...',\n account_promoSuccess: '\\u00A1C\\u00F3digo canjeado! Acceso Pro hasta {{expires}}.',\n account_promoInvalid: 'C\\u00F3digo inv\\u00E1lido o expirado.',\n account_promoError: 'No se pudo validar el c\\u00F3digo. Comprueba tu conexi\\u00F3n.',\n account_promoEsc: 'esc: cancelar',\n account_promoHint: 'p: canjear c\\u00F3digo promocional',\n\n // ── Upgrade Prompt ──\n upgrade_proFeature: '{{title}} \\u2014 Funci\\u00F3n Pro',\n upgrade_profiles: 'Perfiles de Paquetes',\n upgrade_profilesDesc: 'Exporta e importa tu configuraci\\u00F3n de Homebrew entre m\\u00E1quinas. Guarda perfiles con nombre para trabajo, personal o proyectos espec\\u00EDficos.',\n upgrade_cleanup: 'Limpieza Inteligente',\n upgrade_cleanupDesc: 'Encuentra paquetes hu\\u00E9rfanos, analiza uso de disco por paquete y recupera espacio con limpieza inteligente de un clic.',\n upgrade_history: 'Historial de Acciones',\n upgrade_historyDesc: 'Rastrea cada instalaci\\u00F3n, desinstalaci\\u00F3n y actualizaci\\u00F3n con marcas de tiempo. Busca y filtra tu historial de gesti\\u00F3n de paquetes.',\n upgrade_security: 'Auditor\\u00EDa de Seguridad',\n upgrade_securityDesc: 'Escanea paquetes instalados contra vulnerabilidades conocidas (CVEs). Ve niveles de severidad, versiones afectadas y correcciones disponibles.',\n upgrade_pricing: '9\\u20AC/mes o 29\\u20AC de por vida',\n upgrade_buyAt: 'Compra en:',\n upgrade_buyUrl: 'https://buy.polar.sh/polar_cl_QW1ZJ9887bU74drGr7JfujQfm3RKYnn1fuvc53DqD6D',\n upgrade_activateWith: 'Luego activa con:',\n upgrade_activateCmd: 'brew-tui activate <tu-clave-de-licencia>',\n upgrade_proLabel: 'Brew-TUI Pro \\u2014 9\\u20AC/mes o 29\\u20AC de por vida \\u2014 Incluye BrewBar para macOS',\n\n // ── Progress Log ──\n progress_noOutput: 'Sin salida a\\u00FAn',\n\n // ── Search Input ──\n searchInput_placeholder: 'Escriba para filtrar...',\n\n // ── Profile Manager ──\n profileMgr_tapping: 'A\\u00F1adiendo tap {{name}}...',\n profileMgr_installing: 'Instalando {{name}}...',\n profileMgr_installingCask: 'Instalando cask {{name}}...',\n profileMgr_importDone: '\\u00A1Listo! {{count}} paquetes instalados.',\n\n // ── CLI ──\n cli_usageActivate: 'Uso: brew-tui activate <clave-de-licencia>',\n cli_activated: '\\u2714 Pro activado para {{email}}',\n cli_plan: ' Plan: {{plan}}',\n cli_expires: ' Expira: {{date}}',\n cli_activationFailed: '\\u2718 Activaci\\u00F3n fallida: {{error}}',\n cli_noLicense: 'No se encontr\\u00F3 licencia activa.',\n cli_deactivated: '\\u2714 Licencia desactivada.',\n cli_planFree: 'Plan: Gratis',\n cli_planPro: 'Plan: Pro',\n cli_planExpired: 'Plan: Expirada',\n cli_confirmDeactivate: '\\u00BFDesactivar tu licencia Pro en esta m\\u00E1quina? (s/N): ',\n cli_deactivateCancelled: 'Desactivaci\\u00F3n cancelada.',\n cli_upgradeHint: 'Ejecuta `brew-tui activate <clave>` para actualizar a Pro.',\n cli_revalidateHint: 'Ejecuta `brew-tui revalidate` para refrescar tu licencia actual.',\n cli_email: 'Email: {{email}}',\n cli_status: 'Estado: {{status}}',\n cli_revalidated: '\\u2714 Licencia revalidada.',\n cli_revalidateGrace: '\\u26A0 No se pudo contactar al servidor. Tu licencia actual sigue siendo usable dentro del periodo de gracia offline.',\n cli_revalidateFailed: '\\u2718 La revalidaci\\u00F3n de la licencia fall\\u00F3. Renueva tu suscripci\\u00F3n o activa una clave v\\u00E1lida.',\n cli_rateLimited: 'Demasiados intentos de activaci\\u00F3n. Int\\u00E9ntalo en {{minutes}} minutos.',\n cli_cooldown: 'Por favor espera antes de intentar de nuevo.',\n cli_brewbarInstalling: 'Descargando BrewBar...',\n cli_brewbarInstalled: '\\u2714 BrewBar instalado en /Applications/BrewBar.app',\n cli_brewbarAlreadyInstalled: 'BrewBar ya est\\u00E1 instalado. Usa --force para reinstalar.',\n cli_brewbarUninstalled: '\\u2714 BrewBar eliminado de /Applications.',\n cli_brewbarNotInstalled: 'BrewBar no est\\u00E1 instalado.',\n cli_brewbarProRequired: '\\u2718 BrewBar requiere una licencia Pro.\\n Ejecuta: brew-tui activate <clave>',\n cli_brewbarRevalidateRequired: '\\u2718 BrewBar requiere una licencia Pro v\\u00E1lida.\\n Ejecuta: brew-tui revalidate',\n cli_brewbarMacOnly: '\\u2718 BrewBar solo est\\u00E1 disponible en macOS.',\n cli_brewbarDownloadFailed: '\\u2718 Error al descargar BrewBar: {{error}}',\n cli_deactivateRemoteFailed: '\\u26A0 Advertencia: No se pudo contactar al servidor para desactivar remotamente. La licencia se elimin\\u00F3 localmente pero puede seguir contando como activa.',\n\n // ── License degradation (Layer 15) ──\n license_offlineWarning: 'Tu licencia no se ha validado en {{days}} d\\u00EDas. Por favor con\\u00E9ctate a internet.',\n\n // ── Plurals ──\n plural_vulns_one: '({{count}} vuln)',\n plural_vulns_other: '({{count}} vulns)',\n plural_warnings_one: '{{count}} advertencia',\n plural_warnings_other: '{{count}} advertencias',\n\n // ── Scroll indicators ──\n scroll_moreAbove: '\\u2191 {{count}} m\\u00E1s',\n scroll_moreBelow: '\\u2193 {{count}} m\\u00E1s',\n\n // ── SCR-001: Cleanup warning ──\n cleanup_warning_system_tools: 'Advertencia: los hu\\u00E9rfanos detectados pueden incluir dependencias de herramientas no gestionadas por Homebrew. Revisa la lista antes de continuar.',\n\n // ── SCR-002: Installed column headers ──\n installed_col_package: 'Paquete',\n installed_col_version: 'Versi\\u00F3n',\n installed_col_status: 'Estado',\n\n // ── SCR-003: Search failed ──\n search_failed: 'B\\u00FAsqueda fallida',\n\n // ── SCR-007: Deactivate failed ──\n deactivate_failed: 'Error al desactivar',\n\n // ── ACC-005: Version labels ──\n version_installed: 'instalado:',\n version_available: 'disponible:',\n\n // ── SCR-006: Upgrade-all replay warning ──\n upgrade_all_warning: 'Nota: esto actualizar\\u00E1 todos los paquetes desactualizados actualmente, que pueden diferir del conjunto original.',\n\n // ── SEG-007: Delete account ──\n delete_account_confirm: '\\u00BFEliminar todos los datos de Brew-TUI (~/.brew-tui)? Esto elimina tu licencia, perfiles e historial. Esta acci\\u00F3n no se puede deshacer.',\n delete_account_success: 'Todos los datos de Brew-TUI han sido eliminados.',\n\n // ── SCR-012: Upgrade All packages list ──\n outdated_upgradeAllList: 'Paquetes a actualizar: {{list}}',\n\n // ── SCR-005: Profile import summary ──\n profiles_importSummary: 'Este perfil contiene {{formulae}} formulae y {{casks}} casks. \\u00BFContinuar?',\n\n // ── SCR-017: Network error ──\n security_networkError: 'No se pudo conectar con la base de datos de vulnerabilidades OSV.dev. Verifica tu conexi\\u00F3n a internet.',\n\n // ── ARQ-004: Dashboard last updated ──\n dashboard_lastUpdated: '\\u00DAltima actualizaci\\u00F3n: {{time}}',\n\n // ── SCR-014: Services last error ──\n services_lastError: '\\u00DAltimo error: {{error}}',\n\n // ── SCR-010: Generic network error ──\n error_network: 'Error de red: no se puede conectar con el servidor.',\n\n // ── ARQ-005: Security cache ──\n security_cachedResults: 'Mostrando resultados en cach\\u00E9 (hace {{time}}). Presiona r para re-escanear.',\n};\n\nexport default es;\n","type LogLevel = 'debug' | 'info' | 'warn' | 'error';\nconst LOG_LEVELS: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };\nconst currentLevel: LogLevel = (process.env.LOG_LEVEL as LogLevel) || 'warn';\n\nfunction shouldLog(level: LogLevel): boolean {\n return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];\n}\n\nexport const logger = {\n debug: (msg: string, ctx?: Record<string, unknown>) => shouldLog('debug') && console.debug(`[DEBUG] ${msg}`, ctx || ''),\n info: (msg: string, ctx?: Record<string, unknown>) => shouldLog('info') && console.info(`[INFO] ${msg}`, ctx || ''),\n warn: (msg: string, ctx?: Record<string, unknown>) => shouldLog('warn') && console.warn(`[WARN] ${msg}`, ctx || ''),\n error: (msg: string, ctx?: Record<string, unknown>) => shouldLog('error') && console.error(`[ERROR] ${msg}`, ctx || ''),\n};\n","import { logger } from '../utils/logger.js';\n\nexport function fetchWithTimeout(url: string, options: RequestInit = {}, timeoutMs = 15_000): Promise<Response> {\n return fetch(url, { ...options, signal: AbortSignal.timeout(timeoutMs) });\n}\n\n/**\n * Wrap an async function with debug-level latency logging.\n */\nexport function timed<T>(label: string, fn: () => Promise<T>): Promise<T> {\n const start = Date.now();\n return fn().finally(() => logger.debug(`${label} took ${Date.now() - start}ms`));\n}\n"],"mappings":";AAAA,SAAS,cAAc;;;ACAvB,IAAM,KAAK;AAAA;AAAA,EAET,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA;AAAA,EAGb,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,aAAa;AAAA,EACb,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,cAAc;AAAA;AAAA,EAGd,eAAe;AAAA,EACf,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA,EACb,WAAW;AAAA,EACX,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,UAAU;AAAA,EACV,cAAc;AAAA,EACd,aAAa;AAAA,EACb,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX,aAAa;AAAA,EACb,WAAW;AAAA,EACX,UAAU;AAAA;AAAA,EAGV,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA;AAAA,EAGjB,aAAa;AAAA,EACb,YAAY;AAAA;AAAA,EAGZ,cAAc;AAAA;AAAA,EAGd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,WAAW;AAAA;AAAA,EAGX,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,cAAc;AAAA,EACd,gBAAgB;AAAA;AAAA,EAGhB,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,eAAe;AAAA,EACf,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,aAAa;AAAA;AAAA,EAGb,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,4BAA4B;AAAA,EAC5B,yBAAyB;AAAA,EACzB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA;AAAA,EAGrB,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,4BAA4B;AAAA;AAAA,EAG5B,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,wBAAwB;AAAA,EACxB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA;AAAA,EAGjB,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,0BAA0B;AAAA,EAC1B,uBAAuB;AAAA,EACvB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,iBAAiB;AAAA;AAAA,EAGjB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,wBAAwB;AAAA,EACxB,0BAA0B;AAAA,EAC1B,wBAAwB;AAAA,EACxB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA;AAAA,EAGjB,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA;AAAA,EAGzB,cAAc;AAAA,EACd,cAAc;AAAA,EACd,4BAA4B;AAAA;AAAA,EAG5B,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,qBAAqB;AAAA,EACrB,0BAA0B;AAAA,EAC1B,qBAAqB;AAAA,EACrB,0BAA0B;AAAA,EAC1B,kBAAkB;AAAA,EAClB,wBAAwB;AAAA,EACxB,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,qBAAqB;AAAA,EACrB,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA;AAAA,EAGnB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,0BAA0B;AAAA,EAC1B,sBAAsB;AAAA,EACtB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA;AAAA,EAGrB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,2BAA2B;AAAA,EAC3B,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,aAAa;AAAA,EACb,uBAAuB;AAAA,EACvB,yBAAyB;AAAA,EACzB,uBAAuB;AAAA,EACvB,0BAA0B;AAAA,EAC1B,uBAAuB;AAAA,EACvB,mBAAmB;AAAA;AAAA,EAGnB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,yBAAyB;AAAA;AAAA,EAGzB,eAAe;AAAA,EACf,2BAA2B;AAAA,EAC3B,qBAAqB;AAAA,EACrB,aAAa;AAAA,EACb,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,uBAAuB;AAAA,EACvB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,wBAAwB;AAAA,EACxB,sBAAsB;AAAA,EACtB,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA;AAAA,EAGnB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA;AAAA,EAGlB,mBAAmB;AAAA;AAAA,EAGnB,yBAAyB;AAAA;AAAA,EAGzB,oBAAoB;AAAA,EACpB,uBAAuB;AAAA,EACvB,2BAA2B;AAAA,EAC3B,uBAAuB;AAAA;AAAA,EAGvB,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,UAAU;AAAA,EACV,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,uBAAuB;AAAA,EACvB,yBAAyB;AAAA,EACzB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,uBAAuB;AAAA,EACvB,sBAAsB;AAAA,EACtB,6BAA6B;AAAA,EAC7B,wBAAwB;AAAA,EACxB,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,+BAA+B;AAAA,EAC/B,oBAAoB;AAAA,EACpB,2BAA2B;AAAA,EAC3B,4BAA4B;AAAA;AAAA,EAG5B,wBAAwB;AAAA;AAAA,EAGxB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA;AAAA,EAGvB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA;AAAA,EAGlB,8BAA8B;AAAA;AAAA,EAG9B,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,sBAAsB;AAAA;AAAA,EAGtB,eAAe;AAAA;AAAA,EAGf,mBAAmB;AAAA;AAAA,EAGnB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA;AAAA,EAGnB,qBAAqB;AAAA;AAAA,EAGrB,wBAAwB;AAAA,EACxB,wBAAwB;AAAA;AAAA,EAGxB,yBAAyB;AAAA;AAAA,EAGzB,wBAAwB;AAAA;AAAA,EAGxB,uBAAuB;AAAA;AAAA,EAGvB,uBAAuB;AAAA;AAAA,EAGvB,oBAAoB;AAAA;AAAA,EAGpB,eAAe;AAAA;AAAA,EAGf,wBAAwB;AAC1B;AAEA,IAAO,aAAQ;;;AC3Yf,IAAM,KAAmB;AAAA;AAAA,EAEvB,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA;AAAA,EAGb,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,aAAa;AAAA,EACb,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,cAAc;AAAA;AAAA,EAGd,eAAe;AAAA,EACf,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA,EACb,WAAW;AAAA,EACX,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,UAAU;AAAA,EACV,cAAc;AAAA,EACd,aAAa;AAAA,EACb,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX,aAAa;AAAA,EACb,WAAW;AAAA,EACX,UAAU;AAAA;AAAA,EAGV,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA;AAAA,EAGjB,aAAa;AAAA,EACb,YAAY;AAAA;AAAA,EAGZ,cAAc;AAAA;AAAA,EAGd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,WAAW;AAAA;AAAA,EAGX,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,cAAc;AAAA,EACd,gBAAgB;AAAA;AAAA,EAGhB,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,eAAe;AAAA,EACf,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,aAAa;AAAA;AAAA,EAGb,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,4BAA4B;AAAA,EAC5B,yBAAyB;AAAA,EACzB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA;AAAA,EAGrB,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,4BAA4B;AAAA;AAAA,EAG5B,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,wBAAwB;AAAA,EACxB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA;AAAA,EAGjB,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,0BAA0B;AAAA,EAC1B,uBAAuB;AAAA,EACvB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,iBAAiB;AAAA;AAAA,EAGjB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,wBAAwB;AAAA,EACxB,0BAA0B;AAAA,EAC1B,wBAAwB;AAAA,EACxB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA;AAAA,EAGjB,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA;AAAA,EAGzB,cAAc;AAAA,EACd,cAAc;AAAA,EACd,4BAA4B;AAAA;AAAA,EAG5B,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,qBAAqB;AAAA,EACrB,0BAA0B;AAAA,EAC1B,qBAAqB;AAAA,EACrB,0BAA0B;AAAA,EAC1B,kBAAkB;AAAA,EAClB,wBAAwB;AAAA,EACxB,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,qBAAqB;AAAA,EACrB,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA;AAAA,EAGnB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,0BAA0B;AAAA,EAC1B,sBAAsB;AAAA,EACtB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA;AAAA,EAGrB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,2BAA2B;AAAA,EAC3B,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,aAAa;AAAA,EACb,uBAAuB;AAAA,EACvB,yBAAyB;AAAA,EACzB,uBAAuB;AAAA,EACvB,0BAA0B;AAAA,EAC1B,uBAAuB;AAAA,EACvB,mBAAmB;AAAA;AAAA,EAGnB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,yBAAyB;AAAA;AAAA,EAGzB,eAAe;AAAA,EACf,2BAA2B;AAAA,EAC3B,qBAAqB;AAAA,EACrB,aAAa;AAAA,EACb,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,uBAAuB;AAAA,EACvB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,wBAAwB;AAAA,EACxB,sBAAsB;AAAA,EACtB,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA;AAAA,EAGnB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA;AAAA,EAGlB,mBAAmB;AAAA;AAAA,EAGnB,yBAAyB;AAAA;AAAA,EAGzB,oBAAoB;AAAA,EACpB,uBAAuB;AAAA,EACvB,2BAA2B;AAAA,EAC3B,uBAAuB;AAAA;AAAA,EAGvB,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,UAAU;AAAA,EACV,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,uBAAuB;AAAA,EACvB,yBAAyB;AAAA,EACzB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,uBAAuB;AAAA,EACvB,sBAAsB;AAAA,EACtB,6BAA6B;AAAA,EAC7B,wBAAwB;AAAA,EACxB,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,+BAA+B;AAAA,EAC/B,oBAAoB;AAAA,EACpB,2BAA2B;AAAA,EAC3B,4BAA4B;AAAA;AAAA,EAG5B,wBAAwB;AAAA;AAAA,EAGxB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA;AAAA,EAGvB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA;AAAA,EAGlB,8BAA8B;AAAA;AAAA,EAG9B,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,sBAAsB;AAAA;AAAA,EAGtB,eAAe;AAAA;AAAA,EAGf,mBAAmB;AAAA;AAAA,EAGnB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA;AAAA,EAGnB,qBAAqB;AAAA;AAAA,EAGrB,wBAAwB;AAAA,EACxB,wBAAwB;AAAA;AAAA,EAGxB,yBAAyB;AAAA;AAAA,EAGzB,wBAAwB;AAAA;AAAA,EAGxB,uBAAuB;AAAA;AAAA,EAGvB,uBAAuB;AAAA;AAAA,EAGvB,oBAAoB;AAAA;AAAA,EAGpB,eAAe;AAAA;AAAA,EAGf,wBAAwB;AAC1B;AAEA,IAAO,aAAQ;;;AFxYf,IAAM,UAAwC,EAAE,gBAAI,eAAG;AAEvD,SAAS,SAAS,GAAwB;AACxC,SAAO,MAAM,QAAQ,MAAM;AAC7B;AAEA,SAAS,eAAuB;AAC9B,QAAM,OAAO,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,SAAS,CAAC;AAC7D,MAAI,MAAM;AACR,UAAM,OAAO,KAAK,MAAM,GAAG,EAAE,CAAC;AAC9B,QAAI,QAAQ,SAAS,IAAI,EAAG,QAAO;AAAA,EACrC;AACA,QAAM,MAAM,QAAQ,IAAI,QAAQ,QAAQ,IAAI,UAAU,QAAQ,IAAI,eAAe;AACjF,QAAM,SAAS,IAAI,MAAM,MAAM,EAAE,CAAC,KAAK;AACvC,MAAI,SAAS,MAAM,EAAG,QAAO;AAC7B,SAAO;AACT;AAQO,IAAM,iBAAiB,OAAoB,CAAC,SAAS;AAAA,EAC1D,QAAQ,aAAa;AAAA,EACrB,WAAW,CAAC,WAAW,IAAI,EAAE,OAAO,CAAC;AACvC,EAAE;AAEK,SAAS,YAAoB;AAClC,SAAO,eAAe,SAAS,EAAE;AACnC;AAGO,SAAS,EAAE,KAAqB,QAAkD;AACvF,QAAM,SAAS,eAAe,SAAS,EAAE;AACzC,MAAI,OAAe,QAAQ,MAAM,EAAE,GAAG,KAAK,QAAQ,IAAI,EAAE,GAAG,KAAK;AACjE,MAAI,QAAQ;AACV,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3C,aAAO,KAAK,WAAW,KAAK,CAAC,MAAM,OAAO,CAAC,CAAC;AAAA,IAC9C;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,GAAG,SAAiB,OAAe,QAAkD;AACnG,QAAM,SAAS,UAAU,IAAI,SAAS;AACtC,SAAO,EAAE,GAAG,OAAO,GAAG,MAAM,IAAsB,EAAE,OAAO,GAAG,OAAO,CAAC;AACxE;;;AGvDA,IAAM,aAAuC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE;AACpF,IAAM,eAA0B,QAAQ,IAAI,aAA0B;AAEtE,SAAS,UAAU,OAA0B;AAC3C,SAAO,WAAW,KAAK,KAAK,WAAW,YAAY;AACrD;AAEO,IAAM,SAAS;AAAA,EACpB,OAAO,CAAC,KAAa,QAAkC,UAAU,OAAO,KAAK,QAAQ,MAAM,WAAW,GAAG,IAAI,OAAO,EAAE;AAAA,EACtH,MAAM,CAAC,KAAa,QAAkC,UAAU,MAAM,KAAK,QAAQ,KAAK,UAAU,GAAG,IAAI,OAAO,EAAE;AAAA,EAClH,MAAM,CAAC,KAAa,QAAkC,UAAU,MAAM,KAAK,QAAQ,KAAK,UAAU,GAAG,IAAI,OAAO,EAAE;AAAA,EAClH,OAAO,CAAC,KAAa,QAAkC,UAAU,OAAO,KAAK,QAAQ,MAAM,WAAW,GAAG,IAAI,OAAO,EAAE;AACxH;;;ACXO,SAAS,iBAAiB,KAAa,UAAuB,CAAC,GAAG,YAAY,MAA2B;AAC9G,SAAO,MAAM,KAAK,EAAE,GAAG,SAAS,QAAQ,YAAY,QAAQ,SAAS,EAAE,CAAC;AAC1E;","names":[]}
|
package/build/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
t,
|
|
16
16
|
tp,
|
|
17
17
|
useLocaleStore
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-PPSKR6PA.js";
|
|
19
19
|
|
|
20
20
|
// src/index.tsx
|
|
21
21
|
import { createInterface } from "readline/promises";
|
|
@@ -160,7 +160,7 @@ var GRADIENTS = {
|
|
|
160
160
|
};
|
|
161
161
|
|
|
162
162
|
// src/components/layout/header.tsx
|
|
163
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
163
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
164
164
|
var LOGO_BREW = [
|
|
165
165
|
"\u256D\u2501\u2501\u256E\u2571\u256D\u2501\u2501\u2501\u256E\u256D\u2501\u2501\u2501\u256E\u256D\u256E\u256D\u256E\u256D\u256E\u2571\u2571\u2571\u2571\u2571\u2571\u2571",
|
|
166
166
|
"\u2503\u256D\u256E\u2503\u2571\u2503\u256D\u2501\u256E\u2503\u2503\u256D\u2501\u2501\u256F\u2503\u2503\u2503\u2503\u2503\u2503\u2571\u2571\u2571\u2571\u2571\u2571\u2571",
|
|
@@ -227,26 +227,30 @@ function Header() {
|
|
|
227
227
|
/* @__PURE__ */ jsx2(GradientText, { colors: GRADIENTS.gold, children: brew }),
|
|
228
228
|
/* @__PURE__ */ jsx2(GradientText, { colors: ["#B8860B", "#8B6914", "#6B4F10"], children: LOGO_TUI[i] })
|
|
229
229
|
] }, i)) }),
|
|
230
|
+
/* @__PURE__ */ jsx2(Text2, { children: " " }),
|
|
230
231
|
/* @__PURE__ */ jsx2(Box, { borderStyle: "single", borderBottom: true, borderLeft: false, borderRight: false, borderTop: false, borderColor: COLORS.gold, paddingX: 1, flexWrap: "wrap", children: TAB_VIEWS.map((view, i) => {
|
|
231
232
|
const key = VIEW_KEYS[view];
|
|
232
233
|
const viewLabel = t(VIEW_LABEL_KEYS[view]);
|
|
233
|
-
const label = key ? `${key}:${viewLabel}` : viewLabel;
|
|
234
234
|
const isPro = isProView(view);
|
|
235
|
+
const isActive = view === currentView;
|
|
236
|
+
const isAccount = view === "account";
|
|
235
237
|
return /* @__PURE__ */ jsxs(React2.Fragment, { children: [
|
|
236
238
|
i > 0 && /* @__PURE__ */ jsxs(Text2, { color: COLORS.border, children: [
|
|
237
239
|
" ",
|
|
238
240
|
"\u2502",
|
|
239
241
|
" "
|
|
240
242
|
] }),
|
|
241
|
-
/* @__PURE__ */
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
243
|
+
isActive && /* @__PURE__ */ jsxs(Text2, { color: COLORS.sky, children: [
|
|
244
|
+
"\u25CF",
|
|
245
|
+
" "
|
|
246
|
+
] }),
|
|
247
|
+
key ? /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
248
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: "#FFFFFF", children: key }),
|
|
249
|
+
/* @__PURE__ */ jsxs(Text2, { bold: isActive, underline: isActive, color: isActive ? COLORS.success : isAccount ? COLORS.gold : COLORS.textSecondary, children: [
|
|
250
|
+
" ",
|
|
251
|
+
viewLabel
|
|
252
|
+
] })
|
|
253
|
+
] }) : /* @__PURE__ */ jsx2(Text2, { bold: isActive, underline: isActive, color: isActive ? COLORS.success : isAccount ? COLORS.gold : COLORS.textSecondary, children: viewLabel }),
|
|
250
254
|
isPro && /* @__PURE__ */ jsxs(Text2, { color: COLORS.brand, bold: true, children: [
|
|
251
255
|
" ",
|
|
252
256
|
t("pro_badge")
|
|
@@ -259,7 +263,7 @@ function Header() {
|
|
|
259
263
|
// src/components/layout/footer.tsx
|
|
260
264
|
import React3 from "react";
|
|
261
265
|
import { Box as Box2, Text as Text3 } from "ink";
|
|
262
|
-
import { Fragment as
|
|
266
|
+
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
263
267
|
var VIEW_HINT_DEFS = {
|
|
264
268
|
dashboard: [["1-0", "hint_navigate"], ["tab", "hint_next"], ["q", "hint_quit"]],
|
|
265
269
|
installed: [["/", "hint_filter"], ["enter", "hint_info"], ["u", "hint_uninstall"], ["f", "hint_toggle"], ["tab", "hint_next"], ["q", "hint_quit"]],
|
|
@@ -272,11 +276,11 @@ var VIEW_HINT_DEFS = {
|
|
|
272
276
|
"smart-cleanup": [["enter", "hint_toggle"], ["c", "hint_clean"], ["r", "hint_refresh"], ["q", "hint_quit"]],
|
|
273
277
|
history: [["/", "hint_search"], ["enter", "hint_replay"], ["f", "hint_filter"], ["c", "hint_clear"], ["q", "hint_quit"]],
|
|
274
278
|
"security-audit": [["r", "hint_scan"], ["enter", "hint_details"], ["u", "hint_upgrade"], ["q", "hint_quit"]],
|
|
275
|
-
account: [["d", "hint_deactivate"], ["q", "hint_quit"]]
|
|
279
|
+
account: [["p", "hint_promo"], ["d", "hint_deactivate"], ["q", "hint_quit"]]
|
|
276
280
|
};
|
|
277
281
|
function HintItem({ def }) {
|
|
278
282
|
if (def.length === 1) return /* @__PURE__ */ jsx3(Text3, { color: COLORS.gold, dimColor: true, children: t(def[0]) });
|
|
279
|
-
return /* @__PURE__ */ jsxs2(
|
|
283
|
+
return /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
280
284
|
/* @__PURE__ */ jsx3(Text3, { color: COLORS.text, bold: true, children: def[0] }),
|
|
281
285
|
/* @__PURE__ */ jsx3(Text3, { color: COLORS.textSecondary, children: ":" }),
|
|
282
286
|
/* @__PURE__ */ jsx3(Text3, { color: COLORS.gold, dimColor: true, children: t(def[1]) })
|
|
@@ -530,9 +534,9 @@ function isEncryptedLicenseFile(obj) {
|
|
|
530
534
|
async function getMachineId2() {
|
|
531
535
|
try {
|
|
532
536
|
const { readFile: readMachineId } = await import("fs/promises");
|
|
533
|
-
const { join:
|
|
534
|
-
const { homedir:
|
|
535
|
-
const machineIdPath =
|
|
537
|
+
const { join: join4 } = await import("path");
|
|
538
|
+
const { homedir: homedir3 } = await import("os");
|
|
539
|
+
const machineIdPath = join4(homedir3(), ".brew-tui", "machine-id");
|
|
536
540
|
return (await readMachineId(machineIdPath, "utf-8")).trim() || null;
|
|
537
541
|
} catch {
|
|
538
542
|
return null;
|
|
@@ -1430,7 +1434,10 @@ import { Box as Box7, Text as Text8 } from "ink";
|
|
|
1430
1434
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1431
1435
|
function SectionHeader({ emoji, title, color = COLORS.gold, gradient, count }) {
|
|
1432
1436
|
return /* @__PURE__ */ jsxs8(Box7, { gap: 1, children: [
|
|
1433
|
-
/* @__PURE__ */
|
|
1437
|
+
/* @__PURE__ */ jsxs8(Text8, { children: [
|
|
1438
|
+
emoji,
|
|
1439
|
+
" "
|
|
1440
|
+
] }),
|
|
1434
1441
|
gradient ? /* @__PURE__ */ jsx8(GradientText, { colors: gradient, bold: true, children: title }) : /* @__PURE__ */ jsx8(Text8, { bold: true, color, children: title }),
|
|
1435
1442
|
count !== void 0 && /* @__PURE__ */ jsxs8(Text8, { color: COLORS.textSecondary, children: [
|
|
1436
1443
|
"(",
|
|
@@ -1442,9 +1449,9 @@ function SectionHeader({ emoji, title, color = COLORS.gold, gradient, count }) {
|
|
|
1442
1449
|
|
|
1443
1450
|
// src/components/common/version-arrow.tsx
|
|
1444
1451
|
import { Text as Text9 } from "ink";
|
|
1445
|
-
import { Fragment as
|
|
1452
|
+
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1446
1453
|
function VersionArrow({ current, latest }) {
|
|
1447
|
-
return /* @__PURE__ */ jsxs9(
|
|
1454
|
+
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
1448
1455
|
/* @__PURE__ */ jsxs9(Text9, { color: COLORS.muted, children: [
|
|
1449
1456
|
t("version_installed"),
|
|
1450
1457
|
" "
|
|
@@ -2287,7 +2294,7 @@ ${t("outdated_upgradeAllList", { list: allOutdated.map((p) => p.name).join(", ")
|
|
|
2287
2294
|
// src/views/package-info.tsx
|
|
2288
2295
|
import { useEffect as useEffect8, useRef as useRef4, useState as useState6 } from "react";
|
|
2289
2296
|
import { Box as Box17, Text as Text19, useInput as useInput6 } from "ink";
|
|
2290
|
-
import { Fragment as
|
|
2297
|
+
import { Fragment as Fragment5, jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2291
2298
|
var ACTION_PROGRESS_KEYS = {
|
|
2292
2299
|
install: "pkgInfo_installing",
|
|
2293
2300
|
uninstall: "pkgInfo_uninstalling",
|
|
@@ -2408,7 +2415,7 @@ function PackageInfoView() {
|
|
|
2408
2415
|
"esc:",
|
|
2409
2416
|
t("hint_cancel")
|
|
2410
2417
|
] }),
|
|
2411
|
-
!stream.isRunning && /* @__PURE__ */ jsxs18(
|
|
2418
|
+
!stream.isRunning && /* @__PURE__ */ jsxs18(Fragment5, { children: [
|
|
2412
2419
|
/* @__PURE__ */ jsx19(Text19, { color: stream.error ? COLORS.error : COLORS.success, bold: true, children: stream.error ? `\u2718 ${stream.error}` : `\u2714 ${t("pkgInfo_done")}` }),
|
|
2413
2420
|
/* @__PURE__ */ jsxs18(Text19, { color: COLORS.textSecondary, children: [
|
|
2414
2421
|
"esc:",
|
|
@@ -2470,7 +2477,7 @@ function PackageInfoView() {
|
|
|
2470
2477
|
" ",
|
|
2471
2478
|
formula.versions.stable
|
|
2472
2479
|
] }),
|
|
2473
|
-
installed && /* @__PURE__ */ jsxs18(
|
|
2480
|
+
installed && /* @__PURE__ */ jsxs18(Fragment5, { children: [
|
|
2474
2481
|
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
2475
2482
|
/* @__PURE__ */ jsx19(Text19, { color: COLORS.muted, children: t("pkgInfo_installed") }),
|
|
2476
2483
|
" ",
|
|
@@ -4009,17 +4016,95 @@ function SecurityAuditView() {
|
|
|
4009
4016
|
// src/views/account.tsx
|
|
4010
4017
|
import { useState as useState12 } from "react";
|
|
4011
4018
|
import { Box as Box28, Text as Text29, useInput as useInput13 } from "ink";
|
|
4012
|
-
import {
|
|
4019
|
+
import { TextInput as TextInput5 } from "@inkjs/ui";
|
|
4020
|
+
|
|
4021
|
+
// src/lib/license/promo.ts
|
|
4022
|
+
import { readFile as readFile4, writeFile as writeFile4, rename as rename3, mkdir as mkdir2 } from "fs/promises";
|
|
4023
|
+
import { randomBytes as randomBytes2, randomUUID as randomUUID2 } from "crypto";
|
|
4024
|
+
import { join as join3 } from "path";
|
|
4025
|
+
import { homedir as homedir2 } from "os";
|
|
4026
|
+
var MACHINE_ID_PATH2 = join3(homedir2(), ".brew-tui", "machine-id");
|
|
4027
|
+
async function getMachineId3() {
|
|
4028
|
+
try {
|
|
4029
|
+
const id2 = (await readFile4(MACHINE_ID_PATH2, "utf-8")).trim();
|
|
4030
|
+
if (id2) return id2;
|
|
4031
|
+
} catch {
|
|
4032
|
+
}
|
|
4033
|
+
const id = randomUUID2();
|
|
4034
|
+
await mkdir2(join3(homedir2(), ".brew-tui"), { recursive: true, mode: 448 });
|
|
4035
|
+
await writeFile4(MACHINE_ID_PATH2, id, { encoding: "utf-8", mode: 384 });
|
|
4036
|
+
return id;
|
|
4037
|
+
}
|
|
4038
|
+
var PROMO_PATH = join3(DATA_DIR, "promo.json");
|
|
4039
|
+
var PROMO_API_URL = "https://api.molinesdesigns.com/api/promo";
|
|
4040
|
+
async function redeemPromoCode(code) {
|
|
4041
|
+
const normalized = code.trim().toUpperCase();
|
|
4042
|
+
const machineId = await getMachineId3();
|
|
4043
|
+
try {
|
|
4044
|
+
const res = await fetchWithTimeout(`${PROMO_API_URL}/redeem`, {
|
|
4045
|
+
method: "POST",
|
|
4046
|
+
headers: { "Content-Type": "application/json" },
|
|
4047
|
+
body: JSON.stringify({ code: normalized, machineId })
|
|
4048
|
+
}, 1e4);
|
|
4049
|
+
if (!res.ok) {
|
|
4050
|
+
const body = await res.json().catch(() => ({}));
|
|
4051
|
+
return { success: false, error: body.error ?? "Invalid or expired promo code" };
|
|
4052
|
+
}
|
|
4053
|
+
const data = await res.json();
|
|
4054
|
+
var serverExpiresAt = data.data.expiresAt;
|
|
4055
|
+
var serverType = data.data.type;
|
|
4056
|
+
} catch (err) {
|
|
4057
|
+
logger.error("Promo redeem failed", { error: String(err) });
|
|
4058
|
+
return { success: false, error: "Could not reach promo server. Check your connection." };
|
|
4059
|
+
}
|
|
4060
|
+
await ensureDataDirs();
|
|
4061
|
+
const redemption = {
|
|
4062
|
+
code: normalized,
|
|
4063
|
+
redeemedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4064
|
+
expiresAt: serverExpiresAt,
|
|
4065
|
+
type: serverType
|
|
4066
|
+
};
|
|
4067
|
+
let file = { version: 1, redemptions: [] };
|
|
4068
|
+
try {
|
|
4069
|
+
const raw = await readFile4(PROMO_PATH, "utf-8");
|
|
4070
|
+
file = JSON.parse(raw);
|
|
4071
|
+
} catch {
|
|
4072
|
+
}
|
|
4073
|
+
if (file.redemptions.some((r) => r.code === redemption.code)) {
|
|
4074
|
+
return { success: false, error: "This promo code has already been redeemed" };
|
|
4075
|
+
}
|
|
4076
|
+
file.redemptions.push(redemption);
|
|
4077
|
+
const tmpPath = PROMO_PATH + ".tmp";
|
|
4078
|
+
await writeFile4(tmpPath, JSON.stringify(file, null, 2), { encoding: "utf-8", mode: 384 });
|
|
4079
|
+
await rename3(tmpPath, PROMO_PATH);
|
|
4080
|
+
return { success: true, expiresAt: redemption.expiresAt };
|
|
4081
|
+
}
|
|
4082
|
+
|
|
4083
|
+
// src/views/account.tsx
|
|
4084
|
+
import { Fragment as Fragment6, jsx as jsx30, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
4013
4085
|
function AccountView() {
|
|
4014
4086
|
const { status, license, deactivate: deactivate2, degradation } = useLicenseStore();
|
|
4015
4087
|
const [confirmDeactivate, setConfirmDeactivate] = useState12(false);
|
|
4016
4088
|
const [deactivating, setDeactivating] = useState12(false);
|
|
4017
4089
|
const [deactivateError, setDeactivateError] = useState12(null);
|
|
4018
|
-
|
|
4019
|
-
|
|
4090
|
+
const [promoMode, setPromoMode] = useState12(false);
|
|
4091
|
+
const [promoLoading, setPromoLoading] = useState12(false);
|
|
4092
|
+
const [promoResult, setPromoResult] = useState12(null);
|
|
4093
|
+
useInput13((input, key) => {
|
|
4094
|
+
if (confirmDeactivate || deactivating || promoMode) {
|
|
4095
|
+
if (key.escape && promoMode) {
|
|
4096
|
+
setPromoMode(false);
|
|
4097
|
+
setPromoResult(null);
|
|
4098
|
+
}
|
|
4099
|
+
return;
|
|
4100
|
+
}
|
|
4020
4101
|
if (input === "d" && status === "pro") {
|
|
4021
4102
|
setConfirmDeactivate(true);
|
|
4022
4103
|
}
|
|
4104
|
+
if (input === "p") {
|
|
4105
|
+
setPromoMode(true);
|
|
4106
|
+
setPromoResult(null);
|
|
4107
|
+
}
|
|
4023
4108
|
});
|
|
4024
4109
|
const maskKey = (key) => {
|
|
4025
4110
|
if (key.length <= 8) return key;
|
|
@@ -4059,7 +4144,7 @@ function AccountView() {
|
|
|
4059
4144
|
(degradation === "warning" || degradation === "limited") && license && /* @__PURE__ */ jsx30(Box28, { marginTop: 1, borderStyle: "round", borderColor: COLORS.warning, paddingX: 2, paddingY: 0, children: /* @__PURE__ */ jsx30(Text29, { color: COLORS.warning, children: t("license_offlineWarning", {
|
|
4060
4145
|
days: Math.floor((Date.now() - new Date(license.lastValidatedAt).getTime()) / (24 * 60 * 60 * 1e3))
|
|
4061
4146
|
}) }) }),
|
|
4062
|
-
license && /* @__PURE__ */ jsxs29(
|
|
4147
|
+
license && /* @__PURE__ */ jsxs29(Fragment6, { children: [
|
|
4063
4148
|
/* @__PURE__ */ jsxs29(Box28, { gap: 1, children: [
|
|
4064
4149
|
/* @__PURE__ */ jsx30(Text29, { color: COLORS.muted, children: t("account_emailLabel") }),
|
|
4065
4150
|
/* @__PURE__ */ jsx30(Text29, { children: license.customerEmail })
|
|
@@ -4110,10 +4195,41 @@ function AccountView() {
|
|
|
4110
4195
|
deactivating && /* @__PURE__ */ jsx30(Text29, { color: COLORS.sky, children: t("account_deactivating") }),
|
|
4111
4196
|
deactivateError && /* @__PURE__ */ jsx30(Text29, { color: COLORS.error, children: deactivateError })
|
|
4112
4197
|
] }),
|
|
4113
|
-
/* @__PURE__ */ jsx30(Box28, { marginTop: 2, children: /* @__PURE__ */ jsxs29(
|
|
4114
|
-
|
|
4198
|
+
/* @__PURE__ */ jsx30(Box28, { flexDirection: "column", marginTop: 1, paddingLeft: 2, children: promoMode ? /* @__PURE__ */ jsxs29(Box28, { flexDirection: "column", gap: 1, children: [
|
|
4199
|
+
/* @__PURE__ */ jsx30(Text29, { bold: true, color: COLORS.gold, children: t("account_promoTitle") }),
|
|
4200
|
+
promoLoading ? /* @__PURE__ */ jsx30(Text29, { color: COLORS.sky, children: t("account_promoValidating") }) : /* @__PURE__ */ jsxs29(Box28, { gap: 1, children: [
|
|
4201
|
+
/* @__PURE__ */ jsx30(Text29, { color: COLORS.muted, children: t("account_promoLabel") }),
|
|
4202
|
+
/* @__PURE__ */ jsx30(
|
|
4203
|
+
TextInput5,
|
|
4204
|
+
{
|
|
4205
|
+
defaultValue: "",
|
|
4206
|
+
placeholder: "BREW-XXXX-XXXX",
|
|
4207
|
+
onSubmit: async (value) => {
|
|
4208
|
+
if (!value.trim()) return;
|
|
4209
|
+
setPromoLoading(true);
|
|
4210
|
+
try {
|
|
4211
|
+
const result = await redeemPromoCode(value);
|
|
4212
|
+
if (result.success) {
|
|
4213
|
+
setPromoResult({ success: true, message: t("account_promoSuccess", { expires: formatDate(result.expiresAt) }) });
|
|
4214
|
+
} else {
|
|
4215
|
+
setPromoResult({ success: false, message: result.error ?? t("account_promoInvalid") });
|
|
4216
|
+
}
|
|
4217
|
+
} catch {
|
|
4218
|
+
setPromoResult({ success: false, message: t("account_promoError") });
|
|
4219
|
+
} finally {
|
|
4220
|
+
setPromoLoading(false);
|
|
4221
|
+
}
|
|
4222
|
+
}
|
|
4223
|
+
}
|
|
4224
|
+
)
|
|
4225
|
+
] }),
|
|
4226
|
+
promoResult && /* @__PURE__ */ jsx30(ResultBanner, { status: promoResult.success ? "success" : "error", message: promoResult.message }),
|
|
4227
|
+
/* @__PURE__ */ jsx30(Text29, { color: COLORS.textSecondary, dimColor: true, children: t("account_promoEsc") })
|
|
4228
|
+
] }) : /* @__PURE__ */ jsx30(Text29, { color: COLORS.textSecondary, children: t("account_promoHint") }) }),
|
|
4229
|
+
/* @__PURE__ */ jsx30(Box28, { marginTop: 1, children: /* @__PURE__ */ jsxs29(Text29, { color: COLORS.textSecondary, children: [
|
|
4230
|
+
status === "pro" ? `d ${t("hint_deactivate")}` : "",
|
|
4115
4231
|
" ",
|
|
4116
|
-
t("app_version", { version: "0.3.
|
|
4232
|
+
t("app_version", { version: "0.3.3" })
|
|
4117
4233
|
] }) })
|
|
4118
4234
|
] });
|
|
4119
4235
|
}
|
|
@@ -4266,7 +4382,7 @@ async function runCli() {
|
|
|
4266
4382
|
if (command === "install-brewbar") {
|
|
4267
4383
|
await useLicenseStore.getState().initialize();
|
|
4268
4384
|
const isPro = useLicenseStore.getState().isPro();
|
|
4269
|
-
const { installBrewBar } = await import("./brewbar-installer-
|
|
4385
|
+
const { installBrewBar } = await import("./brewbar-installer-SFVZEIA6.js");
|
|
4270
4386
|
try {
|
|
4271
4387
|
await installBrewBar(isPro, arg === "--force");
|
|
4272
4388
|
console.log(t("cli_brewbarInstalled"));
|
|
@@ -4277,7 +4393,7 @@ async function runCli() {
|
|
|
4277
4393
|
return;
|
|
4278
4394
|
}
|
|
4279
4395
|
if (command === "uninstall-brewbar") {
|
|
4280
|
-
const { uninstallBrewBar } = await import("./brewbar-installer-
|
|
4396
|
+
const { uninstallBrewBar } = await import("./brewbar-installer-SFVZEIA6.js");
|
|
4281
4397
|
try {
|
|
4282
4398
|
await uninstallBrewBar();
|
|
4283
4399
|
console.log(t("cli_brewbarUninstalled"));
|