browser-cookie-bridge 1.4.1 → 1.4.2

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
@@ -108,7 +108,7 @@ Run the published package directly:
108
108
  npx browser-cookie-bridge install-app
109
109
  ```
110
110
 
111
- No administrator password is needed. The app is built from source on your Mac and installed in your user Applications folder unless an existing writable system Applications copy is being updated.
111
+ No administrator password is needed. The app is built from source on your Mac and installed in your user Applications folder. If a signed `/Applications/Browser Cookie Bridge.app` already exists, the CLI preserves it instead of replacing its Developer ID signature with an ad-hoc local build; use the app's built-in updater for signed releases.
112
112
 
113
113
  Both installation methods use the same bundle identifier and the same settings under `~/Library/Application Support/BraveCodexCookieSync`. Installing the DMG after npm does not create a separate product identity: the system Applications copy becomes canonical, and a stale matching user Applications copy is moved to the Trash on launch. Future updates replace that same app in place.
114
114
 
@@ -123,7 +123,7 @@ npm test
123
123
  npm run build:app
124
124
  ```
125
125
 
126
- The final command compiles the native SwiftUI app, enables **Open at login**, **Sync at login**, and the **menu-bar helper**, then launches it. A first install uses `~/Applications/Browser Cookie Bridge.app` without requesting administrator access. If an existing `/Applications/Browser Cookie Bridge.app` is present, later builds and updates keep using that system Applications copy instead of creating a duplicate. Daily sync stays off until you enable it.
126
+ The final command compiles the native SwiftUI app, enables **Open at login**, **Sync at login**, and the **menu-bar helper**, then launches it. A first install uses `~/Applications/Browser Cookie Bridge.app` without requesting administrator access. If an existing signed `/Applications/Browser Cookie Bridge.app` is present, the CLI keeps that system copy canonical and leaves app updates to the signed-DMG updater. Developers who intentionally need to replace it with a local ad-hoc build can pass `--replace-system-from-source`. Daily sync stays off until you enable it.
127
127
 
128
128
  ## Setup
129
129
 
@@ -186,7 +186,7 @@ Automation uses the saved source, destination, and data choices for local transf
186
186
  ## CLI
187
187
 
