brew-tui 0.1.0
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/LICENSE +21 -0
- package/README.md +105 -0
- package/bin/brew-tui.js +2 -0
- package/build/brewbar-installer-CPCOE3MI.js +64 -0
- package/build/brewbar-installer-CPCOE3MI.js.map +1 -0
- package/build/chunk-3BK3B53S.js +55 -0
- package/build/chunk-3BK3B53S.js.map +1 -0
- package/build/chunk-P6PTN4HR.js +1140 -0
- package/build/chunk-P6PTN4HR.js.map +1 -0
- package/build/history-logger-LQT622M2.js +12 -0
- package/build/history-logger-LQT622M2.js.map +1 -0
- package/build/index.js +3338 -0
- package/build/index.js.map +1 -0
- package/package.json +66 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MoLines Designs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Brew-TUI
|
|
2
|
+
|
|
3
|
+
A visual terminal UI for [Homebrew](https://brew.sh) package management.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Dashboard** -- overview of installed packages, outdated counts, services, and system info
|
|
12
|
+
- **Installed** -- browse and filter formulae and casks with version info and status badges
|
|
13
|
+
- **Search** -- find and install packages directly from the TUI
|
|
14
|
+
- **Outdated** -- see available upgrades with version comparison arrows, upgrade individually or all at once
|
|
15
|
+
- **Services** -- start, stop, and restart Homebrew services
|
|
16
|
+
- **Doctor** -- run `brew doctor` and see warnings at a glance
|
|
17
|
+
- **Package Info** -- detailed view with dependencies, caveats, and quick install/uninstall
|
|
18
|
+
|
|
19
|
+
### Pro Features
|
|
20
|
+
|
|
21
|
+
- **Profiles** -- export and import your Homebrew setup across machines
|
|
22
|
+
- **Smart Cleanup** -- find orphaned packages and reclaim disk space
|
|
23
|
+
- **Action History** -- track every install, uninstall, and upgrade
|
|
24
|
+
- **Security Audit** -- scan packages against the OSV vulnerability database
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# npm / pnpm / yarn / bun (all use the same npm registry)
|
|
30
|
+
npm install -g brew-tui
|
|
31
|
+
pnpm add -g brew-tui
|
|
32
|
+
yarn global add brew-tui
|
|
33
|
+
bun add -g brew-tui
|
|
34
|
+
|
|
35
|
+
# Homebrew
|
|
36
|
+
brew tap MoLinesGitHub/tap
|
|
37
|
+
brew install brew-tui
|
|
38
|
+
|
|
39
|
+
# GitHub Packages
|
|
40
|
+
npm install -g @MoLinesGitHub/brew-tui --registry https://npm.pkg.github.com
|
|
41
|
+
|
|
42
|
+
# npx (run without installing)
|
|
43
|
+
npx brew-tui
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
brew-tui # Launch the TUI
|
|
50
|
+
brew-tui status # Show license status
|
|
51
|
+
brew-tui activate <key> # Activate Pro license
|
|
52
|
+
brew-tui deactivate # Deactivate Pro license
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Install BrewBar (Pro)
|
|
56
|
+
|
|
57
|
+
BrewBar is a companion macOS menu bar app that shows outdated package counts, sends notifications, and lets you upgrade packages without opening a terminal. Pro users can install it directly from the CLI:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
brew-tui install-brewbar # Download & install to /Applications
|
|
61
|
+
brew-tui install-brewbar --force # Reinstall / update
|
|
62
|
+
brew-tui uninstall-brewbar # Remove from /Applications
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Keyboard Navigation
|
|
66
|
+
|
|
67
|
+
| Key | Action |
|
|
68
|
+
|-----|--------|
|
|
69
|
+
| `1`-`0` | Jump to view |
|
|
70
|
+
| `Tab` / `Shift+Tab` | Cycle views |
|
|
71
|
+
| `j` / `k` | Navigate lists |
|
|
72
|
+
| `Enter` | Select / confirm |
|
|
73
|
+
| `/` | Search / filter |
|
|
74
|
+
| `Escape` | Go back |
|
|
75
|
+
| `L` | Toggle language (en/es) |
|
|
76
|
+
| `q` | Quit |
|
|
77
|
+
|
|
78
|
+
## Language
|
|
79
|
+
|
|
80
|
+
Brew-TUI supports English and Spanish. The language is detected automatically from your system locale (`LANG` environment variable). You can also:
|
|
81
|
+
|
|
82
|
+
- Pass `--lang=es` or `--lang=en` as a CLI flag
|
|
83
|
+
- Press `L` inside the TUI to toggle between languages
|
|
84
|
+
|
|
85
|
+
## BrewBar
|
|
86
|
+
|
|
87
|
+
BrewBar is a companion macOS menu bar app (Swift 6 / SwiftUI) that shows outdated package counts, sends notifications, and lets you upgrade packages without opening a terminal.
|
|
88
|
+
|
|
89
|
+
BrewBar lives in the `menubar/` directory and is built separately with [Tuist](https://tuist.io):
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
cd menubar
|
|
93
|
+
tuist generate
|
|
94
|
+
xcodebuild -workspace BrewBar.xcworkspace -scheme BrewBar build
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Requirements
|
|
98
|
+
|
|
99
|
+
- **Node.js** >= 18
|
|
100
|
+
- **Homebrew** installed on your system
|
|
101
|
+
- **macOS** 14+ (for BrewBar)
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
[MIT](LICENSE) -- MoLines Designs
|
package/bin/brew-tui.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
t,
|
|
3
|
+
verifyPro
|
|
4
|
+
} from "./chunk-P6PTN4HR.js";
|
|
5
|
+
|
|
6
|
+
// src/lib/brewbar-installer.ts
|
|
7
|
+
import { rm, access } from "fs/promises";
|
|
8
|
+
import { createWriteStream } from "fs";
|
|
9
|
+
import { pipeline } from "stream/promises";
|
|
10
|
+
import { execFile } from "child_process";
|
|
11
|
+
import { promisify } from "util";
|
|
12
|
+
var execFileAsync = promisify(execFile);
|
|
13
|
+
var BREWBAR_APP_PATH = "/Applications/BrewBar.app";
|
|
14
|
+
var DOWNLOAD_URL = "https://github.com/MoLinesGitHub/Brew-TUI/releases/latest/download/BrewBar.app.zip";
|
|
15
|
+
var TMP_ZIP = "/tmp/BrewBar.app.zip";
|
|
16
|
+
async function isBrewBarInstalled() {
|
|
17
|
+
try {
|
|
18
|
+
await access(BREWBAR_APP_PATH);
|
|
19
|
+
return true;
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function installBrewBar(force = false) {
|
|
25
|
+
if (process.platform !== "darwin") {
|
|
26
|
+
throw new Error(t("cli_brewbarMacOnly"));
|
|
27
|
+
}
|
|
28
|
+
if (!verifyPro()) {
|
|
29
|
+
throw new Error(t("cli_brewbarProRequired"));
|
|
30
|
+
}
|
|
31
|
+
if (!force && await isBrewBarInstalled()) {
|
|
32
|
+
throw new Error(t("cli_brewbarAlreadyInstalled"));
|
|
33
|
+
}
|
|
34
|
+
console.log(t("cli_brewbarInstalling"));
|
|
35
|
+
const res = await fetch(DOWNLOAD_URL);
|
|
36
|
+
if (!res.ok || !res.body) {
|
|
37
|
+
throw new Error(t("cli_brewbarDownloadFailed", { error: `HTTP ${res.status}` }));
|
|
38
|
+
}
|
|
39
|
+
const fileStream = createWriteStream(TMP_ZIP);
|
|
40
|
+
await pipeline(res.body, fileStream);
|
|
41
|
+
if (force && await isBrewBarInstalled()) {
|
|
42
|
+
await rm(BREWBAR_APP_PATH, { recursive: true, force: true });
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
await execFileAsync("ditto", ["-xk", TMP_ZIP, "/Applications/"]);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
throw new Error(t("cli_brewbarDownloadFailed", { error: err instanceof Error ? err.message : String(err) }));
|
|
48
|
+
} finally {
|
|
49
|
+
await rm(TMP_ZIP, { force: true }).catch(() => {
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function uninstallBrewBar() {
|
|
54
|
+
if (!await isBrewBarInstalled()) {
|
|
55
|
+
throw new Error(t("cli_brewbarNotInstalled"));
|
|
56
|
+
}
|
|
57
|
+
await rm(BREWBAR_APP_PATH, { recursive: true, force: true });
|
|
58
|
+
}
|
|
59
|
+
export {
|
|
60
|
+
installBrewBar,
|
|
61
|
+
isBrewBarInstalled,
|
|
62
|
+
uninstallBrewBar
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=brewbar-installer-CPCOE3MI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/brewbar-installer.ts"],"sourcesContent":["import { rm, access } from 'node:fs/promises';\nimport { createWriteStream } from 'node:fs';\nimport { pipeline } from 'node:stream/promises';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { t } from '../i18n/index.js';\nimport { verifyPro } from './license/pro-guard.js';\n\nconst execFileAsync = promisify(execFile);\nconst BREWBAR_APP_PATH = '/Applications/BrewBar.app';\nconst DOWNLOAD_URL = 'https://github.com/MoLinesGitHub/Brew-TUI/releases/latest/download/BrewBar.app.zip';\nconst TMP_ZIP = '/tmp/BrewBar.app.zip';\n\nexport async function isBrewBarInstalled(): Promise<boolean> {\n try {\n await access(BREWBAR_APP_PATH);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function installBrewBar(force = false): Promise<void> {\n // macOS only\n if (process.platform !== 'darwin') {\n throw new Error(t('cli_brewbarMacOnly'));\n }\n\n // Pro check\n if (!verifyPro()) {\n throw new Error(t('cli_brewbarProRequired'));\n }\n\n // Already installed check\n if (!force && await isBrewBarInstalled()) {\n throw new Error(t('cli_brewbarAlreadyInstalled'));\n }\n\n console.log(t('cli_brewbarInstalling'));\n\n // Download zip\n const res = await fetch(DOWNLOAD_URL);\n if (!res.ok || !res.body) {\n throw new Error(t('cli_brewbarDownloadFailed', { error: `HTTP ${res.status}` }));\n }\n\n // Write to tmp file\n const fileStream = createWriteStream(TMP_ZIP);\n await pipeline(res.body as any, fileStream);\n\n // Remove old app if force reinstall\n if (force && await isBrewBarInstalled()) {\n await rm(BREWBAR_APP_PATH, { recursive: true, force: true });\n }\n\n // Unzip to /Applications\n try {\n await execFileAsync('ditto', ['-xk', TMP_ZIP, '/Applications/']);\n } catch (err) {\n throw new Error(t('cli_brewbarDownloadFailed', { error: err instanceof Error ? err.message : String(err) }));\n } finally {\n // Clean up tmp zip\n await rm(TMP_ZIP, { force: true }).catch(() => {});\n }\n}\n\nexport async function uninstallBrewBar(): Promise<void> {\n if (!await isBrewBarInstalled()) {\n throw new Error(t('cli_brewbarNotInstalled'));\n }\n\n await rm(BREWBAR_APP_PATH, { recursive: true, force: true });\n}\n"],"mappings":";;;;;;AAAA,SAAS,IAAI,cAAc;AAC3B,SAAS,yBAAyB;AAClC,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAI1B,IAAM,gBAAgB,UAAU,QAAQ;AACxC,IAAM,mBAAmB;AACzB,IAAM,eAAe;AACrB,IAAM,UAAU;AAEhB,eAAsB,qBAAuC;AAC3D,MAAI;AACF,UAAM,OAAO,gBAAgB;AAC7B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,eAAe,QAAQ,OAAsB;AAEjE,MAAI,QAAQ,aAAa,UAAU;AACjC,UAAM,IAAI,MAAM,EAAE,oBAAoB,CAAC;AAAA,EACzC;AAGA,MAAI,CAAC,UAAU,GAAG;AAChB,UAAM,IAAI,MAAM,EAAE,wBAAwB,CAAC;AAAA,EAC7C;AAGA,MAAI,CAAC,SAAS,MAAM,mBAAmB,GAAG;AACxC,UAAM,IAAI,MAAM,EAAE,6BAA6B,CAAC;AAAA,EAClD;AAEA,UAAQ,IAAI,EAAE,uBAAuB,CAAC;AAGtC,QAAM,MAAM,MAAM,MAAM,YAAY;AACpC,MAAI,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM;AACxB,UAAM,IAAI,MAAM,EAAE,6BAA6B,EAAE,OAAO,QAAQ,IAAI,MAAM,GAAG,CAAC,CAAC;AAAA,EACjF;AAGA,QAAM,aAAa,kBAAkB,OAAO;AAC5C,QAAM,SAAS,IAAI,MAAa,UAAU;AAG1C,MAAI,SAAS,MAAM,mBAAmB,GAAG;AACvC,UAAM,GAAG,kBAAkB,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EAC7D;AAGA,MAAI;AACF,UAAM,cAAc,SAAS,CAAC,OAAO,SAAS,gBAAgB,CAAC;AAAA,EACjE,SAAS,KAAK;AACZ,UAAM,IAAI,MAAM,EAAE,6BAA6B,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC,CAAC;AAAA,EAC7G,UAAE;AAEA,UAAM,GAAG,SAAS,EAAE,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACnD;AACF;AAEA,eAAsB,mBAAkC;AACtD,MAAI,CAAC,MAAM,mBAAmB,GAAG;AAC/B,UAAM,IAAI,MAAM,EAAE,yBAAyB,CAAC;AAAA,EAC9C;AAEA,QAAM,GAAG,kBAAkB,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAC7D;","names":[]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HISTORY_PATH,
|
|
3
|
+
ensureDataDirs,
|
|
4
|
+
requirePro
|
|
5
|
+
} from "./chunk-P6PTN4HR.js";
|
|
6
|
+
|
|
7
|
+
// src/lib/history/history-logger.ts
|
|
8
|
+
import { readFile, writeFile, rename } from "fs/promises";
|
|
9
|
+
var MAX_ENTRIES = 1e3;
|
|
10
|
+
async function loadHistory() {
|
|
11
|
+
requirePro();
|
|
12
|
+
try {
|
|
13
|
+
const raw = await readFile(HISTORY_PATH, "utf-8");
|
|
14
|
+
const file = JSON.parse(raw);
|
|
15
|
+
const entries = file.entries;
|
|
16
|
+
return Array.isArray(entries) ? entries : [];
|
|
17
|
+
} catch {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function saveHistory(entries) {
|
|
22
|
+
await ensureDataDirs();
|
|
23
|
+
const file = { version: 1, entries };
|
|
24
|
+
const tmp = HISTORY_PATH + ".tmp";
|
|
25
|
+
await writeFile(tmp, JSON.stringify(file, null, 2), "utf-8");
|
|
26
|
+
await rename(tmp, HISTORY_PATH);
|
|
27
|
+
}
|
|
28
|
+
async function appendEntry(action, packageName, success, error = null) {
|
|
29
|
+
requirePro();
|
|
30
|
+
const entries = await loadHistory();
|
|
31
|
+
const entry = {
|
|
32
|
+
id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
33
|
+
action,
|
|
34
|
+
packageName,
|
|
35
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
36
|
+
success,
|
|
37
|
+
error
|
|
38
|
+
};
|
|
39
|
+
entries.unshift(entry);
|
|
40
|
+
if (entries.length > MAX_ENTRIES) {
|
|
41
|
+
entries.length = MAX_ENTRIES;
|
|
42
|
+
}
|
|
43
|
+
await saveHistory(entries);
|
|
44
|
+
}
|
|
45
|
+
async function clearHistory() {
|
|
46
|
+
requirePro();
|
|
47
|
+
await saveHistory([]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export {
|
|
51
|
+
loadHistory,
|
|
52
|
+
appendEntry,
|
|
53
|
+
clearHistory
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=chunk-3BK3B53S.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/history/history-logger.ts"],"sourcesContent":["import { readFile, writeFile, rename } from 'node:fs/promises';\nimport { HISTORY_PATH, ensureDataDirs } from '../data-dir.js';\nimport { requirePro } from '../license/pro-guard.js';\nimport type { HistoryEntry, HistoryFile, HistoryAction } from './types.js';\n\nconst MAX_ENTRIES = 1000;\n\nexport async function loadHistory(): Promise<HistoryEntry[]> {\n requirePro();\n\n try {\n const raw = await readFile(HISTORY_PATH, 'utf-8');\n const file = JSON.parse(raw) as HistoryFile;\n const entries = file.entries;\n return Array.isArray(entries) ? entries : [];\n } catch {\n return [];\n }\n}\n\nasync function saveHistory(entries: HistoryEntry[]): Promise<void> {\n await ensureDataDirs();\n const file: HistoryFile = { version: 1, entries };\n const tmp = HISTORY_PATH + '.tmp';\n await writeFile(tmp, JSON.stringify(file, null, 2), 'utf-8');\n await rename(tmp, HISTORY_PATH);\n}\n\nexport async function appendEntry(\n action: HistoryAction,\n packageName: string | null,\n success: boolean,\n error: string | null = null,\n): Promise<void> {\n requirePro();\n const entries = await loadHistory();\n\n const entry: HistoryEntry = {\n id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n action,\n packageName,\n timestamp: new Date().toISOString(),\n success,\n error,\n };\n\n entries.unshift(entry);\n\n if (entries.length > MAX_ENTRIES) {\n entries.length = MAX_ENTRIES;\n }\n\n await saveHistory(entries);\n}\n\nexport async function clearHistory(): Promise<void> {\n requirePro();\n await saveHistory([]);\n}\n"],"mappings":";;;;;;;AAAA,SAAS,UAAU,WAAW,cAAc;AAK5C,IAAM,cAAc;AAEpB,eAAsB,cAAuC;AAC3D,aAAW;AAEX,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,cAAc,OAAO;AAChD,UAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,UAAM,UAAU,KAAK;AACrB,WAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC;AAAA,EAC7C,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,eAAe,YAAY,SAAwC;AACjE,QAAM,eAAe;AACrB,QAAM,OAAoB,EAAE,SAAS,GAAG,QAAQ;AAChD,QAAM,MAAM,eAAe;AAC3B,QAAM,UAAU,KAAK,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG,OAAO;AAC3D,QAAM,OAAO,KAAK,YAAY;AAChC;AAEA,eAAsB,YACpB,QACA,aACA,SACA,QAAuB,MACR;AACf,aAAW;AACX,QAAM,UAAU,MAAM,YAAY;AAElC,QAAM,QAAsB;AAAA,IAC1B,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,IAC3D;AAAA,IACA;AAAA,IACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IACA;AAAA,EACF;AAEA,UAAQ,QAAQ,KAAK;AAErB,MAAI,QAAQ,SAAS,aAAa;AAChC,YAAQ,SAAS;AAAA,EACnB;AAEA,QAAM,YAAY,OAAO;AAC3B;AAEA,eAAsB,eAA8B;AAClD,aAAW;AACX,QAAM,YAAY,CAAC,CAAC;AACtB;","names":[]}
|