brew-tui 1.2.0 → 1.2.1

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/index.js CHANGED
@@ -66,7 +66,7 @@ import { rm as rm2 } from "fs/promises";
66
66
  import { render } from "ink";
67
67
 
68
68
  // src/app.tsx
69
- import { useEffect as useEffect23, useState as useState21 } from "react";
69
+ import { useEffect as useEffect22, useState as useState20 } from "react";
70
70
  import { useApp } from "ink";
71
71
 
72
72
  // src/components/layout/app-layout.tsx
@@ -77,28 +77,46 @@ import { Box as Box3 } from "ink";
77
77
  import { Box, Text as Text3 } from "ink";
78
78
 
79
79
  // src/hooks/use-terminal-size.ts
80
- import { useEffect, useState } from "react";
80
+ import { useSyncExternalStore } from "react";
81
81
  import { useStdout } from "ink";
82
+ var FALLBACK = { columns: 80, rows: 24 };
83
+ var cache = /* @__PURE__ */ new WeakMap();
84
+ function snapshot(stdout) {
85
+ return {
86
+ columns: stdout.columns ?? FALLBACK.columns,
87
+ rows: stdout.rows ?? FALLBACK.rows
88
+ };
89
+ }
90
+ function getCache(stdout) {
91
+ const existing = cache.get(stdout);
92
+ if (existing) return existing;
93
+ const entry = {
94
+ current: snapshot(stdout),
95
+ subscribers: /* @__PURE__ */ new Set()
96
+ };
97
+ cache.set(stdout, entry);
98
+ stdout.on("resize", () => {
99
+ entry.current = snapshot(stdout);
100
+ entry.subscribers.forEach((cb) => cb());
101
+ });
102
+ return entry;
103
+ }
82
104
  function useTerminalSize() {
83
105
  const { stdout } = useStdout();
84
- const [size, setSize] = useState(() => ({
85
- columns: stdout?.columns ?? 80,
86
- rows: stdout?.rows ?? 24
87
- }));
88
- useEffect(() => {
89
- if (!stdout) return;
90
- const onResize = () => {
91
- setSize({
92
- columns: stdout.columns ?? 80,
93
- rows: stdout.rows ?? 24
94
- });
95
- };
96
- stdout.on("resize", onResize);
97
- return () => {
98
- stdout.off("resize", onResize);
99
- };
100
- }, [stdout]);
101
- return size;
106
+ return useSyncExternalStore(
107
+ (cb) => {
108
+ if (!stdout) return () => {
109
+ };
110
+ const entry = getCache(stdout);
111
+ entry.subscribers.add(cb);
112
+ return () => {
113
+ entry.subscribers.delete(cb);
114
+ };
115
+ },
116
+ () => stdout ? getCache(stdout).current : FALLBACK,
117
+ // Server snapshot — not used in CLI, but useSyncExternalStore requires it.
118
+ () => FALLBACK
119
+ );
102
120
  }
103
121
 
104
122
  // src/stores/navigation-store.ts
@@ -322,7 +340,7 @@ var GRADIENTS = {
322
340
  };
323
341
 
324
342
  // src/components/common/blinking-text.tsx
325
- import { useEffect as useEffect2, useState as useState2 } from "react";
343
+ import { useEffect, useState } from "react";
326
344
  import { Text as Text2 } from "ink";
327
345
  import { jsx as jsx2 } from "react/jsx-runtime";