188
188
  ```bash
189
- browser-cookie-bridge install-app [--no-open]
189
+ browser-cookie-bridge install-app [--no-open] [--replace-system-from-source]
190
190
  browser-cookie-bridge setup [--hour 9] [--minute 0] [--no-schedule]
191
191
  browser-cookie-bridge preferences --source brave --target codex --cookies on --history off --auto-restart-codex off
192
192
  browser-cookie-bridge sync [--timeout 300] [--allow-cloud-upload]
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Browser Cookie Bridge",
4
- "version": "1.4.1",
4
+ "version": "1.4.2",
5
5
  "description": "Transfers selected browser data locally between supported browsers and into ChatGPT Codex.",
6
6
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5o6lDkXzU/23Jm2QRk4mfuxNnr3VlEIjRHcZr93Gdo7PI7asHJQhigaMGT6UOz0lkaTn1F+TGIPlsJo9GNBSsxbCfxWoBSXcFQFrPolY5LEfKaMtZQQ6eb4UAnp+bbUwb1den4On0piWU47Yzl6i0Jcdg4EG5H1kCSF/6nJsbKgF7OTaR/3drULu40yRvflzSXRhly3UDO7c5mgHJsaMwVV+VILsxbcPOoRINjuo3zDC737HFs67dpf38xF3tjSVL0HURAWKKobMvfABiDfVEm5O0Lvf+57d1Ib12QLT2qtVXNDy3iYwX+w2S0wH2vIMsfvoFPlRdmeqft70kZOqXwIDAQAB",
7
7
  "permissions": ["alarms", "cookies", "history"],
@@ -10,8 +10,8 @@
10
10
  <key>CFBundleInfoDictionaryVersion</key><string>6.0</string>
11
11
  <key>CFBundleName</key><string>Browser Cookie Bridge</string>
12
12
  <key>CFBundlePackageType</key><string>APPL</string>
13
- <key>CFBundleShortVersionString</key><string>1.4.1</string>
14
- <key>CFBundleVersion</key><string>29</string>
13
+ <key>CFBundleShortVersionString</key><string>1.4.2</string>
14
+ <key>CFBundleVersion</key><string>30</string>
15
15
  <key>LSMinimumSystemVersion</key><string>13.5</string>
16
16
  <key>NSHighResolutionCapable</key><true/>
17
17
  </dict>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-cookie-bridge",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "description": "Local-first cookie and session transfer for macOS with optional Browserless upload",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,7 +11,7 @@
11
11
  "test:web-worker": "node --test web/worker/*.test.mjs",
12
12
  "check": "node --check bin/brave-codex-cookie-sync.js && node --check src/app-installer.js && node --check src/browserless.js && node --check src/browserless-preflight.js && node --check src/browserless-runner.js && node --check src/broker.js && node --check src/chromium-reader.js && node --check src/cli.js && node --check src/codex-direct-import.js && node --check src/config.js && node --check src/paths.js && node --check src/scheduler.js && node --check src/updater.js && node --check scripts/build-dmg.js && node --check extension-template/background.js && node --check web/server.js && node --check web/script.js",
13
13
  "release:check": "node scripts/check-release-version.js",
14
- "build:app": "node bin/brave-codex-cookie-sync.js install-app --no-open",
14
+ "build:app": "node bin/brave-codex-cookie-sync.js install-app --no-open --replace-system-from-source",
15
15
  "build:dmg": "node scripts/build-dmg.js",
16
16
  "web": "node web/server.js",
17
17
  "web:deploy": "wrangler deploy --config web/wrangler.jsonc"
@@ -2,11 +2,25 @@ import fs from "node:fs";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { spawnSync } from "node:child_process";
5
- import { appSupportDir, installedAppPath, projectRoot } from "./paths.js";
5
+ import {
6
+ appSupportDir,
7
+ installedAppPath,
8
+ projectRoot,
9
+ systemInstalledAppPath,
10
+ } from "./paths.js";
6
11
 
7
- export function installApp({ home = os.homedir(), open = true } = {}) {
12
+ export function installApp({ home = os.homedir(), open = true, preserveSystemApp = true } = {}) {
8
13
  if (process.platform !== "darwin") throw new Error("The desktop app supports macOS only.");
9
14
 
15
+ const destination = installedAppPath(home);
16
+ const isSystemInstall = path.resolve(destination) === path.resolve(systemInstalledAppPath());
17
+ if (isSystemInstall && preserveSystemApp) {
18
+ console.log(`Preserving the signed installation at ${destination}`);
19
+ console.log("Use Check for Updates in the app to install signed releases.");
20
+ if (open) run("open", [destination]);
21
+ return destination;
22
+ }
23
+
10
24
  const packagePath = path.join(projectRoot(), "macos-app");
11
25
  run("swift", ["build", "-c", "release", "--package-path", packagePath]);
12
26
  const binPath = run("swift", [
@@ -32,7 +46,6 @@ export function installApp({ home = os.homedir(), open = true } = {}) {
32
46
 
33
47
  run("codesign", ["--force", "--deep", "--sign", "-", staging]);
34
48
 
35
- const destination = installedAppPath(home);
36
49
  fs.mkdirSync(path.dirname(destination), { recursive: true, mode: 0o755 });
37
50
  fs.rmSync(destination, { recursive: true, force: true });
38
51
  fs.cpSync(staging, destination, { recursive: true, force: true });
package/src/cli.js CHANGED
@@ -24,6 +24,7 @@ import {
24
24
  systemInstalledAppPath,
25
25
  userInstalledAppPath,
26
26
  APP_ID,
27
+ APP_BUNDLE_ID,
27
28
  SOURCE_BROWSERS,
28
29
  TARGET_BROWSERS,
29
30
  } from "./paths.js";
@@ -43,7 +44,7 @@ Local cookie and session transfer between Chromium browsers and into ChatGPT Cod
43
44
 
44
45
  Commands:
45
46
  setup [--hour 9] [--minute 0] [--no-schedule]
46
- install-app [--no-open]
47
+ install-app [--no-open] [--replace-system-from-source]
47
48
  bootstrap-bundled --app-path /Applications/Browser Cookie Bridge.app
48
49
  preferences --source brave --target codex --cookies on --history off --menu-bar on --auto-check-updates on --auto-restart-codex off
49
50
  sync [--timeout 300] [--allow-cloud-upload]
@@ -147,8 +148,11 @@ function installDesktopApp(args) {
147
148
  hour: existing?.schedule?.hour ?? 9,
148
149
  minute: existing?.schedule?.minute ?? 0,
149
150
  });
150
- console.log("Building the native macOS app…");
151
- const destination = installApp({ open: !args.includes("--no-open") });
151
+ console.log("Preparing the native macOS app…");
152
+ const destination = installApp({
153
+ open: !args.includes("--no-open"),
154
+ preserveSystemApp: !args.includes("--replace-system-from-source"),
155
+ });
152
156
  if (config.ui.openAtLogin) {
153
157
  installAppLogin({ appPath: destination, bootstrapNow: false });
154
158
  } else {
@@ -214,7 +218,7 @@ function archiveDuplicateUserApp(currentAppPath) {
214
218
  if (!fs.existsSync(duplicate)) return;
215
219
  const infoPath = path.join(duplicate, "Contents", "Info.plist");
216
220
  const info = fs.existsSync(infoPath) ? fs.readFileSync(infoPath, "utf8") : "";
217
- if (!info.includes(`<string>${APP_ID}</string>`)) return;
221
+ if (!info.includes(`<string>${APP_BUNDLE_ID}</string>`)) return;
218
222
 
219
223
  const trash = path.join(os.homedir(), ".Trash");
220
224
  fs.mkdirSync(trash, { recursive: true, mode: 0o700 });
package/src/paths.js CHANGED
@@ -4,6 +4,7 @@ import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
 
6
6
  export const APP_ID = "com.apoorvdarshan.brave-codex-cookie-sync";
7
+ export const APP_BUNDLE_ID = "com.apoorvdarshan.browser-cookie-bridge";
7
8
  export const LOGIN_SYNC_APP_ID = `${APP_ID}.login-sync`;
8
9
  export const APP_LOGIN_APP_ID = `${APP_ID}.app-login`;
9
10
  export const DEFAULT_PORT = 43128;
@@ -48,10 +49,22 @@ export function systemInstalledAppPath() {
48
49
  return path.join("/Applications", "Browser Cookie Bridge.app");
49
50
  }
50
51
 
52
+ export function isAppBundleWithIdentifier(appPath, identifier = APP_BUNDLE_ID) {
53
+ const infoPath = path.join(appPath, "Contents", "Info.plist");
54
+ if (!fs.existsSync(infoPath)) return false;
55
+ try {
56
+ const info = fs.readFileSync(infoPath, "utf8");
57
+ const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
58
+ return new RegExp(`<key>CFBundleIdentifier</key>\\s*<string>${escaped}</string>`).test(info);
59
+ } catch {
60
+ return false;
61
+ }
62
+ }
63
+
51
64
  export function installedAppPath(home = os.homedir()) {
52
65
  const systemApp = systemInstalledAppPath();
53
66
  const isCurrentUser = path.resolve(home) === path.resolve(os.homedir());
54
- return isCurrentUser && fs.existsSync(systemApp) ? systemApp : userInstalledAppPath(home);
67
+ return isCurrentUser && isAppBundleWithIdentifier(systemApp) ? systemApp : userInstalledAppPath(home);
55
68
  }
56
69
 
57
70
  export function braveCookiePaths(home = os.homedir()) {