brew-tui 0.1.0 → 0.2.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/README.md CHANGED
@@ -100,6 +100,8 @@ xcodebuild -workspace BrewBar.xcworkspace -scheme BrewBar build
100
100
  - **Homebrew** installed on your system
101
101
  - **macOS** 14+ (for BrewBar)
102
102
 
103
+ > **Note:** Brew-TUI is designed for dark terminal backgrounds. Light terminal themes may have reduced visibility.
104
+
103
105
  ## License
104
106
 
105
107
  [MIT](LICENSE) -- MoLines Designs
@@ -1,11 +1,14 @@
1
1
  import {
2
+ fetchWithTimeout,
2
3
  t,
4
+ useLicenseStore,
3
5
  verifyPro
4
- } from "./chunk-P6PTN4HR.js";
6
+ } from "./chunk-KXDTKY3E.js";
5
7
 
6
8
  // src/lib/brewbar-installer.ts
7
- import { rm, access } from "fs/promises";
9
+ import { rm, access, readFile } from "fs/promises";
8
10
  import { createWriteStream } from "fs";
11
+ import { createHash } from "crypto";
9
12
  import { pipeline } from "stream/promises";
10
13
  import { execFile } from "child_process";
11
14
  import { promisify } from "util";
@@ -25,19 +28,39 @@ async function installBrewBar(force = false) {
25
28
  if (process.platform !== "darwin") {
26
29
  throw new Error(t("cli_brewbarMacOnly"));
27
30
  }
28
- if (!verifyPro()) {
31
+ const { license, status } = useLicenseStore.getState();
32
+ if (!verifyPro(license, status)) {
29
33
  throw new Error(t("cli_brewbarProRequired"));
30
34
  }
31
35
  if (!force && await isBrewBarInstalled()) {
32
36
  throw new Error(t("cli_brewbarAlreadyInstalled"));
33
37
  }
34
38
  console.log(t("cli_brewbarInstalling"));
35
- const res = await fetch(DOWNLOAD_URL);
39
+ const res = await fetchWithTimeout(DOWNLOAD_URL, {}, 12e4);
36
40
  if (!res.ok || !res.body) {
37
41
  throw new Error(t("cli_brewbarDownloadFailed", { error: `HTTP ${res.status}` }));
38
42
  }
43
+ const contentLength = Number(res.headers.get("content-length") ?? "0");
44
+ if (contentLength > 200 * 1024 * 1024) {
45
+ throw new Error(t("cli_brewbarDownloadFailed", { error: "Download exceeds 200 MB size limit" }));
46
+ }
39
47
  const fileStream = createWriteStream(TMP_ZIP);
40
48
  await pipeline(res.body, fileStream);
49
+ try {
50
+ const checksumRes = await fetchWithTimeout(`${DOWNLOAD_URL}.sha256`, {}, 15e3);
51
+ if (checksumRes.ok) {
52
+ const expected = (await checksumRes.text()).trim().split(/\s+/)[0].toLowerCase();
53
+ const fileBuffer = await readFile(TMP_ZIP);
54
+ const actual = createHash("sha256").update(fileBuffer).digest("hex");
55
+ if (actual !== expected) {
56
+ await rm(TMP_ZIP, { force: true }).catch(() => {
57
+ });
58
+ throw new Error(t("cli_brewbarDownloadFailed", { error: "SHA-256 checksum mismatch" }));
59
+ }
60
+ }
61
+ } catch (err) {
62
+ if (err instanceof Error && err.message.includes("checksum mismatch")) throw err;
63
+ }
41
64
  if (force && await isBrewBarInstalled()) {
42
65
  await rm(BREWBAR_APP_PATH, { recursive: true, force: true });
43
66
  }
@@ -61,4 +84,3 @@ export {
61
84
  isBrewBarInstalled,
62
85
  uninstallBrewBar
63
86
  };
64
- //# sourceMappingURL=brewbar-installer-CPCOE3MI.js.map
@@ -231,13 +231,13 @@ var en = {
231
231
  account_nameLabel: "Name:",
232
232
  account_planLabel: "Plan:",
233
233
  account_monthlyPrice: "9\u20AC/month",
234
- account_yearlyPrice: "49\u20AC/year",
234
+ account_lifetimePrice: "29\u20AC lifetime",
235
235
  account_keyLabel: "Key:",
236
236
  account_expiresLabel: "Expires:",
237
237
  account_activatedLabel: "Activated:",
238
238
  account_upgradeTitle: "Upgrade to Brew-TUI Pro",
239
239
  account_unlockDesc: "Unlock Profiles, Smart Cleanup, History, Security Audit, and BrewBar (macOS menu bar companion).",
240
- account_pricing: "9\u20AC/month or 49\u20AC/year",
240
+ account_pricing: "9\u20AC/month or 29\u20AC lifetime",
241
241
  account_runActivate: "Run:",
242
242
  account_activateCmd: "brew-tui activate <key>",
243
243
  account_licenseExpired: "Your license has expired. Renew to continue using Pro features.",
@@ -252,10 +252,12 @@ var en = {
252
252
  upgrade_historyDesc: "Track every install, uninstall, and upgrade with timestamps. Search and filter your package management history.",
253
253
  upgrade_security: "Security Audit",
254
254
  upgrade_securityDesc: "Scan installed packages against known vulnerabilities (CVEs). See severity levels, affected versions, and available fixes.",
255
- upgrade_pricing: "9\u20AC/month or 49\u20AC/year",
256
- upgrade_activateWith: "Activate with:",
255
+ upgrade_pricing: "9\u20AC/month or 29\u20AC lifetime",
256
+ upgrade_buyAt: "Buy at:",
257
+ upgrade_buyUrl: "https://buy.polar.sh/polar_cl_QW1ZJ9887bU74drGr7JfujQfm3RKYnn1fuvc53DqD6D",
258
+ upgrade_activateWith: "Then activate with:",
257
259
  upgrade_activateCmd: "brew-tui activate <your-license-key>",
258
- upgrade_proLabel: "Brew-TUI Pro \u2014 9\u20AC/month or 49\u20AC/year \u2014 Includes BrewBar for macOS",
260
+ upgrade_proLabel: "Brew-TUI Pro \u2014 9\u20AC/month or 29\u20AC lifetime \u2014 Includes BrewBar for macOS",
259
261
  // ── Progress Log ──
260
262
  progress_noOutput: "No output yet",
261
263
  // ── Search Input ──
@@ -290,6 +292,7 @@ var en = {
290
292
  cli_brewbarProRequired: "\u2718 BrewBar requires a Pro license.\n Run: brew-tui activate <key>",
291
293
  cli_brewbarMacOnly: "\u2718 BrewBar is only available on macOS.",
292
294
  cli_brewbarDownloadFailed: "\u2718 Failed to download BrewBar: {{error}}",
295
+ cli_deactivateRemoteFailed: "\u26A0 Warning: Could not reach the server to deactivate remotely. The license was removed locally but may still count as active.",
293
296
  // ── License degradation (Layer 15) ──
294
297
  license_offlineWarning: "Your license has not been validated for {{days}} days. Please connect to the internet.",
295
298
  // ── Plurals ──
@@ -533,13 +536,13 @@ var es = {
533
536
  account_nameLabel: "Nombre:",
534
537
  account_planLabel: "Plan:",
535
538
  account_monthlyPrice: "9\u20AC/mes",
536
- account_yearlyPrice: "49\u20AC/a\xF1o",
539
+ account_lifetimePrice: "29\u20AC de por vida",
537
540
  account_keyLabel: "Clave:",
538
541
  account_expiresLabel: "Expira:",
539
542
  account_activatedLabel: "Activado:",
540
543
  account_upgradeTitle: "Actualiza a Brew-TUI Pro",
541
544
  account_unlockDesc: "Desbloquea Perfiles, Limpieza Inteligente, Historial, Auditor\xEDa de Seguridad y BrewBar (barra de men\xFA macOS).",
542
- account_pricing: "9\u20AC/mes o 49\u20AC/a\xF1o",
545
+ account_pricing: "9\u20AC/mes o 29\u20AC de por vida",
543
546
  account_runActivate: "Ejecuta:",
544
547
  account_activateCmd: "brew-tui activate <clave>",
545
548
  account_licenseExpired: "Tu licencia ha expirado. Renueva para seguir usando las funciones Pro.",
@@ -554,10 +557,12 @@ var es = {
554
557
  upgrade_historyDesc: "Rastrea cada instalaci\xF3n, desinstalaci\xF3n y actualizaci\xF3n con marcas de tiempo. Busca y filtra tu historial de gesti\xF3n de paquetes.",
555
558
  upgrade_security: "Auditor\xEDa de Seguridad",
556
559
  upgrade_securityDesc: "Escanea paquetes instalados contra vulnerabilidades conocidas (CVEs). Ve niveles de severidad, versiones afectadas y correcciones disponibles.",
557
- upgrade_pricing: "9\u20AC/mes o 49\u20AC/a\xF1o",
558
- upgrade_activateWith: "Activa con:",
560
+ upgrade_pricing: "9\u20AC/mes o 29\u20AC de por vida",
561
+ upgrade_buyAt: "Compra en:",
562
+ upgrade_buyUrl: "https://buy.polar.sh/polar_cl_QW1ZJ9887bU74drGr7JfujQfm3RKYnn1fuvc53DqD6D",
563
+ upgrade_activateWith: "Luego activa con:",
559
564
  upgrade_activateCmd: "brew-tui activate <tu-clave-de-licencia>",
560
- upgrade_proLabel: "Brew-TUI Pro \u2014 9\u20AC/mes o 49\u20AC/a\xF1o \u2014 Incluye BrewBar para macOS",
565
+ upgrade_proLabel: "Brew-TUI Pro \u2014 9\u20AC/mes o 29\u20AC de por vida \u2014 Incluye BrewBar para macOS",
561
566
  // ── Progress Log ──
562
567
  progress_noOutput: "Sin salida a\xFAn",
563
568
  // ── Search Input ──
@@ -592,6 +597,7 @@ var es = {
592
597
  cli_brewbarProRequired: "\u2718 BrewBar requiere una licencia Pro.\n Ejecuta: brew-tui activate <clave>",
593
598
  cli_brewbarMacOnly: "\u2718 BrewBar solo est\xE1 disponible en macOS.",
594
599
  cli_brewbarDownloadFailed: "\u2718 Error al descargar BrewBar: {{error}}",
600
+ cli_deactivateRemoteFailed: "\u26A0 Advertencia: No se pudo contactar al servidor para desactivar remotamente. La licencia se elimin\xF3 localmente pero puede seguir contando como activa.",
595
601
  // ── License degradation (Layer 15) ──
596
602
  license_offlineWarning: "Tu licencia no se ha validado en {{days}} d\xEDas. Por favor con\xE9ctate a internet.",
597
603
  // ── Plurals ──
@@ -649,12 +655,17 @@ var PROFILES_DIR = join(DATA_DIR, "profiles");
649
655
  var LICENSE_PATH = join(DATA_DIR, "license.json");
650
656
  var HISTORY_PATH = join(DATA_DIR, "history.json");
651
657
  async function ensureDataDirs() {
652
- await mkdir(DATA_DIR, { recursive: true });
653
- await mkdir(PROFILES_DIR, { recursive: true });
658
+ await mkdir(DATA_DIR, { recursive: true, mode: 448 });
659
+ await mkdir(PROFILES_DIR, { recursive: true, mode: 448 });
660
+ }
661
+
662
+ // src/lib/fetch-timeout.ts
663
+ function fetchWithTimeout(url, options = {}, timeoutMs = 15e3) {
664
+ return fetch(url, { ...options, signal: AbortSignal.timeout(timeoutMs) });
654
665
  }
655
666
 
656
667
  // src/lib/license/license-manager.ts
657
- import { readFile, writeFile, rm } from "fs/promises";
668
+ import { readFile, writeFile, rename, rm } from "fs/promises";
658
669
  import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from "crypto";
659
670
 
660
671
  // src/lib/license/polar-api.ts
@@ -673,11 +684,11 @@ function validateApiUrl(url) {
673
684
  async function post(endpoint, body, expectEmpty = false) {
674
685
  const url = `${BASE_URL}/${endpoint}`;
675
686
  validateApiUrl(url);
676
- const res = await fetch(url, {
687
+ const res = await fetchWithTimeout(url, {
677
688
  method: "POST",
678
689
  headers: { "Content-Type": "application/json" },
679
690
  body: JSON.stringify(body)
680
- });
691
+ }, 15e3);
681
692
  if (!res.ok) {
682
693
  let message = `Request failed with status ${res.status}`;
683
694
  try {
@@ -789,8 +800,9 @@ function recordAttempt(success) {
789
800
  }
790
801
  var ENCRYPTION_SECRET = "brew-tui-license-aes256gcm-v1";
791
802
  var SCRYPT_SALT = "brew-tui-salt-v1";
792
- var _derivedKey = scryptSync(ENCRYPTION_SECRET, SCRYPT_SALT, 32);
803
+ var _derivedKey = null;
793
804
  function deriveEncryptionKey() {
805
+ if (!_derivedKey) _derivedKey = scryptSync(ENCRYPTION_SECRET, SCRYPT_SALT, 32);
794
806
  return _derivedKey;
795
807
  }
796
808
  function encryptLicenseData(data) {
@@ -824,6 +836,9 @@ async function loadLicense() {
824
836
  try {
825
837
  const raw = await readFile(LICENSE_PATH, "utf-8");
826
838
  const file = JSON.parse(raw);
839
+ if (file.version !== 1) {
840
+ throw new Error("Unsupported data version");
841
+ }
827
842
  if (file.encrypted && file.iv && file.tag) {
828
843
  const data = decryptLicenseData(file.encrypted, file.iv, file.tag);
829
844
  return data;
@@ -842,7 +857,9 @@ async function saveLicense(data) {
842
857
  await ensureDataDirs();
843
858
  const { encrypted, iv, tag } = encryptLicenseData(data);
844
859
  const file = { version: 1, encrypted, iv, tag };
845
- await writeFile(LICENSE_PATH, JSON.stringify(file, null, 2), { encoding: "utf-8", mode: 384 });
860
+ const tmpPath = LICENSE_PATH + ".tmp";
861
+ await writeFile(tmpPath, JSON.stringify(file, null, 2), { encoding: "utf-8", mode: 384 });
862
+ await rename(tmpPath, LICENSE_PATH);
846
863
  }
847
864
  async function clearLicense() {
848
865
  try {
@@ -930,23 +947,52 @@ async function revalidate(license) {
930
947
  }
931
948
  }
932
949
  async function deactivate(license) {
933
- try {
934
- await deactivateLicense(license.key, license.instanceId);
935
- } catch {
950
+ let remoteSuccess = false;
951
+ for (let attempt = 0; attempt < 3; attempt++) {
952
+ try {
953
+ await deactivateLicense(license.key, license.instanceId);
954
+ remoteSuccess = true;
955
+ break;
956
+ } catch {
957
+ if (attempt < 2) await new Promise((r) => setTimeout(r, 1e3));
958
+ }
936
959
  }
937
960
  await clearLicense();
961
+ return { remoteSuccess };
938
962
  }
939
963
 
940
964
  // src/stores/license-store.ts
941
965
  import { create as create2 } from "zustand";
966
+
967
+ // src/lib/license/anti-tamper.ts
968
+ var _originalIsPro = null;
969
+ var _originalGetState = null;
970
+ var _storeApi = null;
971
+ function initStoreIntegrity(store) {
972
+ _storeApi = store;
973
+ _originalIsPro = store.getState().isPro;
974
+ _originalGetState = store.getState;
975
+ }
976
+ function verifyStoreIntegrity() {
977
+ if (!_storeApi || !_originalIsPro || !_originalGetState) return false;
978
+ const state = _storeApi.getState();
979
+ if (state.isPro !== _originalIsPro) return false;
980
+ if (_storeApi.getState !== _originalGetState) return false;
981
+ if (state.status === "free" && state.isPro()) return false;
982
+ return true;
983
+ }
984
+
985
+ // src/stores/license-store.ts
942
986
  var REVALIDATION_CHECK_MS = 60 * 60 * 1e3;
943
987
  var _revalidating = false;
988
+ var _revalidationInterval = null;
944
989
  var useLicenseStore = create2((set, get) => ({
945
- status: "free",
990
+ status: "validating",
946
991
  license: null,
947
992
  error: null,
948
993
  degradation: "none",
949
994
  initialize: async () => {
995
+ initStoreIntegrity(useLicenseStore);
950
996
  await ensureDataDirs();
951
997
  const license = await loadLicense();
952
998
  if (!license) {
@@ -977,7 +1023,8 @@ var useLicenseStore = create2((set, get) => ({
977
1023
  _revalidating = false;
978
1024
  }
979
1025
  }
980
- setInterval(async () => {
1026
+ if (_revalidationInterval) clearInterval(_revalidationInterval);
1027
+ _revalidationInterval = setInterval(async () => {
981
1028
  const current = get().license;
982
1029
  if (!current || get().status !== "pro") return;
983
1030
  if (!needsRevalidation(current)) return;
@@ -994,7 +1041,8 @@ var useLicenseStore = create2((set, get) => ({
994
1041
  } finally {
995
1042
  _revalidating = false;
996
1043
  }
997
- }, REVALIDATION_CHECK_MS).unref();
1044
+ }, REVALIDATION_CHECK_MS);
1045
+ _revalidationInterval.unref();
998
1046
  },
999
1047
  activate: async (key) => {
1000
1048
  set({ error: null });
@@ -1011,7 +1059,11 @@ var useLicenseStore = create2((set, get) => ({
1011
1059
  deactivate: async () => {
1012
1060
  const { license } = get();
1013
1061
  if (license) {
1014
- await deactivate(license);
1062
+ const { remoteSuccess } = await deactivate(license);
1063
+ if (!remoteSuccess) {
1064
+ set({ status: "free", license: null, error: "License removed locally but server deactivation failed. It may remain active remotely." });
1065
+ return;
1066
+ }
1015
1067
  }
1016
1068
  set({ status: "free", license: null, error: null });
1017
1069
  },
@@ -1021,24 +1073,13 @@ var useLicenseStore = create2((set, get) => ({
1021
1073
  // src/lib/license/anti-debug.ts
1022
1074
  import inspector from "inspector";
1023
1075
  function isDebuggerAttached() {
1024
- if (process.env.VITEST || process.env.CI) return false;
1076
+ if (false) return false;
1025
1077
  if (inspector.url()) return true;
1026
1078
  if (process.execArgv.some((a) => a.includes("--inspect") || a.includes("--debug"))) return true;
1027
1079
  if (process.env.NODE_OPTIONS?.includes("--inspect")) return true;
1028
1080
  return false;
1029
1081
  }
1030
1082
 
1031
- // src/lib/license/anti-tamper.ts
1032
- var _originalIsPro = useLicenseStore.getState().isPro;
1033
- var _originalGetState = useLicenseStore.getState;
1034
- function verifyStoreIntegrity() {
1035
- const state = useLicenseStore.getState();
1036
- if (state.isPro !== _originalIsPro) return false;
1037
- if (useLicenseStore.getState !== _originalGetState) return false;
1038
- if (state.status === "free" && state.isPro()) return false;
1039
- return true;
1040
- }
1041
-
1042
1083
  // src/lib/license/canary.ts
1043
1084
  var _canaryTripped = false;
1044
1085
  function isProUnlocked() {
@@ -1096,29 +1137,26 @@ function checkBundleIntegrity() {
1096
1137
  }
1097
1138
 
1098
1139
  // src/lib/license/pro-guard.ts
1099
- var _S = String.fromCharCode(115, 116, 97, 116, 117, 115);
1100
1140
  var _P = String.fromCharCode(112, 114, 111);
1101
- function _verify() {
1102
- const state = useLicenseStore.getState();
1103
- return state[_S] === _P;
1141
+ function _verify(status) {
1142
+ return status === _P;
1104
1143
  }
1105
- function verifyPro() {
1144
+ function verifyPro(license, status) {
1106
1145
  if (isDebuggerAttached()) return false;
1107
1146
  if (!checkBundleIntegrity()) return false;
1108
1147
  if (!verifyStoreIntegrity()) return false;
1109
1148
  if (!checkCanaries()) return false;
1110
- const directCheck = useLicenseStore.getState().status === "pro";
1111
- const indirectCheck = _verify();
1149
+ const directCheck = status === "pro";
1150
+ const indirectCheck = _verify(status);
1112
1151
  if (!directCheck || !indirectCheck) return false;
1113
- const license = useLicenseStore.getState().license;
1114
1152
  if (license) {
1115
1153
  const level = getDegradationLevel(license);
1116
1154
  if (level === "expired" || level === "limited") return false;
1117
1155
  }
1118
1156
  return true;
1119
1157
  }
1120
- function requirePro() {
1121
- if (!verifyPro()) {
1158
+ function requirePro(license, status) {
1159
+ if (!verifyPro(license, status)) {
1122
1160
  throw new Error("Pro license required");
1123
1161
  }
1124
1162
  }
@@ -1130,6 +1168,7 @@ export {
1130
1168
  PROFILES_DIR,
1131
1169
  HISTORY_PATH,
1132
1170
  ensureDataDirs,
1171
+ fetchWithTimeout,
1133
1172
  loadLicense,
1134
1173
  activate,
1135
1174
  deactivate,
@@ -1137,4 +1176,3 @@ export {
1137
1176
  verifyPro,
1138
1177
  requirePro
1139
1178
  };
1140
- //# sourceMappingURL=chunk-P6PTN4HR.js.map
@@ -0,0 +1,76 @@
1
+ import {
2
+ HISTORY_PATH,
3
+ ensureDataDirs,
4
+ requirePro,
5
+ useLicenseStore
6
+ } from "./chunk-KXDTKY3E.js";
7
+
8
+ // src/lib/history/history-logger.ts
9
+ import { readFile, writeFile, rename } from "fs/promises";
10
+ import { randomUUID } from "crypto";
11
+ var MAX_ENTRIES = 1e3;
12
+ function detectAction(args) {
13
+ const cmd = args[0];
14
+ if (cmd === "install") return { action: "install", packageName: args[1] ?? null };
15
+ if (cmd === "uninstall") {
16
+ const name = args.find((a) => !a.startsWith("-")) === "uninstall" ? args.find((a, i) => i > 0 && !a.startsWith("-")) ?? null : args[1] ?? null;
17
+ return { action: "uninstall", packageName: name };
18
+ }
19
+ if (cmd === "upgrade") {
20
+ if (args.length === 1) return { action: "upgrade-all", packageName: null };
21
+ return { action: "upgrade", packageName: args[1] ?? null };
22
+ }
23
+ return null;
24
+ }
25
+ async function loadHistory() {
26
+ const { license, status } = useLicenseStore.getState();
27
+ requirePro(license, status);
28
+ try {
29
+ const raw = await readFile(HISTORY_PATH, "utf-8");
30
+ const file = JSON.parse(raw);
31
+ if (file.version !== 1) {
32
+ throw new Error("Unsupported data version");
33
+ }
34
+ const entries = file.entries;
35
+ return Array.isArray(entries) ? entries : [];
36
+ } catch {
37
+ return [];
38
+ }
39
+ }
40
+ async function saveHistory(entries) {
41
+ await ensureDataDirs();
42
+ const file = { version: 1, entries };
43
+ const tmp = HISTORY_PATH + ".tmp";
44
+ await writeFile(tmp, JSON.stringify(file, null, 2), { encoding: "utf-8", mode: 384 });
45
+ await rename(tmp, HISTORY_PATH);
46
+ }
47
+ async function appendEntry(action, packageName, success, error = null) {
48
+ const { license, status } = useLicenseStore.getState();
49
+ requirePro(license, status);
50
+ const entries = await loadHistory();
51
+ const entry = {
52
+ id: randomUUID(),
53
+ action,
54
+ packageName,
55
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
56
+ success,
57
+ error
58
+ };
59
+ entries.unshift(entry);
60
+ if (entries.length > MAX_ENTRIES) {
61
+ entries.length = MAX_ENTRIES;
62
+ }
63
+ await saveHistory(entries);
64
+ }
65
+ async function clearHistory() {
66
+ const { license, status } = useLicenseStore.getState();
67
+ requirePro(license, status);
68
+ await saveHistory([]);
69
+ }
70
+
71
+ export {
72
+ detectAction,
73
+ loadHistory,
74
+ appendEntry,
75
+ clearHistory
76
+ };
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  appendEntry,
3
3
  clearHistory,
4
+ detectAction,
4
5
  loadHistory
5
- } from "./chunk-3BK3B53S.js";
6
- import "./chunk-P6PTN4HR.js";
6
+ } from "./chunk-UBHTQL7T.js";
7
+ import "./chunk-KXDTKY3E.js";
7
8
  export {
8
9
  appendEntry,
9
10
  clearHistory,
11
+ detectAction,
10
12
  loadHistory
11
13
  };
12
- //# sourceMappingURL=history-logger-LQT622M2.js.map