328
346
  function BlinkingText({
@@ -331,8 +349,8 @@ function BlinkingText({
331
349
  bold = true,
332
350
  children
333
351
  }) {
334
- const [bright, setBright] = useState2(true);
335
- useEffect2(() => {
352
+ const [bright, setBright] = useState(true);
353
+ useEffect(() => {
336
354
  const id = setInterval(() => setBright((b) => !b), intervalMs);
337
355
  return () => clearInterval(id);
338
356
  }, [intervalMs]);
@@ -567,12 +585,12 @@ function Footer() {
567
585
  }
568
586
 
569
587
  // src/hooks/use-container-size.ts
570
- import { useEffect as useEffect3, useState as useState3 } from "react";
588
+ import { useEffect as useEffect2, useState as useState2 } from "react";
571
589
  import { measureElement } from "ink";
572
590
  function useContainerSize(ref) {
573
591
  const terminal = useTerminalSize();
574
- const [size, setSize] = useState3({ width: 0, height: 0 });
575
- useEffect3(() => {
592
+ const [size, setSize] = useState2({ width: 0, height: 0 });
593
+ useEffect2(() => {
576
594
  if (!ref.current) return;
577
595
  const measured = measureElement(ref.current);
578
596
  setSize(
@@ -849,7 +867,7 @@ async function markOnboardingComplete() {
849
867
  }
850
868
 
851
869
  // src/views/welcome.tsx
852
- import { useEffect as useEffect4 } from "react";
870
+ import { useEffect as useEffect3 } from "react";
853
871
  import { Box as Box4, Text as Text5 } from "ink";
854
872
 
855
873
  // src/hooks/use-view-input.ts
@@ -863,7 +881,7 @@ function useViewInput(handler, opts) {
863
881
  // src/views/welcome.tsx
864
882
  import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
865
883
  function WelcomeView({ onContinue }) {
866
- useEffect4(() => {
884
+ useEffect3(() => {
867
885
  return () => {
868
886
  };
869
887
  }, []);
@@ -982,7 +1000,7 @@ function UpgradePrompt({ viewId }) {
982
1000
  }
983
1001
 
984
1002
  // src/views/dashboard.tsx
985
- import { useEffect as useEffect5, useMemo as useMemo2 } from "react";
1003
+ import { useEffect as useEffect4, useMemo as useMemo2 } from "react";
986
1004
  import { Box as Box9, Text as Text12 } from "ink";
987
1005
 
988
1006
  // src/hooks/use-visible-rows.ts
@@ -2143,7 +2161,7 @@ function DashboardView() {
2143
2161
  minRows: 2
2144
2162
  });
2145
2163
  const halfRows = Math.max(1, Math.floor(splitRows / 2));
2146
- useEffect5(() => {
2164
+ useEffect4(() => {
2147
2165
  fetchAll();
2148
2166
  }, []);
2149
2167
  useViewInput((input) => {
@@ -2256,14 +2274,14 @@ function DashboardView() {
2256
2274
  }
2257
2275
 
2258
2276
  // src/views/installed.tsx
2259
- import { useState as useState6, useMemo as useMemo3, useEffect as useEffect9, useRef as useRef3 } from "react";
2277
+ import { useState as useState5, useMemo as useMemo3, useEffect as useEffect8, useRef as useRef3 } from "react";
2260
2278
  import { Box as Box15, Text as Text18 } from "ink";
2261
2279
 
2262
2280
  // src/hooks/use-debounce.ts
2263
- import { useState as useState4, useEffect as useEffect6 } from "react";
2281
+ import { useState as useState3, useEffect as useEffect5 } from "react";
2264
2282
  function useDebounce(value, delayMs) {
2265
- const [debounced, setDebounced] = useState4(value);
2266
- useEffect6(() => {
2283
+ const [debounced, setDebounced] = useState3(value);
2284
+ useEffect5(() => {
2267
2285
  const timer = setTimeout(() => setDebounced(value), delayMs);
2268
2286
  return () => clearTimeout(timer);
2269
2287
  }, [value, delayMs]);
@@ -2271,7 +2289,7 @@ function useDebounce(value, delayMs) {
2271
2289
  }
2272
2290
 
2273
2291
  // src/hooks/use-brew-stream.ts
2274
- import { useState as useState5, useCallback, useRef as useRef2, useEffect as useEffect7 } from "react";
2292
+ import { useState as useState4, useCallback, useRef as useRef2, useEffect as useEffect6 } from "react";
2275
2293
  var MAX_LINES = 100;
2276
2294
  async function logToHistory(args, success, error) {
2277
2295
  const detected = detectAction(args);
@@ -2284,13 +2302,13 @@ async function logToHistory(args, success, error) {
2284
2302
  }
2285
2303
  }
2286
2304
  function useBrewStream() {
2287
- const [lines, setLines] = useState5([]);
2288
- const [isRunning, setIsRunning] = useState5(false);
2289
- const [error, setError2] = useState5(null);
2305
+ const [lines, setLines] = useState4([]);
2306
+ const [isRunning, setIsRunning] = useState4(false);
2307
+ const [error, setError2] = useState4(null);
2290
2308
  const cancelRef = useRef2(false);
2291
2309
  const generatorRef = useRef2(null);
2292
2310
  const mountedRef = useRef2(true);
2293
- useEffect7(() => {
2311
+ useEffect6(() => {
2294
2312
  mountedRef.current = true;
2295
2313
  return () => {
2296
2314
  mountedRef.current = false;
@@ -2370,13 +2388,13 @@ function SearchInput({ defaultValue, onChange, placeholder, isActive = true }) {
2370
2388
  }
2371
2389
 
2372
2390
  // src/components/common/confirm-dialog.tsx
2373
- import { useEffect as useEffect8 } from "react";
2391
+ import { useEffect as useEffect7 } from "react";
2374
2392
  import { Box as Box11, Text as Text14, useInput as useInput3 } from "ink";
2375
2393
  import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
2376
2394
  function ConfirmDialog({ message, onConfirm, onCancel }) {
2377
2395
  const locale = useLocaleStore((s) => s.locale);
2378
2396
  const { openModal, closeModal } = useModalStore();
2379
- useEffect8(() => {
2397
+ useEffect7(() => {
2380
2398
  openModal();
2381
2399
  return () => {
2382
2400
  closeModal();
@@ -2467,11 +2485,11 @@ function InstalledView() {
2467
2485
  /* cursor + gap */
2468
2486
  ) : Math.max(12, Math.floor(columns * 0.35));
2469
2487
  const versionWidth = Math.max(8, Math.floor(columns * 0.15));
2470
- const [filter, setFilter] = useState6("");
2471
- const [cursor, setCursor] = useState6(0);
2472
- const [tab, setTab] = useState6("formulae");
2473
- const [isSearching, setIsSearching] = useState6(false);
2474
- const [confirmUninstall, setConfirmUninstall] = useState6(null);
2488
+ const [filter, setFilter] = useState5("");
2489
+ const [cursor, setCursor] = useState5(0);
2490
+ const [tab, setTab] = useState5("formulae");
2491
+ const [isSearching, setIsSearching] = useState5(false);
2492
+ const [confirmUninstall, setConfirmUninstall] = useState5(null);
2475
2493
  const debouncedFilter = useDebounce(filter, 200);
2476
2494
  const stream = useBrewStream();
2477
2495
  const listRows = useVisibleRows({
@@ -2484,10 +2502,10 @@ function InstalledView() {
2484
2502
  fallbackReservedRows: 14,
2485
2503
  minRows: 1
2486
2504
  });
2487
- useEffect9(() => {
2505
+ useEffect8(() => {
2488
2506
  fetchInstalled();
2489
2507
  }, []);
2490
- useEffect9(() => {
2508
+ useEffect8(() => {
2491
2509
  if (isSearching) {
2492
2510
  openModal();
2493
2511
  return () => {
@@ -2673,17 +2691,17 @@ function InstalledView() {
2673
2691
  }
2674
2692
 
2675
2693
  // src/views/search.tsx
2676
- import { useState as useState7, useCallback as useCallback2, useEffect as useEffect10, useRef as useRef4 } from "react";
2694
+ import { useState as useState6, useCallback as useCallback2, useEffect as useEffect9, useRef as useRef4 } from "react";
2677
2695
  import { Box as Box16, Text as Text19 } from "ink";
2678
2696
  import { TextInput as TextInput2 } from "@inkjs/ui";
2679
2697
  import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
2680
2698
  function SearchView() {
2681
- const [query, setQuery] = useState7("");
2682
- const [results, setResults] = useState7(null);
2683
- const [searching, setSearching] = useState7(false);
2684
- const [searchError, setSearchError] = useState7(null);
2685
- const [cursor, setCursor] = useState7(0);
2686
- const [confirmInstall, setConfirmInstall] = useState7(null);
2699
+ const [query, setQuery] = useState6("");
2700
+ const [results, setResults] = useState6(null);
2701
+ const [searching, setSearching] = useState6(false);
2702
+ const [searchError, setSearchError] = useState6(null);
2703
+ const [cursor, setCursor] = useState6(0);
2704
+ const [confirmInstall, setConfirmInstall] = useState6(null);
2687
2705
  const stream = useBrewStream();
2688
2706
  const { openModal, closeModal } = useModalStore();
2689
2707
  const navigate = useNavigationStore((s) => s.navigate);
@@ -2700,7 +2718,7 @@ function SearchView() {
2700
2718
  fallbackReservedRows: 14,
2701
2719
  minRows: 1
2702
2720
  });
2703
- useEffect10(() => {
2721
+ useEffect9(() => {
2704
2722
  if (results !== null) {
2705
2723
  openModal();
2706
2724
  return () => {
@@ -2728,7 +2746,7 @@ function SearchView() {
2728
2746
  setSearching(false);
2729
2747
  }
2730
2748
  }, []);
2731
- useEffect10(() => {
2749
+ useEffect9(() => {
2732
2750
  if (!stream.isRunning && !stream.error && stream.lines.length > 0 && !hasRefreshed.current) {
2733
2751
  hasRefreshed.current = true;
2734
2752
  void fetchInstalled();
@@ -2743,7 +2761,7 @@ function SearchView() {
2743
2761
  Math.max(0, allResults.length - resultRows)
2744
2762
  );
2745
2763
  const visibleResults = allResults.slice(start, start + resultRows);
2746
- useEffect10(() => {
2764
+ useEffect9(() => {
2747
2765
  setCursor((current) => Math.min(current, Math.max(0, allResults.length - 1)));
2748
2766
  }, [allResults.length]);
2749
2767
  useViewInput((input, key) => {
@@ -2885,7 +2903,7 @@ function SearchView() {
2885
2903
  }
2886
2904
 
2887
2905
  // src/views/outdated.tsx
2888
- import { useEffect as useEffect11, useMemo as useMemo4, useRef as useRef5, useState as useState8 } from "react";
2906
+ import { useEffect as useEffect10, useMemo as useMemo4, useRef as useRef5, useState as useState7 } from "react";
2889
2907
  import { Box as Box17, Text as Text20 } from "ink";
2890
2908
  import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
2891
2909
  function ImpactPanel({ impact }) {
@@ -2912,12 +2930,12 @@ function ImpactPanel({ impact }) {
2912
2930
  function OutdatedView() {
2913
2931
  const { outdated, loading, errors, fetchOutdated } = useBrewStore();
2914
2932
  const stream = useBrewStream();
2915
- const [cursor, setCursor] = useState8(0);
2916
- const [confirmAction, setConfirmAction] = useState8(null);
2933
+ const [cursor, setCursor] = useState7(0);
2934
+ const [confirmAction, setConfirmAction] = useState7(null);
2917
2935
  const hasRefreshed = useRef5(false);
2918
2936
  const pendingUpgradeRef = useRef5(null);
2919
- const [impact, setImpact] = useState8(null);
2920
- const [impactLoading, setImpactLoading] = useState8(false);
2937
+ const [impact, setImpact] = useState7(null);
2938
+ const [impactLoading, setImpactLoading] = useState7(false);
2921
2939
  const listRows = useVisibleRows({
2922
2940
  reservedRows: impact || impactLoading ? 11 : 7,
2923
2941
  fallbackReservedRows: impact || impactLoading ? 18 : 14,
@@ -2928,10 +2946,10 @@ function OutdatedView() {
2928
2946
  fallbackReservedRows: 14,
2929
2947
  minRows: 1
2930
2948
  });
2931
- useEffect11(() => {
2949
+ useEffect10(() => {
2932
2950
  fetchOutdated();
2933
2951
  }, []);
2934
- useEffect11(() => {
2952
+ useEffect10(() => {
2935
2953
  if (!stream.isRunning && !stream.error && stream.lines.length > 0 && !hasRefreshed.current) {
2936
2954
  hasRefreshed.current = true;
2937
2955
  void fetchOutdated().then(() => {
@@ -2958,7 +2976,7 @@ function OutdatedView() {
2958
2976
  [outdated.formulae, outdated.casks]
2959
2977
  );
2960
2978
  const debouncedCursor = useDebounce(cursor, 150);
2961
- useEffect11(() => {
2979
+ useEffect10(() => {
2962
2980
  const pkg = allOutdated[debouncedCursor];
2963
2981
  if (!pkg || stream.isRunning) {
2964
2982
  setImpact(null);
@@ -3115,7 +3133,7 @@ ${t("outdated_upgradeAllList", { list: allOutdated.map((p) => p.name).join(", ")
3115
3133
  }
3116
3134
 
3117
3135
  // src/views/package-info.tsx
3118
- import { useEffect as useEffect12, useRef as useRef6, useState as useState9 } from "react";
3136
+ import { useEffect as useEffect11, useRef as useRef6, useState as useState8 } from "react";
3119
3137
  import { Box as Box18, Text as Text21 } from "ink";
3120
3138
  import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
3121
3139
  var ACTION_PROGRESS_KEYS = {
@@ -3131,21 +3149,21 @@ var ACTION_CONFIRM_KEYS = {
3131
3149
  function PackageInfoView() {
3132
3150
  const packageName = useNavigationStore((s) => s.selectedPackage);
3133
3151
  const packageType = useNavigationStore((s) => s.selectedPackageType);
3134
- const [formula, setFormula] = useState9(null);
3135
- const [loading, setLoading2] = useState9(true);
3136
- const [error, setError2] = useState9(null);
3137
- const [confirmAction, setConfirmAction] = useState9(null);
3152
+ const [formula, setFormula] = useState8(null);
3153
+ const [loading, setLoading2] = useState8(true);
3154
+ const [error, setError2] = useState8(null);
3155
+ const [confirmAction, setConfirmAction] = useState8(null);
3138
3156
  const activeActionRef = useRef6("install");
3139
3157
  const mountedRef = useRef6(true);
3140
3158
  const hasRefreshed = useRef6(false);
3141
3159
  const stream = useBrewStream();
3142
- useEffect12(() => {
3160
+ useEffect11(() => {
3143
3161
  mountedRef.current = true;
3144
3162
  return () => {
3145
3163
  mountedRef.current = false;
3146
3164
  };
3147
3165
  }, []);
3148
- useEffect12(() => {
3166
+ useEffect11(() => {
3149
3167
  if (!packageName) return;
3150
3168
  setLoading2(true);
3151
3169
  const fetchInfo = async () => {
@@ -3170,7 +3188,7 @@ function PackageInfoView() {
3170
3188
  }
3171
3189
  });
3172
3190
  }, [packageName, packageType]);
3173
- useEffect12(() => {
3191
+ useEffect11(() => {
3174
3192
  if (!stream.isRunning && !stream.error && stream.lines.length > 0 && !hasRefreshed.current && packageName) {
3175
3193
  hasRefreshed.current = true;
3176
3194
  const refreshFn = packageType === "cask" ? getCaskInfo(packageName).then((c) => c ? { ...c, installed: c.installed ? [{ version: c.installed }] : [] } : null) : getFormulaInfo(packageName);
@@ -3330,7 +3348,7 @@ function PackageInfoView() {
3330
3348
  }
3331
3349
 
3332
3350
  // src/views/services.tsx
3333
- import { useEffect as useEffect13, useRef as useRef7, useState as useState10 } from "react";
3351
+ import { useEffect as useEffect12, useRef as useRef7, useState as useState9 } from "react";
3334
3352
  import { Box as Box19, Text as Text22 } from "ink";
3335
3353
  import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
3336
3354
  var STATUS_VARIANTS = {
@@ -3347,10 +3365,10 @@ function humaniseServiceError(message) {
3347
3365
  }
3348
3366
  function ServicesView() {
3349
3367
  const { services, loading, errors, fetchServices, serviceAction: serviceAction2 } = useBrewStore();
3350
- const [cursor, setCursor] = useState10(0);
3351
- const [actionInProgress, setActionInProgress] = useState10(false);
3352
- const [confirmAction, setConfirmAction] = useState10(null);
3353
- const [lastError, setLastError] = useState10(null);
3368
+ const [cursor, setCursor] = useState9(0);
3369
+ const [actionInProgress, setActionInProgress] = useState9(false);
3370
+ const [confirmAction, setConfirmAction] = useState9(null);
3371
+ const [lastError, setLastError] = useState9(null);
3354
3372
  const containerRef = useRef7(null);
3355
3373
  const { width: containerWidth } = useContainerSize(containerRef);
3356
3374
  const cols = containerWidth > 0 ? containerWidth : 80;
@@ -3366,7 +3384,7 @@ function ServicesView() {
3366
3384
  fallbackReservedRows: lastError || actionInProgress ? 16 : 14,
3367
3385
  minRows: 1
3368
3386
  });
3369
- useEffect13(() => {
3387
+ useEffect12(() => {
3370
3388
  fetchServices();
3371
3389
  }, []);
3372
3390
  useViewInput((input, key) => {
@@ -3477,25 +3495,25 @@ function ServicesView() {
3477
3495
  }
3478
3496
 
3479
3497
  // src/views/doctor.tsx
3480
- import { useEffect as useEffect14, useRef as useRef8, useState as useState11 } from "react";
3498
+ import { useEffect as useEffect13, useRef as useRef8, useState as useState10 } from "react";
3481
3499
  import { Box as Box20, Text as Text23 } from "ink";
3482
3500
  import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
3483
3501
  function DoctorView() {
3484
3502
  const { doctorWarnings, doctorClean, loading, errors, fetchDoctor } = useBrewStore();
3485
- const [cursor, setCursor] = useState11(0);
3503
+ const [cursor, setCursor] = useState10(0);
3486
3504
  const visibleWarnings = useVisibleRows({
3487
3505
  reservedRows: 6,
3488
3506
  fallbackReservedRows: 14,
3489
3507
  minRows: 1
3490
3508
  });
3491
3509
  const mountedRef = useRef8(true);
3492
- useEffect14(() => {
3510
+ useEffect13(() => {
3493
3511
  mountedRef.current = true;
3494
3512
  return () => {
3495
3513
  mountedRef.current = false;
3496
3514
  };
3497
3515
  }, []);
3498
- useEffect14(() => {
3516
+ useEffect13(() => {
3499
3517
  fetchDoctor();
3500
3518
  }, []);
3501
3519
  useViewInput((input, key) => {
@@ -3533,7 +3551,7 @@ function DoctorView() {
3533
3551
  }
3534
3552
 
3535
3553
  // src/views/profiles.tsx
3536
- import { useEffect as useEffect15, useRef as useRef9, useState as useState12 } from "react";
3554
+ import { useEffect as useEffect14, useRef as useRef9, useState as useState11 } from "react";
3537
3555
  import { Box as Box25 } from "ink";
3538
3556
 
3539
3557
  // src/stores/profile-store.ts
@@ -3905,23 +3923,23 @@ function ProfileEditDesc({ name, defaultDesc, loadError, onSubmit }) {
3905
3923
  import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
3906
3924
  function ProfilesView() {
3907
3925
  const { profileNames, selectedProfile, loading, loadError, fetchProfiles, loadProfile: loadProfile2, exportCurrent, deleteProfile: deleteProfile2, updateProfile: updateProfile2 } = useProfileStore();
3908
- const [cursor, setCursor] = useState12(0);
3909
- const [mode, setMode] = useState12("list");
3910
- const [newName, setNewName] = useState12("");
3911
- const [confirmDelete, setConfirmDelete] = useState12(false);
3912
- const [editName, setEditName] = useState12("");
3913
- const [editDesc, setEditDesc] = useState12("");
3914
- const [importLines, setImportLines] = useState12([]);
3915
- const [importRunning, setImportRunning] = useState12(false);
3916
- const [importHadError, setImportHadError] = useState12(false);
3917
- const [importProfile2, setImportProfile] = useState12(null);
3926
+ const [cursor, setCursor] = useState11(0);
3927
+ const [mode, setMode] = useState11("list");
3928
+ const [newName, setNewName] = useState11("");
3929
+ const [confirmDelete, setConfirmDelete] = useState11(false);
3930
+ const [editName, setEditName] = useState11("");
3931
+ const [editDesc, setEditDesc] = useState11("");
3932
+ const [importLines, setImportLines] = useState11([]);
3933
+ const [importRunning, setImportRunning] = useState11(false);
3934
+ const [importHadError, setImportHadError] = useState11(false);
3935
+ const [importProfile2, setImportProfile] = useState11(null);
3918
3936
  const { openModal, closeModal } = useModalStore();
3919
3937
  const importGenRef = useRef9(null);
3920
3938
  const mountedRef = useRef9(true);
3921
- useEffect15(() => {
3939
+ useEffect14(() => {
3922
3940
  fetchProfiles();
3923
3941
  }, []);
3924
- useEffect15(() => {
3942
+ useEffect14(() => {
3925
3943
  mountedRef.current = true;
3926
3944
  return () => {
3927
3945
  mountedRef.current = false;
@@ -3929,7 +3947,7 @@ function ProfilesView() {
3929
3947
  importGenRef.current = null;
3930
3948
  };
3931
3949
  }, []);
3932
- useEffect15(() => {
3950
+ useEffect14(() => {
3933
3951
  if (mode !== "list") {
3934
3952
  openModal();
3935
3953
  return () => {
@@ -4105,7 +4123,7 @@ function ProfilesView() {
4105
4123
  }
4106
4124
 
4107
4125
  // src/views/smart-cleanup.tsx
4108
- import { useEffect as useEffect16, useRef as useRef10, useState as useState13 } from "react";
4126
+ import { useEffect as useEffect15, useRef as useRef10, useState as useState12 } from "react";
4109
4127
  import { Box as Box26, Text as Text28 } from "ink";
4110
4128
 
4111
4129
  // src/stores/cleanup-store.ts
@@ -4229,10 +4247,10 @@ var useCleanupStore = create10((set, get) => ({
4229
4247
  import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
4230
4248
  function SmartCleanupView() {
4231
4249
  const { summary, selected, loading, error, analyze, toggleSelect, selectAll } = useCleanupStore();
4232
- const [cursor, setCursor] = useState13(0);
4233
- const [confirmClean, setConfirmClean] = useState13(false);
4234
- const [confirmForce, setConfirmForce] = useState13(false);
4235
- const [failedNames, setFailedNames] = useState13([]);
4250
+ const [cursor, setCursor] = useState12(0);
4251
+ const [confirmClean, setConfirmClean] = useState12(false);
4252
+ const [confirmForce, setConfirmForce] = useState12(false);
4253
+ const [failedNames, setFailedNames] = useState12([]);
4236
4254
  const stream = useBrewStream();
4237
4255
  const hasRefreshed = useRef10(false);
4238
4256
  const listRows = useVisibleRows({
@@ -4240,10 +4258,10 @@ function SmartCleanupView() {
4240
4258
  fallbackReservedRows: confirmClean || confirmForce ? 18 : 14,
4241
4259
  minRows: 1
4242
4260
  });
4243
- useEffect16(() => {
4261
+ useEffect15(() => {
4244
4262
  analyze();
4245
4263
  }, []);
4246
- useEffect16(() => {
4264
+ useEffect15(() => {
4247
4265
  if (!stream.isRunning && !stream.error && stream.lines.length > 0 && !hasRefreshed.current) {
4248
4266
  hasRefreshed.current = true;
4249
4267
  void analyze();
@@ -4379,7 +4397,7 @@ function SmartCleanupView() {
4379
4397
  }
4380
4398
 
4381
4399
  // src/views/history.tsx
4382
- import { useEffect as useEffect17, useState as useState14, useMemo as useMemo5 } from "react";
4400
+ import { useEffect as useEffect16, useState as useState13, useMemo as useMemo5 } from "react";
4383
4401
  import { Box as Box27, Text as Text29 } from "ink";
4384
4402
 
4385
4403
  // src/stores/history-store.ts
@@ -4432,12 +4450,12 @@ var ACTION_LABEL_KEYS = {
4432
4450
  var FILTERS = ["all", "install", "uninstall", "upgrade", "upgrade-all"];
4433
4451
  function HistoryView() {
4434
4452
  const { entries, loading, error, fetchHistory, clearHistory: clearHistory2 } = useHistoryStore();
4435
- const [cursor, setCursor] = useState14(0);
4436
- const [filter, setFilter] = useState14("all");
4437
- const [searchQuery, setSearchQuery] = useState14("");
4438
- const [isSearching, setIsSearching] = useState14(false);
4439
- const [confirmClear, setConfirmClear] = useState14(false);
4440
- const [confirmReplay, setConfirmReplay] = useState14(null);
4453
+ const [cursor, setCursor] = useState13(0);
4454
+ const [filter, setFilter] = useState13("all");
4455
+ const [searchQuery, setSearchQuery] = useState13("");
4456
+ const [isSearching, setIsSearching] = useState13(false);
4457
+ const [confirmClear, setConfirmClear] = useState13(false);
4458
+ const [confirmReplay, setConfirmReplay] = useState13(null);
4441
4459
  const stream = useBrewStream();
4442
4460
  const debouncedQuery = useDebounce(searchQuery, 200);
4443
4461
  const { openModal, closeModal } = useModalStore();
@@ -4451,10 +4469,10 @@ function HistoryView() {
4451
4469
  fallbackReservedRows: 16,
4452
4470
  minRows: 1
4453
4471
  });
4454
- useEffect17(() => {
4472
+ useEffect16(() => {
4455
4473
  fetchHistory();
4456
4474
  }, []);
4457
- useEffect17(() => {
4475
+ useEffect16(() => {
4458
4476
  if (isSearching) {
4459
4477
  openModal();
4460
4478
  return () => {
@@ -4595,7 +4613,7 @@ function HistoryView() {
4595
4613
  }
4596
4614
 
4597
4615
  // src/views/security-audit.tsx
4598
- import { useEffect as useEffect18, useState as useState15 } from "react";
4616
+ import { useEffect as useEffect17, useState as useState14 } from "react";
4599
4617
  import { Box as Box28, Text as Text30 } from "ink";
4600
4618
  import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
4601
4619
  var SEVERITY_COLORS = {
@@ -4618,11 +4636,11 @@ function isNetworkError(msg) {
4618
4636
  function SecurityAuditView() {
4619
4637
  const { summary, loading, error, scan, cachedAt } = useSecurityStore();
4620
4638
  const navigate = useNavigationStore((s) => s.navigate);
4621
- const [cursor, setCursor] = useState15(0);
4622
- const [expandedPkg, setExpandedPkg] = useState15(null);
4623
- const [confirmUpgrade, setConfirmUpgrade] = useState15(null);
4639
+ const [cursor, setCursor] = useState14(0);
4640
+ const [expandedPkg, setExpandedPkg] = useState14(null);
4641
+ const [confirmUpgrade, setConfirmUpgrade] = useState14(null);
4624
4642
  const stream = useBrewStream();
4625
- useEffect18(() => {
4643
+ useEffect17(() => {
4626
4644
  scan();
4627
4645
  }, []);
4628
4646
  const results = summary?.results ?? [];
@@ -4727,7 +4745,7 @@ function SecurityAuditView() {
4727
4745
  }
4728
4746
 
4729
4747
  // src/views/account.tsx
4730
- import { useState as useState16 } from "react";
4748
+ import { useState as useState15 } from "react";
4731
4749
  import { Box as Box29, Text as Text31 } from "ink";
4732
4750
  import { TextInput as TextInput5 } from "@inkjs/ui";
4733
4751
 
@@ -4809,13 +4827,13 @@ async function redeemPromoCode(code) {
4809
4827
  import { Fragment as Fragment5, jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
4810
4828
  function AccountView() {
4811
4829
  const { status, license, deactivate: deactivate2, revalidate: revalidate2, degradation } = useLicenseStore();
4812
- const [confirmDeactivate, setConfirmDeactivate] = useState16(false);
4813
- const [deactivating, setDeactivating] = useState16(false);
4814
- const [deactivateError, setDeactivateError] = useState16(null);
4815
- const [promoMode, setPromoMode] = useState16(false);
4816
- const [promoLoading, setPromoLoading] = useState16(false);
4817
- const [promoResult, setPromoResult] = useState16(null);
4818
- const [revalidating, setRevalidating] = useState16(false);
4830
+ const [confirmDeactivate, setConfirmDeactivate] = useState15(false);
4831
+ const [deactivating, setDeactivating] = useState15(false);
4832
+ const [deactivateError, setDeactivateError] = useState15(null);
4833
+ const [promoMode, setPromoMode] = useState15(false);
4834
+ const [promoLoading, setPromoLoading] = useState15(false);
4835
+ const [promoResult, setPromoResult] = useState15(null);
4836
+ const [revalidating, setRevalidating] = useState15(false);
4819
4837
  useViewInput((input, key) => {
4820
4838
  if (confirmDeactivate || deactivating || promoMode || revalidating) {
4821
4839
  if (key.escape && promoMode) {
@@ -4959,13 +4977,13 @@ function AccountView() {
4959
4977
  status === "pro" || status === "team" || status === "expired" ? `v ${t("hint_revalidate")} ` : "",
4960
4978
  revalidating ? t("account_revalidating") : "",
4961
4979
  " ",
4962
- t("app_version", { version: "1.2.0" })
4980
+ t("app_version", { version: "1.2.1" })
4963
4981
  ] }) })
4964
4982
  ] });
4965
4983
  }
4966
4984
 
4967
4985
  // src/views/rollback.tsx
4968
- import { useCallback as useCallback3, useEffect as useEffect19, useRef as useRef11, useState as useState17 } from "react";
4986
+ import { useCallback as useCallback3, useEffect as useEffect18, useRef as useRef11, useState as useState16 } from "react";
4969
4987
  import { Box as Box30, Text as Text32 } from "ink";
4970
4988
 
4971
4989
  // src/stores/rollback-store.ts
@@ -5001,10 +5019,10 @@ async function detectStrategy(name, targetVersion, packageType) {
5001
5019
  }
5002
5020
  return { strategy: "pin-only" };
5003
5021
  }
5004
- async function buildRollbackPlan(snapshot, isPro) {
5022
+ async function buildRollbackPlan(snapshot2, isPro) {
5005
5023
  if (!isPro) throw new Error("Pro license required");
5006
5024
  const current = await captureSnapshot();
5007
- const diff = diffSnapshots(snapshot, current);
5025
+ const diff = diffSnapshots(snapshot2, current);
5008
5026
  const actions = [];
5009
5027
  const warnings = [];
5010
5028
  for (const entry of diff.upgraded) {
@@ -5070,8 +5088,8 @@ async function buildRollbackPlan(snapshot, isPro) {
5070
5088
  warnings.push(`${caskPinCount} cask(s) will be pinned only (version restoration not supported)`);
5071
5089
  }
5072
5090
  const canExecute = actions.some((a) => a.strategy !== "unavailable");
5073
- const snapshotLabel = snapshot.label ?? "Auto";
5074
- const snapshotDate = new Date(snapshot.capturedAt).toLocaleString();
5091
+ const snapshotLabel = snapshot2.label ?? "Auto";
5092
+ const snapshotDate = new Date(snapshot2.capturedAt).toLocaleString();
5075
5093
  logger.debug("Built rollback plan", { actionCount: actions.length, canExecute });
5076
5094
  return {
5077
5095
  snapshotLabel,
@@ -5159,14 +5177,14 @@ var useRollbackStore = create12((set) => ({
5159
5177
  set({ error: err instanceof Error ? err.message : String(err), loading: false });
5160
5178
  }
5161
5179
  },
5162
- selectSnapshot: async (snapshot, isPro) => {
5163
- if (!snapshot) {
5180
+ selectSnapshot: async (snapshot2, isPro) => {
5181
+ if (!snapshot2) {
5164
5182
  set({ selectedSnapshot: null, plan: null, planError: null });
5165
5183
  return;
5166
5184
  }
5167
- set({ selectedSnapshot: snapshot, plan: null, planLoading: true, planError: null });
5185
+ set({ selectedSnapshot: snapshot2, plan: null, planLoading: true, planError: null });
5168
5186
  try {
5169
- const plan = await buildRollbackPlan(snapshot, isPro);
5187
+ const plan = await buildRollbackPlan(snapshot2, isPro);
5170
5188
  set({ plan, planLoading: false });
5171
5189
  } catch (err) {
5172
5190
  set({ planError: err instanceof Error ? err.message : String(err), planLoading: false });
@@ -5271,11 +5289,11 @@ function PlanView({ plan }) {
5271
5289
  function RollbackView() {
5272
5290
  const isPro = useLicenseStore((s) => s.isPro);
5273
5291
  const { snapshots, loading, error, plan, planLoading, planError, fetchSnapshots, selectSnapshot, clearPlan } = useRollbackStore();
5274
- const [cursor, setCursor] = useState17(0);
5275
- const [phase, setPhase] = useState17("list");
5276
- const [streamLines, setStreamLines] = useState17([]);
5277
- const [streamRunning, setStreamRunning] = useState17(false);
5278
- const [streamError, setStreamError] = useState17(null);
5292
+ const [cursor, setCursor] = useState16(0);
5293
+ const [phase, setPhase] = useState16("list");
5294
+ const [streamLines, setStreamLines] = useState16([]);
5295
+ const [streamRunning, setStreamRunning] = useState16(false);
5296
+ const [streamError, setStreamError] = useState16(null);
5279
5297
  const generatorRef = useRef11(null);
5280
5298
  const mountedRef = useRef11(true);
5281
5299
  const snapshotRows = useVisibleRows({
@@ -5283,14 +5301,14 @@ function RollbackView() {
5283
5301
  fallbackReservedRows: 14,
5284
5302
  minRows: 1
5285
5303
  });
5286
- useEffect19(() => {
5304
+ useEffect18(() => {
5287
5305
  mountedRef.current = true;
5288
5306
  return () => {
5289
5307
  mountedRef.current = false;
5290
5308
  void generatorRef.current?.return(void 0);
5291
5309
  };
5292
5310
  }, []);
5293
- useEffect19(() => {
5311
+ useEffect18(() => {
5294
5312
  void fetchSnapshots(isPro());
5295
5313
  }, []);
5296
5314
  const runRollback = useCallback3(async (p) => {
@@ -5427,7 +5445,7 @@ function RollbackView() {
5427
5445
  }
5428
5446
 
5429
5447
  // src/views/brewfile.tsx
5430
- import { useCallback as useCallback4, useEffect as useEffect20, useRef as useRef12, useState as useState18 } from "react";
5448
+ import { useCallback as useCallback4, useEffect as useEffect19, useRef as useRef12, useState as useState17 } from "react";
5431
5449
  import { Box as Box31, Text as Text33 } from "ink";
5432
5450
  import { TextInput as TextInput6 } from "@inkjs/ui";
5433
5451
  import { jsx as jsx35, jsxs as jsxs32 } from "react/jsx-runtime";
@@ -5473,14 +5491,14 @@ function DriftSummary({ drift }) {
5473
5491
  function BrewfileView() {
5474
5492
  const isPro = useLicenseStore((s) => s.isPro);
5475
5493
  const { schema, drift, loading, driftLoading, error, load, createFromCurrent } = useBrewfileStore();
5476
- const [phase, setPhase] = useState18("overview");
5477
- const [streamLines, setStreamLines] = useState18([]);
5478
- const [streamRunning, setStreamRunning] = useState18(false);
5479
- const [streamError, setStreamError] = useState18(null);
5480
- const [resultMessage, setResultMessage] = useState18("");
5494
+ const [phase, setPhase] = useState17("overview");
5495
+ const [streamLines, setStreamLines] = useState17([]);
5496
+ const [streamRunning, setStreamRunning] = useState17(false);
5497
+ const [streamError, setStreamError] = useState17(null);
5498
+ const [resultMessage, setResultMessage] = useState17("");
5481
5499
  const generatorRef = useRef12(null);
5482
5500
  const mountedRef = useRef12(true);
5483
- useEffect20(() => {
5501
+ useEffect19(() => {
5484
5502
  mountedRef.current = true;
5485
5503
  void load();
5486
5504
  return () => {
@@ -5656,7 +5674,7 @@ function BrewfileView() {
5656
5674
  }
5657
5675
 
5658
5676
  // src/views/sync.tsx
5659
- import { useCallback as useCallback5, useEffect as useEffect21, useState as useState19 } from "react";
5677
+ import { useCallback as useCallback5, useEffect as useEffect20, useState as useState18 } from "react";
5660
5678
  import { Box as Box32, Text as Text34 } from "ink";
5661
5679
  import { Fragment as Fragment6, jsx as jsx36, jsxs as jsxs33 } from "react/jsx-runtime";
5662
5680
  function OverviewSection({
@@ -5782,14 +5800,14 @@ function SyncView() {
5782
5800
  const isPro = useLicenseStore((s) => s.isPro);
5783
5801
  const navigate = useNavigationStore((s) => s.navigate);
5784
5802
  const { config, lastResult, conflicts, loading, error, initialize, syncNow, resolveConflicts } = useSyncStore();
5785
- const [phase, setPhase] = useState19("overview");
5786
- const [syncError, setSyncError] = useState19(null);
5787
- const [conflictEntries, setConflictEntries] = useState19([]);
5788
- const [cursor, setCursor] = useState19(0);
5789
- useEffect21(() => {
5803
+ const [phase, setPhase] = useState18("overview");
5804
+ const [syncError, setSyncError] = useState18(null);
5805
+ const [conflictEntries, setConflictEntries] = useState18([]);
5806
+ const [cursor, setCursor] = useState18(0);
5807
+ useEffect20(() => {
5790
5808
  void initialize(isPro());
5791
5809
  }, []);
5792
- useEffect21(() => {
5810
+ useEffect20(() => {
5793
5811
  if (conflicts.length > 0) {
5794
5812
  setConflictEntries(
5795
5813
  conflicts.map((c) => ({ conflict: c, resolution: "pending" }))
@@ -5954,7 +5972,7 @@ function SyncView() {
5954
5972
  }
5955
5973
 
5956
5974
  // src/views/compliance.tsx
5957
- import { useCallback as useCallback6, useEffect as useEffect22, useRef as useRef13, useState as useState20 } from "react";
5975
+ import { useCallback as useCallback6, useEffect as useEffect21, useRef as useRef13, useState as useState19 } from "react";
5958
5976
  import { Box as Box33, Text as Text35 } from "ink";
5959
5977
  import { TextInput as TextInput7 } from "@inkjs/ui";
5960
5978
 
@@ -6081,13 +6099,13 @@ function ViolationList({ violations }) {
6081
6099
  function ComplianceView() {
6082
6100
  const isPro = useLicenseStore((s) => s.isPro);
6083
6101
  const { policy, report, loading, error, importPolicy, runCheck } = useComplianceStore();
6084
- const [phase, setPhase] = useState20("overview");
6085
- const [resultMessage, setResultMessage] = useState20(null);
6086
- const [streamLines, setStreamLines] = useState20([]);
6087
- const [streamRunning, setStreamRunning] = useState20(false);
6102
+ const [phase, setPhase] = useState19("overview");
6103
+ const [resultMessage, setResultMessage] = useState19(null);
6104
+ const [streamLines, setStreamLines] = useState19([]);
6105
+ const [streamRunning, setStreamRunning] = useState19(false);
6088
6106
  const generatorRef = useRef13(null);
6089
6107
  const mountedRef = useRef13(true);
6090
- useEffect22(() => {
6108
+ useEffect21(() => {
6091
6109
  mountedRef.current = true;
6092
6110
  return () => {
6093
6111
  mountedRef.current = false;
@@ -6292,7 +6310,7 @@ function ComplianceView() {
6292
6310
  import { Fragment as Fragment7, jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
6293
6311
  function LicenseInitializer() {
6294
6312
  const initLicense = useLicenseStore((s) => s.initialize);
6295
- useEffect23(() => {
6313
+ useEffect22(() => {
6296
6314
  initLicense();
6297
6315
  }, []);
6298
6316
  return null;
@@ -6345,8 +6363,8 @@ function App() {
6345
6363
  const { exit } = useApp();
6346
6364
  const currentView = useNavigationStore((s) => s.currentView);
6347
6365
  const isTestEnv = typeof process !== "undefined" && false;
6348
- const [showWelcome, setShowWelcome] = useState21(isTestEnv ? false : null);
6349
- useEffect23(() => {
6366
+ const [showWelcome, setShowWelcome] = useState20(isTestEnv ? false : null);
6367
+ useEffect22(() => {
6350
6368
  if (isTestEnv) return;
6351
6369
  void hasCompletedOnboarding().then((done) => setShowWelcome(!done));
6352
6370
  }, []);
@@ -6443,7 +6461,7 @@ async function reportError(err, context = {}) {
6443
6461
  const config = await resolveConfig();
6444
6462
  if (!config.enabled || !config.endpoint) return;
6445
6463
  const machineId = await getMachineId();
6446
- const version = true ? "1.2.0" : "unknown";
6464
+ const version = true ? "1.2.1" : "unknown";
6447
6465
  await postReport(buildReport("error", err, context, machineId, version), config);
6448
6466
  }
6449
6467
  async function installCrashReporter() {
@@ -6452,7 +6470,7 @@ async function installCrashReporter() {
6452
6470
  if (!config.enabled || !config.endpoint) return;
6453
6471
  _installed = true;
6454
6472
  const machineId = await getMachineId();
6455
- const version = true ? "1.2.0" : "unknown";
6473
+ const version = true ? "1.2.1" : "unknown";
6456
6474
  process.on("uncaughtException", (err) => {
6457
6475
  void postReport(buildReport("fatal", err, { kind: "uncaughtException" }, machineId, version), config);
6458
6476
  });
@@ -6467,7 +6485,7 @@ import { jsx as jsx39 } from "react/jsx-runtime";
6467
6485
  var [, , command, arg] = process.argv;
6468
6486
  async function runCli() {
6469
6487
  if (command === "--version" || command === "-v" || command === "version") {
6470
- process.stdout.write("1.2.0\n");
6488
+ process.stdout.write("1.2.1\n");
6471
6489
  return;
6472
6490
  }
6473
6491
  await ensureDataDirs();
@@ -6650,7 +6668,7 @@ async function ensureBrewBarRunning() {
6650
6668
  await useLicenseStore.getState().initialize();
6651
6669
  if (!useLicenseStore.getState().isPro()) return;
6652
6670
  const { isBrewBarInstalled, installBrewBar, launchBrewBar } = await import("./brewbar-installer-GWJ76J6G.js");
6653
- const { checkBrewBarVersion } = await import("./version-check-MJZDQG73.js");
6671
+ const { checkBrewBarVersion } = await import("./version-check-AIYMRDFF.js");
6654
6672
  try {
6655
6673
  if (!await isBrewBarInstalled()) {
6656
6674
  console.log(t("cli_brewbarInstalling"));