brew-tui 2.3.2 → 3.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/build/{brew-tui-bar-installer-5L4RUQF4.js → brew-tui-bar-installer-66P3MJVS.js} +3 -3
- package/build/{brewfile-manager-VMQSH6WR.js → brewfile-manager-KHDIFP23.js} +3 -3
- package/build/{chunk-4XUWG775.js → chunk-4CSFRRSB.js} +2 -2
- package/build/{chunk-7UREKBJD.js → chunk-4RPJM7O7.js} +14 -39
- package/build/chunk-4RPJM7O7.js.map +1 -0
- package/build/{chunk-PETT3DQP.js → chunk-5FAI7JKA.js} +3 -41
- package/build/chunk-5FAI7JKA.js.map +1 -0
- package/build/{chunk-RMYDKHAQ.js → chunk-6VLQW2JL.js} +2 -2
- package/build/{chunk-AYWJHS5X.js → chunk-A7U3NZYM.js} +1 -3
- package/build/chunk-A7U3NZYM.js.map +1 -0
- package/build/{chunk-VLAOY7ZM.js → chunk-D6DGYMXM.js} +10 -22
- package/build/chunk-D6DGYMXM.js.map +1 -0
- package/build/{chunk-GOUEYUCQ.js → chunk-FQV2F47X.js} +2 -2
- package/build/{doctor-K5HUAVBP.js → doctor-GR3IXTWM.js} +8 -8
- package/build/doctor-GR3IXTWM.js.map +1 -0
- package/build/index.js +18 -24
- package/build/index.js.map +1 -1
- package/build/postinstall.js +2 -2
- package/build/{sync-engine-UNCZIREV.js → sync-engine-37NCGPBS.js} +4 -4
- package/build/{version-check-LTPHFA73.js → version-check-PKTSIF43.js} +2 -2
- package/package.json +3 -2
- package/build/chunk-7UREKBJD.js.map +0 -1
- package/build/chunk-AYWJHS5X.js.map +0 -1
- package/build/chunk-PETT3DQP.js.map +0 -1
- package/build/chunk-VLAOY7ZM.js.map +0 -1
- package/build/doctor-K5HUAVBP.js.map +0 -1
- /package/build/{brew-tui-bar-installer-5L4RUQF4.js.map → brew-tui-bar-installer-66P3MJVS.js.map} +0 -0
- /package/build/{brewfile-manager-VMQSH6WR.js.map → brewfile-manager-KHDIFP23.js.map} +0 -0
- /package/build/{chunk-4XUWG775.js.map → chunk-4CSFRRSB.js.map} +0 -0
- /package/build/{chunk-RMYDKHAQ.js.map → chunk-6VLQW2JL.js.map} +0 -0
- /package/build/{chunk-GOUEYUCQ.js.map → chunk-FQV2F47X.js.map} +0 -0
- /package/build/{sync-engine-UNCZIREV.js.map → sync-engine-37NCGPBS.js.map} +0 -0
- /package/build/{version-check-LTPHFA73.js.map → version-check-PKTSIF43.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadLicense
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4RPJM7O7.js";
|
|
4
4
|
import {
|
|
5
5
|
captureSnapshot
|
|
6
6
|
} from "./chunk-OXDZ4DCK.js";
|
|
@@ -18,7 +18,7 @@ import { join as join2 } from "path";
|
|
|
18
18
|
import { hostname } from "os";
|
|
19
19
|
|
|
20
20
|
// src/lib/sync/crypto.ts
|
|
21
|
-
import { createCipheriv, createDecipheriv, randomBytes,
|
|
21
|
+
import { createCipheriv, createDecipheriv, randomBytes, hkdfSync } from "crypto";
|
|
22
22
|
|
|
23
23
|
// src/lib/sync/types.ts
|
|
24
24
|
function isSyncPayload(value) {
|
|
@@ -39,7 +39,6 @@ function isSyncPayload(value) {
|
|
|
39
39
|
var ENCRYPTION_SECRET = "brew-tui-sync-aes256gcm-v1";
|
|
40
40
|
var HKDF_SALT = "brew-tui-sync-salt-v1";
|
|
41
41
|
var keyCache = /* @__PURE__ */ new Map();
|
|
42
|
-
var _legacyKey = null;
|
|
43
42
|
function deriveEncryptionKey(licenseKey) {
|
|
44
43
|
const cached = keyCache.get(licenseKey);
|
|
45
44
|
if (cached) return cached;
|
|
@@ -47,12 +46,6 @@ function deriveEncryptionKey(licenseKey) {
|
|
|
47
46
|
keyCache.set(licenseKey, derived);
|
|
48
47
|
return derived;
|
|
49
48
|
}
|
|
50
|
-
function deriveLegacyKey() {
|
|
51
|
-
if (!_legacyKey) {
|
|
52
|
-
_legacyKey = scryptSync(ENCRYPTION_SECRET, HKDF_SALT, 32, { N: 16384, r: 8, p: 1 });
|
|
53
|
-
}
|
|
54
|
-
return _legacyKey;
|
|
55
|
-
}
|
|
56
49
|
function encryptPayload(data, licenseKey) {
|
|
57
50
|
const key = deriveEncryptionKey(licenseKey);
|
|
58
51
|
const iv = randomBytes(12);
|
|
@@ -70,18 +63,13 @@ function decryptPayload(encrypted, iv, tag, licenseKey) {
|
|
|
70
63
|
const ivBuf = Buffer.from(iv, "base64");
|
|
71
64
|
const tagBuf = Buffer.from(tag, "base64");
|
|
72
65
|
const ciphertext = Buffer.from(encrypted, "base64");
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return parsed;
|
|
81
|
-
} catch {
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
throw new Error("Failed to decrypt sync payload");
|
|
66
|
+
const key = deriveEncryptionKey(licenseKey);
|
|
67
|
+
const decipher = createDecipheriv("aes-256-gcm", key, ivBuf);
|
|
68
|
+
decipher.setAuthTag(tagBuf);
|
|
69
|
+
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
70
|
+
const parsed = JSON.parse(plaintext.toString("utf-8"));
|
|
71
|
+
if (!isSyncPayload(parsed)) throw new Error("Invalid sync payload shape");
|
|
72
|
+
return parsed;
|
|
85
73
|
}
|
|
86
74
|
|
|
87
75
|
// src/lib/sync/backends/icloud-backend.ts
|
|
@@ -339,4 +327,4 @@ export {
|
|
|
339
327
|
sync,
|
|
340
328
|
applyConflictResolutions
|
|
341
329
|
};
|
|
342
|
-
//# sourceMappingURL=chunk-
|
|
330
|
+
//# sourceMappingURL=chunk-D6DGYMXM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/sync/sync-engine.ts","../src/lib/sync/crypto.ts","../src/lib/sync/types.ts","../src/lib/sync/backends/icloud-backend.ts"],"sourcesContent":["import { readFile, writeFile, rename } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { hostname } from 'node:os';\nimport { encryptPayload, decryptPayload } from './crypto.js';\nimport {\n readSyncEnvelope,\n writeSyncEnvelope,\n isICloudAvailable,\n} from './backends/icloud-backend.js';\nimport { captureSnapshot } from '../state-snapshot/snapshot.js';\nimport { DATA_DIR, getMachineId } from '../data-dir.js';\nimport { loadLicense } from '../license/license-manager.js';\nimport { logger } from '../../utils/logger.js';\nimport type {\n SyncConfig,\n SyncPayload,\n SyncConflict,\n SyncResult,\n MachineState,\n SyncEnvelope,\n} from './types.js';\nimport type { BrewfileSchema } from '../brewfile/types.js';\n\nconst SYNC_CONFIG_PATH = join(DATA_DIR, 'sync-config.json');\n\n// ── Config I/O ──────────────────────────────────────────────────────────────\n\nexport async function loadSyncConfig(): Promise<SyncConfig | null> {\n try {\n const raw = await readFile(SYNC_CONFIG_PATH, 'utf-8');\n return JSON.parse(raw) as SyncConfig;\n } catch {\n return null;\n }\n}\n\nexport async function saveSyncConfig(config: SyncConfig): Promise<void> {\n const tmpPath = SYNC_CONFIG_PATH + '.tmp';\n await writeFile(tmpPath, JSON.stringify(config, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n await rename(tmpPath, SYNC_CONFIG_PATH);\n}\n\n// ── Machine ID ───────────────────────────────────────────────────────────────\n// Single canonical implementation lives in data-dir.ts. The previous fallback\n// to os.hostname() here meant two different machines with the same hostname\n// (common on freshly-imaged corporate fleets) collided in sync state.\n\nexport { getMachineId };\n\n// ── Conflict detection ───────────────────────────────────────────────────────\n\nfunction detectConflicts(\n localSnapshot: { formulae: Array<{ name: string; version: string }>; casks: Array<{ name: string; version: string }> },\n otherMachines: MachineState[],\n localMachineId: string,\n): SyncConflict[] {\n const conflicts: SyncConflict[] = [];\n\n const localFormulaMap = new Map(localSnapshot.formulae.map((f) => [f.name, f.version]));\n const localCaskMap = new Map(localSnapshot.casks.map((c) => [c.name, c.version]));\n\n for (const machine of otherMachines) {\n if (machine.machineId === localMachineId) continue;\n\n // Check formula conflicts: same package, different version on both machines\n for (const remoteFormula of machine.snapshot.formulae) {\n const localVersion = localFormulaMap.get(remoteFormula.name);\n if (localVersion !== undefined && localVersion !== remoteFormula.version) {\n conflicts.push({\n packageName: remoteFormula.name,\n packageType: 'formula',\n localVersion,\n remoteMachine: machine.machineName,\n remoteVersion: remoteFormula.version,\n });\n }\n }\n\n // Check cask conflicts\n for (const remoteCask of machine.snapshot.casks) {\n const localVersion = localCaskMap.get(remoteCask.name);\n if (localVersion !== undefined && localVersion !== remoteCask.version) {\n conflicts.push({\n packageName: remoteCask.name,\n packageType: 'cask',\n localVersion,\n remoteMachine: machine.machineName,\n remoteVersion: remoteCask.version,\n });\n }\n }\n }\n\n return conflicts;\n}\n\n// ── Merge ────────────────────────────────────────────────────────────────────\n\nasync function writeEnvelope(payload: SyncPayload, licenseKey: string): Promise<string> {\n const now = new Date().toISOString();\n const { encrypted, iv, tag } = encryptPayload(payload, licenseKey);\n const envelope: SyncEnvelope = {\n schemaVersion: 1,\n encrypted,\n iv,\n tag,\n updatedAt: now,\n };\n await writeSyncEnvelope(envelope);\n return now;\n}\n\nasync function loadLicenseKeyOrThrow(): Promise<string> {\n // Sync requires Pro, and Pro requires a license. Read it lazily so\n // sync-store callers don't have to plumb the key through every call.\n const license = await loadLicense();\n if (!license || !license.key) {\n throw new Error('Sync requires an active license');\n }\n return license.key;\n}\n\nfunction mergePayload(existing: SyncPayload, localState: MachineState): SyncPayload {\n return {\n machines: {\n ...existing.machines,\n [localState.machineId]: localState,\n },\n };\n}\n\n// ── Main sync function ───────────────────────────────────────────────────────\n\nexport async function sync(\n isPro: boolean,\n currentBrewfile?: BrewfileSchema,\n): Promise<SyncResult> {\n if (!isPro) {\n throw new Error('Pro license required');\n }\n\n const available = await isICloudAvailable();\n if (!available) {\n return {\n success: false,\n conflicts: [],\n resolvedCount: 0,\n error: 'iCloud Drive not available',\n };\n }\n\n const licenseKey = await loadLicenseKeyOrThrow();\n\n let existingPayload: SyncPayload | null = null;\n\n try {\n const envelope = await readSyncEnvelope();\n if (envelope) {\n existingPayload = decryptPayload(envelope.encrypted, envelope.iv, envelope.tag, licenseKey);\n }\n } catch (err) {\n logger.warn('sync: could not decrypt existing payload, starting fresh', { error: String(err) });\n existingPayload = null;\n }\n\n // Capture current local state\n const snapshot = await captureSnapshot();\n const machineId = await getMachineId();\n const machineName = hostname();\n\n const localState: MachineState = {\n machineId,\n machineName,\n updatedAt: new Date().toISOString(),\n snapshot,\n ...(currentBrewfile ? { brewfile: currentBrewfile } : {}),\n };\n\n // Detect conflicts against other machines in the payload\n const otherMachines = existingPayload\n ? Object.values(existingPayload.machines).filter((m) => m.machineId !== machineId)\n : [];\n\n const conflicts = detectConflicts(snapshot, otherMachines, machineId);\n\n // Always write the local machine state to the payload, even when conflicts\n // exist, so that applyConflictResolutions() has a local entry to update.\n // Without this, the iCloud envelope keeps only remote machines, and\n // resolution updates are silently dropped (they require localMachine to exist).\n const basePayload: SyncPayload = existingPayload ?? { machines: {} };\n const mergedPayload = mergePayload(basePayload, localState);\n\n if (conflicts.length > 0) {\n // Persist local state, then surface conflicts so the user can resolve them.\n await writeEnvelope(mergedPayload, licenseKey);\n return {\n success: false,\n conflicts,\n resolvedCount: 0,\n };\n }\n\n const now = await writeEnvelope(mergedPayload, licenseKey);\n\n // Update local sync config\n const existingConfig = await loadSyncConfig();\n await saveSyncConfig({\n enabled: true,\n machineId,\n machineName,\n ...(existingConfig ?? {}),\n lastSync: now,\n });\n\n logger.info('sync: completed successfully', { machineId, machines: Object.keys(mergedPayload.machines).length });\n\n return {\n success: true,\n conflicts: [],\n resolvedCount: 0,\n };\n}\n\n// ── Conflict resolution ──────────────────────────────────────────────────────\n\nexport async function applyConflictResolutions(\n payload: SyncPayload,\n resolutions: Array<{ conflict: SyncConflict; resolution: 'use-local' | 'use-remote' }>,\n localMachineId: string,\n): Promise<void> {\n // Work on a mutable copy\n const updatedPayload: SyncPayload = {\n machines: { ...payload.machines },\n };\n\n for (const { conflict, resolution } of resolutions) {\n if (resolution !== 'use-remote') continue;\n // Re-read latest local machine on every iteration so consecutive resolutions\n // build on top of each other instead of overwriting prior changes.\n const localMachine = updatedPayload.machines[localMachineId];\n if (!localMachine) {\n logger.warn('sync: cannot apply resolution, local machine missing in payload', { localMachineId });\n continue;\n }\n if (conflict.packageType === 'formula') {\n updatedPayload.machines[localMachineId] = {\n ...localMachine,\n snapshot: {\n ...localMachine.snapshot,\n formulae: localMachine.snapshot.formulae.map((f) =>\n f.name === conflict.packageName\n ? { ...f, version: conflict.remoteVersion }\n : f,\n ),\n },\n };\n } else {\n updatedPayload.machines[localMachineId] = {\n ...localMachine,\n snapshot: {\n ...localMachine.snapshot,\n casks: localMachine.snapshot.casks.map((c) =>\n c.name === conflict.packageName\n ? { ...c, version: conflict.remoteVersion }\n : c,\n ),\n },\n };\n }\n }\n\n const licenseKey = await loadLicenseKeyOrThrow();\n await writeEnvelope(updatedPayload, licenseKey);\n logger.info('sync: conflict resolutions applied', { count: resolutions.length });\n}\n","import { createCipheriv, createDecipheriv, randomBytes, hkdfSync } from 'node:crypto';\nimport { isSyncPayload, type SyncPayload } from './types.js';\n\n// SEG-003: Cross-machine sync encryption.\n// The two constants below are public (compiled into the npm bundle). The\n// per-user secret factor is the Polar license key, which only the user's\n// own machines hold and which Polar issues — so any two of the user's\n// machines derive the same key, but bundle + iCloud snoop is no longer\n// enough to decrypt: the attacker also needs the license key.\n//\n// HKDF-SHA256 over scrypt: the license key is high-entropy by construction\n// (Polar issues UUID-style keys), so the cost-hardening of scrypt isn't\n// what's protecting the key — the secrecy of the license key is. HKDF is\n// also faster, so machines don't pay scrypt's CPU tax on every sync.\nconst ENCRYPTION_SECRET = 'brew-tui-sync-aes256gcm-v1';\nconst HKDF_SALT = 'brew-tui-sync-salt-v1';\n\nconst keyCache = new Map<string, Buffer>();\n\nfunction deriveEncryptionKey(licenseKey: string): Buffer {\n const cached = keyCache.get(licenseKey);\n if (cached) return cached;\n const derived = Buffer.from(hkdfSync('sha256', ENCRYPTION_SECRET, HKDF_SALT, licenseKey, 32));\n keyCache.set(licenseKey, derived);\n return derived;\n}\n\nexport function encryptPayload(data: SyncPayload, licenseKey: string): { encrypted: string; iv: string; tag: string } {\n const key = deriveEncryptionKey(licenseKey);\n const iv = randomBytes(12); // 96-bit IV for GCM\n const cipher = createCipheriv('aes-256-gcm', key, iv);\n\n const plaintext = JSON.stringify(data);\n const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf-8'), cipher.final()]);\n const tag = cipher.getAuthTag();\n\n return {\n encrypted: ciphertext.toString('base64'),\n iv: iv.toString('base64'),\n tag: tag.toString('base64'),\n };\n}\n\nexport function decryptPayload(encrypted: string, iv: string, tag: string, licenseKey: string): SyncPayload {\n const ivBuf = Buffer.from(iv, 'base64');\n const tagBuf = Buffer.from(tag, 'base64');\n const ciphertext = Buffer.from(encrypted, 'base64');\n\n // Only the licenseKey-bound HKDF key is accepted. The legacy bundle-only\n // scrypt fallback (for envelopes written by 0.6.2 and earlier) was retired\n // in 3.1.0 — see SEG-M3 in the security audit.\n const key = deriveEncryptionKey(licenseKey);\n const decipher = createDecipheriv('aes-256-gcm', key, ivBuf);\n decipher.setAuthTag(tagBuf);\n const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n const parsed: unknown = JSON.parse(plaintext.toString('utf-8'));\n if (!isSyncPayload(parsed)) throw new Error('Invalid sync payload shape');\n return parsed;\n}\n","import type { BrewSnapshot } from '../state-snapshot/snapshot.js';\nimport type { BrewfileSchema } from '../brewfile/types.js';\n\nexport interface SyncConfig {\n enabled: boolean;\n machineId: string;\n machineName: string;\n lastSync?: string; // ISO 8601\n}\n\nexport interface MachineState {\n machineId: string;\n machineName: string;\n updatedAt: string; // ISO 8601\n snapshot: BrewSnapshot;\n brewfile?: BrewfileSchema;\n}\n\nexport interface SyncPayload {\n machines: Record<string, MachineState>;\n}\n\n// BK-008: type guard for sync envelopes after AES-GCM decrypt. Defends against\n// truncated or migrated payloads landing as undefined accesses downstream.\nexport function isSyncPayload(value: unknown): value is SyncPayload {\n if (typeof value !== 'object' || value === null) return false;\n const machines = (value as Record<string, unknown>).machines;\n if (typeof machines !== 'object' || machines === null || Array.isArray(machines)) return false;\n for (const m of Object.values(machines as Record<string, unknown>)) {\n if (typeof m !== 'object' || m === null) return false;\n const state = m as Record<string, unknown>;\n if (\n typeof state.machineId !== 'string' ||\n typeof state.machineName !== 'string' ||\n typeof state.updatedAt !== 'string' ||\n typeof state.snapshot !== 'object'\n ) {\n return false;\n }\n }\n return true;\n}\n\nexport interface SyncEnvelope {\n schemaVersion: 1;\n encrypted: string;\n iv: string;\n tag: string;\n updatedAt: string; // ISO 8601 — plaintext for Brew-TUI-Bar monitoring\n}\n\n// BK-006: 'merge-union' aparecia en este union pero applyConflictResolutions()\n// nunca implemento la rama; cualquier caller que lo pasara veia el conflicto\n// descartado silenciosamente. Eliminado hasta que exista la logica de merge.\nexport type ConflictResolution = 'use-local' | 'use-remote';\n\nexport interface SyncConflict {\n packageName: string;\n packageType: 'formula' | 'cask';\n localVersion: string;\n remoteMachine: string;\n remoteVersion: string;\n}\n\nexport interface SyncResult {\n success: boolean;\n conflicts: SyncConflict[];\n resolvedCount: number;\n error?: string;\n}\n","import { readFile, writeFile, rename, mkdir, stat } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { logger } from '../../../utils/logger.js';\nimport type { SyncEnvelope } from '../types.js';\n\nconst ICLOUD_BASE = join(\n homedir(),\n 'Library', 'Mobile Documents', 'com~apple~CloudDocs',\n);\nexport const ICLOUD_SYNC_DIR = join(ICLOUD_BASE, 'BrewTUI');\nexport const ICLOUD_SYNC_PATH = join(ICLOUD_SYNC_DIR, 'sync.json');\n\nexport async function isICloudAvailable(): Promise<boolean> {\n try {\n await stat(ICLOUD_BASE);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isValidEnvelope(v: unknown): v is SyncEnvelope {\n if (!v || typeof v !== 'object') return false;\n const obj = v as Record<string, unknown>;\n return (\n obj['schemaVersion'] === 1 &&\n typeof obj['encrypted'] === 'string' &&\n typeof obj['iv'] === 'string' &&\n typeof obj['tag'] === 'string' &&\n typeof obj['updatedAt'] === 'string'\n );\n}\n\nexport async function readSyncEnvelope(): Promise<SyncEnvelope | null> {\n // BK-012: iCloud may leave an undownloaded placeholder at the path. Reading\n // returns 0 bytes (or ENOENT for the file but a sibling .icloud entry).\n // Treat empty / missing-but-pending as \"not yet ready\" without surfacing\n // a misleading \"no remote state\" to the caller.\n try {\n const info = await stat(ICLOUD_SYNC_PATH);\n if (info.size === 0) {\n logger.warn('sync: iCloud envelope exists but is empty (placeholder?)');\n return null;\n }\n } catch (err: unknown) {\n if (err instanceof Error && (err as NodeJS.ErrnoException).code === 'ENOENT') {\n // First-sync case OR pending download — check for the placeholder sibling.\n try {\n const placeholder = ICLOUD_SYNC_PATH.replace(/sync\\.json$/, '.sync.json.icloud');\n await stat(placeholder);\n logger.warn('sync: iCloud placeholder present, file not yet downloaded');\n } catch { /* genuinely absent */ }\n return null;\n }\n logger.warn('sync: could not stat iCloud envelope', { error: String(err) });\n return null;\n }\n\n try {\n const raw = await readFile(ICLOUD_SYNC_PATH, 'utf-8');\n const parsed: unknown = JSON.parse(raw);\n if (!isValidEnvelope(parsed)) {\n logger.warn('sync: invalid envelope structure in iCloud file');\n return null;\n }\n return parsed;\n } catch (err: unknown) {\n logger.warn('sync: could not read iCloud envelope', { error: String(err) });\n return null;\n }\n}\n\nexport async function writeSyncEnvelope(envelope: SyncEnvelope): Promise<void> {\n // BK-007: explicito 0o700 — iCloud Drive hereda permisos del sistema y por\n // defecto pueden ser 0o755. Aunque el contenido del envelope va cifrado, el\n // listado del directorio no deberia ser legible por otros usuarios locales.\n await mkdir(ICLOUD_SYNC_DIR, { recursive: true, mode: 0o700 });\n const tmpPath = ICLOUD_SYNC_PATH + '.tmp';\n await writeFile(tmpPath, JSON.stringify(envelope, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n await rename(tmpPath, ICLOUD_SYNC_PATH);\n}\n"],"mappings":"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","names":["readFile","writeFile","rename","join","join","readFile","writeFile","rename"]}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
loadLicense,
|
|
7
7
|
needsRevalidation,
|
|
8
8
|
revalidate
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-4RPJM7O7.js";
|
|
10
10
|
import {
|
|
11
11
|
ensureDataDirs
|
|
12
12
|
} from "./chunk-LFGDNAXH.js";
|
|
@@ -135,4 +135,4 @@ export {
|
|
|
135
135
|
verifyStoreIntegrity,
|
|
136
136
|
useLicenseStore
|
|
137
137
|
};
|
|
138
|
-
//# sourceMappingURL=chunk-
|
|
138
|
+
//# sourceMappingURL=chunk-FQV2F47X.js.map
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
checkBrewTUIBarVersion,
|
|
3
3
|
readBrewTUIBarVersion
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4CSFRRSB.js";
|
|
5
5
|
import {
|
|
6
6
|
useLicenseStore
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-FQV2F47X.js";
|
|
8
8
|
import {
|
|
9
9
|
bundleIdAt,
|
|
10
10
|
isBrewTUIBarInstalled,
|
|
11
11
|
isBrewTUIBarRunning
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-5FAI7JKA.js";
|
|
13
|
+
import "./chunk-4RPJM7O7.js";
|
|
14
14
|
import "./chunk-NRRQECXA.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-A7U3NZYM.js";
|
|
16
16
|
import "./chunk-KDHEUNRI.js";
|
|
17
17
|
import "./chunk-LFGDNAXH.js";
|
|
18
18
|
|
|
@@ -53,7 +53,7 @@ async function findBrewBinary() {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
async function runDoctor() {
|
|
56
|
-
const cliVersion = "
|
|
56
|
+
const cliVersion = "3.1.0";
|
|
57
57
|
console.log(format("Brew-TUI", [
|
|
58
58
|
{ label: "CLI version", value: cliVersion },
|
|
59
59
|
{ label: "Platform", value: `${process.platform} (${arch()})` },
|
|
@@ -94,7 +94,7 @@ async function runDoctor() {
|
|
|
94
94
|
{ label: "Bundle ID", value: legacyId ?? "(unreadable)" },
|
|
95
95
|
{
|
|
96
96
|
label: "Note",
|
|
97
|
-
value: legacyId === "com.molinesdesigns.brewbar" ? "
|
|
97
|
+
value: legacyId === "com.molinesdesigns.brewbar" ? "remove manually: rm -rf /Applications/BrewBar.app" : "foreign app \u2014 not ours, not touching"
|
|
98
98
|
}
|
|
99
99
|
]));
|
|
100
100
|
console.log("");
|
|
@@ -130,4 +130,4 @@ async function runDoctor() {
|
|
|
130
130
|
export {
|
|
131
131
|
runDoctor
|
|
132
132
|
};
|
|
133
|
-
//# sourceMappingURL=doctor-
|
|
133
|
+
//# sourceMappingURL=doctor-GR3IXTWM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/doctor.ts"],"sourcesContent":["import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { access, stat } from 'node:fs/promises';\nimport { homedir, arch } from 'node:os';\nimport { join } from 'node:path';\nimport { useLicenseStore } from '../stores/license-store.js';\nimport { bundleIdAt, isBrewTUIBarInstalled, isBrewTUIBarRunning } from './brew-tui-bar-installer.js';\nimport { readBrewTUIBarVersion, checkBrewTUIBarVersion } from './version-check.js';\n\nconst execFileAsync = promisify(execFile);\n\nconst EXPECTED_BUNDLE_ID = 'com.molinesdesigns.brewtuibar';\nconst APP_PATH = '/Applications/Brew-TUI-Bar.app';\nconst LEGACY_APP_PATH = '/Applications/BrewBar.app';\n\ntype Line = { label: string; value: string; ok?: boolean | null };\n\nfunction format(section: string, lines: Line[]): string {\n const out: string[] = [`=== ${section} ===`];\n const maxLabel = lines.reduce((m, l) => Math.max(m, l.label.length), 0);\n for (const l of lines) {\n const pad = ' '.repeat(maxLabel - l.label.length);\n const mark = l.ok === true ? ' ✓' : l.ok === false ? ' ✘' : '';\n out.push(` ${l.label}${pad} ${l.value}${mark}`);\n }\n return out.join('\\n');\n}\n\nasync function pathExists(p: string): Promise<boolean> {\n try {\n await access(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function findBrewBinary(): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync('which', ['brew']);\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/// Plain-text diagnostic dump for the user / support. No Ink, no colors —\n/// users will paste this into bug reports. Each section is best-effort:\n/// individual probes can fail without aborting the whole report.\nexport async function runDoctor(): Promise<void> {\n const cliVersion = process.env.APP_VERSION ?? '0.0.0';\n\n // ── Brew-TUI ──────────────────────────────────────────────────────────\n console.log(format('Brew-TUI', [\n { label: 'CLI version', value: cliVersion },\n { label: 'Platform', value: `${process.platform} (${arch()})` },\n { label: 'Node', value: process.version },\n ]));\n console.log('');\n\n // ── Brew-TUI-Bar (macOS only) ─────────────────────────────────────────\n if (process.platform === 'darwin') {\n const lines: Line[] = [];\n try {\n const installed = await isBrewTUIBarInstalled();\n if (!installed) {\n lines.push({ label: 'Installed', value: 'no' });\n } else {\n lines.push({ label: 'Installed at', value: APP_PATH, ok: true });\n const appVersion = await readBrewTUIBarVersion();\n lines.push({ label: 'App version', value: appVersion ?? '(unreadable)' });\n const status = await checkBrewTUIBarVersion();\n const statusLabel = status.kind === 'ok' ? 'in sync'\n : status.kind === 'outdated' ? `outdated (expected ${status.expected})`\n : status.kind === 'newer' ? `app is newer than CLI (CLI expects ${status.expected})`\n : status.kind === 'not-installed' ? 'not installed'\n : `unknown (${status.reason})`;\n lines.push({ label: 'Version status', value: statusLabel, ok: status.kind === 'ok' });\n const bundleId = await bundleIdAt(APP_PATH);\n lines.push({\n label: 'Bundle ID',\n value: bundleId ?? '(unreadable)',\n ok: bundleId === EXPECTED_BUNDLE_ID ? true : bundleId ? false : null,\n });\n const running = await isBrewTUIBarRunning();\n lines.push({ label: 'Process running', value: running ? 'yes' : 'no' });\n }\n } catch (err) {\n lines.push({ label: '(probe error)', value: err instanceof Error ? err.message : String(err) });\n }\n console.log(format('Brew-TUI-Bar (macOS companion)', lines));\n console.log('');\n\n // Legacy bundle from the BrewBar era. As of 3.0.0 we no longer auto-clean\n // it (the cask `brewbar` is `disable!` and the in-process cleanup helper\n // was retired); the doctor still reports it so users can wipe it manually.\n if (await pathExists(LEGACY_APP_PATH)) {\n const legacyId = await bundleIdAt(LEGACY_APP_PATH);\n console.log(format('Legacy BrewBar.app', [\n { label: 'Path', value: LEGACY_APP_PATH },\n { label: 'Bundle ID', value: legacyId ?? '(unreadable)' },\n {\n label: 'Note',\n value: legacyId === 'com.molinesdesigns.brewbar'\n ? 'remove manually: rm -rf /Applications/BrewBar.app'\n : 'foreign app — not ours, not touching',\n },\n ]));\n console.log('');\n }\n }\n\n // ── License ───────────────────────────────────────────────────────────\n const licLines: Line[] = [];\n try {\n await useLicenseStore.getState().initialize();\n const { status, license, degradation } = useLicenseStore.getState();\n const tierLabel = status === 'pro' ? 'Pro' : status === 'expired' ? 'Expired' : 'Free';\n licLines.push({ label: 'Tier', value: tierLabel });\n if (license) {\n licLines.push({ label: 'Email', value: license.customerEmail });\n licLines.push({ label: 'Activated at', value: license.activatedAt });\n if (license.expiresAt) licLines.push({ label: 'Expires at', value: license.expiresAt });\n licLines.push({ label: 'Last validated', value: license.lastValidatedAt });\n }\n licLines.push({ label: 'Degradation', value: degradation });\n } catch (err) {\n licLines.push({ label: '(probe error)', value: err instanceof Error ? err.message : String(err) });\n }\n console.log(format('License', licLines));\n console.log('');\n\n // ── Environment ───────────────────────────────────────────────────────\n const dataDir = join(homedir(), '.brew-tui');\n const machineIdPath = join(dataDir, 'machine-id');\n const machineIdPresent = await stat(machineIdPath).then(() => true).catch(() => false);\n console.log(format('Environment', [\n { label: 'brew binary', value: (await findBrewBinary()) ?? '(not on PATH)' },\n { label: 'Data directory', value: dataDir },\n { label: 'machine-id', value: machineIdPresent ? 'present' : '(not created — appears after first activate)' },\n ]));\n}\n"],"mappings":"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","names":[]}
|
package/build/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useLicenseStore,
|
|
3
3
|
verifyStoreIntegrity
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-FQV2F47X.js";
|
|
5
5
|
import {
|
|
6
6
|
brewUpdate,
|
|
7
7
|
casksToListItems,
|
|
@@ -28,21 +28,21 @@ import {
|
|
|
28
28
|
uninstallPackage,
|
|
29
29
|
unpinPackage,
|
|
30
30
|
validatePackageName
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-6VLQW2JL.js";
|
|
32
32
|
import {
|
|
33
33
|
applyConflictResolutions,
|
|
34
34
|
decryptPayload,
|
|
35
35
|
loadSyncConfig,
|
|
36
36
|
readSyncEnvelope,
|
|
37
37
|
sync
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-D6DGYMXM.js";
|
|
39
39
|
import {
|
|
40
40
|
activate,
|
|
41
41
|
deactivate,
|
|
42
42
|
getDegradationLevel,
|
|
43
43
|
loadLicense,
|
|
44
44
|
revalidate
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-4RPJM7O7.js";
|
|
46
46
|
import {
|
|
47
47
|
fetchWithRetry
|
|
48
48
|
} from "./chunk-NRRQECXA.js";
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
t,
|
|
52
52
|
tp,
|
|
53
53
|
useLocaleStore
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-A7U3NZYM.js";
|
|
55
55
|
import {
|
|
56
56
|
checkCompliance
|
|
57
57
|
} from "./chunk-S3NRCC23.js";
|
|
@@ -4550,7 +4550,7 @@ function AccountView() {
|
|
|
4550
4550
|
status === "pro" || status === "team" || status === "expired" ? `v ${t("hint_revalidate")} ` : "",
|
|
4551
4551
|
revalidating ? t("account_revalidating") : "",
|
|
4552
4552
|
" ",
|
|
4553
|
-
t("app_version", { version: "
|
|
4553
|
+
t("app_version", { version: "3.1.0" })
|
|
4554
4554
|
] }) })
|
|
4555
4555
|
] });
|
|
4556
4556
|
}
|
|
@@ -6058,7 +6058,7 @@ async function reportError(err, context = {}) {
|
|
|
6058
6058
|
const config = await resolveConfig();
|
|
6059
6059
|
if (!config.enabled || !config.endpoint) return;
|
|
6060
6060
|
const machineId = await getMachineId();
|
|
6061
|
-
const version = true ? "
|
|
6061
|
+
const version = true ? "3.1.0" : "unknown";
|
|
6062
6062
|
await postReport(buildReport("error", err, context, machineId, version), config);
|
|
6063
6063
|
}
|
|
6064
6064
|
async function installCrashReporter() {
|
|
@@ -6067,7 +6067,7 @@ async function installCrashReporter() {
|
|
|
6067
6067
|
if (!config.enabled || !config.endpoint) return;
|
|
6068
6068
|
_installed = true;
|
|
6069
6069
|
const machineId = await getMachineId();
|
|
6070
|
-
const version = true ? "
|
|
6070
|
+
const version = true ? "3.1.0" : "unknown";
|
|
6071
6071
|
process.on("uncaughtException", (err) => {
|
|
6072
6072
|
void postReport(buildReport("fatal", err, { kind: "uncaughtException" }, machineId, version), config);
|
|
6073
6073
|
});
|
|
@@ -6082,11 +6082,11 @@ import { jsx as jsx39 } from "react/jsx-runtime";
|
|
|
6082
6082
|
var [, , command, arg] = process.argv;
|
|
6083
6083
|
async function runCli() {
|
|
6084
6084
|
if (command === "--version" || command === "-v" || command === "version") {
|
|
6085
|
-
const cliVersion = "
|
|
6085
|
+
const cliVersion = "3.1.0";
|
|
6086
6086
|
process.stdout.write(cliVersion + "\n");
|
|
6087
6087
|
if (process.platform === "darwin") {
|
|
6088
6088
|
try {
|
|
6089
|
-
const { readBrewTUIBarVersion } = await import("./version-check-
|
|
6089
|
+
const { readBrewTUIBarVersion } = await import("./version-check-PKTSIF43.js");
|
|
6090
6090
|
const appVersion = await readBrewTUIBarVersion();
|
|
6091
6091
|
if (appVersion && appVersion !== cliVersion) {
|
|
6092
6092
|
process.stderr.write(t("cli_versionMismatchWarning", { installed: appVersion, expected: cliVersion }) + "\n");
|
|
@@ -6201,7 +6201,7 @@ Snapshots: ${snapshots.length} (latest: ${latest ? formatDate(latest.capturedAt)
|
|
|
6201
6201
|
} catch {
|
|
6202
6202
|
}
|
|
6203
6203
|
try {
|
|
6204
|
-
const { loadBrewfile: loadBrewfile2, computeDrift: computeDrift2 } = await import("./brewfile-manager-
|
|
6204
|
+
const { loadBrewfile: loadBrewfile2, computeDrift: computeDrift2 } = await import("./brewfile-manager-KHDIFP23.js");
|
|
6205
6205
|
const schema = await loadBrewfile2();
|
|
6206
6206
|
if (schema) {
|
|
6207
6207
|
const drift = await computeDrift2(schema);
|
|
@@ -6210,7 +6210,7 @@ Snapshots: ${snapshots.length} (latest: ${latest ? formatDate(latest.capturedAt)
|
|
|
6210
6210
|
} catch {
|
|
6211
6211
|
}
|
|
6212
6212
|
try {
|
|
6213
|
-
const { loadSyncConfig: loadSyncConfig2 } = await import("./sync-engine-
|
|
6213
|
+
const { loadSyncConfig: loadSyncConfig2 } = await import("./sync-engine-37NCGPBS.js");
|
|
6214
6214
|
const syncConfig = await loadSyncConfig2();
|
|
6215
6215
|
if (syncConfig?.lastSync) {
|
|
6216
6216
|
console.log(`Sync: last sync ${formatDate(syncConfig.lastSync)}`);
|
|
@@ -6230,11 +6230,8 @@ Snapshots: ${snapshots.length} (latest: ${latest ? formatDate(latest.capturedAt)
|
|
|
6230
6230
|
}
|
|
6231
6231
|
return;
|
|
6232
6232
|
}
|
|
6233
|
-
if (command === "install-brew-tui-bar"
|
|
6234
|
-
|
|
6235
|
-
console.warn(t("cli_brewtuibarLegacyAlias", { legacy: command, current: "install-brew-tui-bar" }));
|
|
6236
|
-
}
|
|
6237
|
-
const { installBrewTUIBar } = await import("./brew-tui-bar-installer-5L4RUQF4.js");
|
|
6233
|
+
if (command === "install-brew-tui-bar") {
|
|
6234
|
+
const { installBrewTUIBar } = await import("./brew-tui-bar-installer-66P3MJVS.js");
|
|
6238
6235
|
try {
|
|
6239
6236
|
console.log(t("cli_brewtuibarInstalling"));
|
|
6240
6237
|
await installBrewTUIBar(false, arg === "--force");
|
|
@@ -6245,11 +6242,8 @@ Snapshots: ${snapshots.length} (latest: ${latest ? formatDate(latest.capturedAt)
|
|
|
6245
6242
|
}
|
|
6246
6243
|
return;
|
|
6247
6244
|
}
|
|
6248
|
-
if (command === "uninstall-brew-tui-bar"
|
|
6249
|
-
|
|
6250
|
-
console.warn(t("cli_brewtuibarLegacyAlias", { legacy: command, current: "uninstall-brew-tui-bar" }));
|
|
6251
|
-
}
|
|
6252
|
-
const { uninstallBrewTUIBar } = await import("./brew-tui-bar-installer-5L4RUQF4.js");
|
|
6245
|
+
if (command === "uninstall-brew-tui-bar") {
|
|
6246
|
+
const { uninstallBrewTUIBar } = await import("./brew-tui-bar-installer-66P3MJVS.js");
|
|
6253
6247
|
try {
|
|
6254
6248
|
await uninstallBrewTUIBar();
|
|
6255
6249
|
console.log(t("cli_brewtuibarUninstalled"));
|
|
@@ -6260,7 +6254,7 @@ Snapshots: ${snapshots.length} (latest: ${latest ? formatDate(latest.capturedAt)
|
|
|
6260
6254
|
return;
|
|
6261
6255
|
}
|
|
6262
6256
|
if (command === "doctor") {
|
|
6263
|
-
const { runDoctor } = await import("./doctor-
|
|
6257
|
+
const { runDoctor } = await import("./doctor-GR3IXTWM.js");
|
|
6264
6258
|
await runDoctor();
|
|
6265
6259
|
return;
|
|
6266
6260
|
}
|
|
@@ -6284,7 +6278,7 @@ Snapshots: ${snapshots.length} (latest: ${latest ? formatDate(latest.capturedAt)
|
|
|
6284
6278
|
async function ensureBrewTUIBarRunning() {
|
|
6285
6279
|
if (process.platform !== "darwin") return;
|
|
6286
6280
|
await useLicenseStore.getState().initialize();
|
|
6287
|
-
const { syncAndLaunchBrewTUIBar } = await import("./brew-tui-bar-installer-
|
|
6281
|
+
const { syncAndLaunchBrewTUIBar } = await import("./brew-tui-bar-installer-66P3MJVS.js");
|
|
6288
6282
|
await syncAndLaunchBrewTUIBar();
|
|
6289
6283
|
}
|
|
6290
6284
|
runCli().catch((err) => {
|