chrome-relay 0.5.21 → 0.5.22

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/dist/cli.js CHANGED
@@ -1101,7 +1101,7 @@ var init_dist = __esm({
1101
1101
  import { Command } from "commander";
1102
1102
 
1103
1103
  // src/index.ts
1104
- var CHROME_RELAY_VERSION = true ? "0.5.21" : "0.0.0-dev";
1104
+ var CHROME_RELAY_VERSION = true ? "0.5.22" : "0.0.0-dev";
1105
1105
 
1106
1106
  // src/commands/shared.ts
1107
1107
  init_dist();
@@ -1255,18 +1255,52 @@ function getDefaultAllowedOrigins() {
1255
1255
  function formatKnownExtensionIds() {
1256
1256
  return KNOWN_EXTENSION_IDS.map(([label, id]) => `${label}: ${id}`).join(", ");
1257
1257
  }
1258
- function getChromeManifestDir() {
1258
+ function getChromiumBrowserTargets() {
1259
+ const home = os.homedir();
1259
1260
  if (process.platform === "darwin") {
1260
- return path.join(
1261
- os.homedir(),
1262
- "Library/Application Support/Google/Chrome/NativeMessagingHosts"
1263
- );
1261
+ const appSupport = path.join(home, "Library/Application Support");
1262
+ return [
1263
+ { label: "Google Chrome", installRoot: path.join(appSupport, "Google/Chrome"), manifestDir: path.join(appSupport, "Google/Chrome/NativeMessagingHosts") },
1264
+ { label: "Google Chrome Canary", installRoot: path.join(appSupport, "Google/Chrome Canary"), manifestDir: path.join(appSupport, "Google/Chrome Canary/NativeMessagingHosts") },
1265
+ { label: "Chromium", installRoot: path.join(appSupport, "Chromium"), manifestDir: path.join(appSupport, "Chromium/NativeMessagingHosts") },
1266
+ { label: "Microsoft Edge", installRoot: path.join(appSupport, "Microsoft Edge"), manifestDir: path.join(appSupport, "Microsoft Edge/NativeMessagingHosts") },
1267
+ { label: "Brave", installRoot: path.join(appSupport, "BraveSoftware/Brave-Browser"), manifestDir: path.join(appSupport, "BraveSoftware/Brave-Browser/NativeMessagingHosts") },
1268
+ { label: "Vivaldi", installRoot: path.join(appSupport, "Vivaldi"), manifestDir: path.join(appSupport, "Vivaldi/NativeMessagingHosts") },
1269
+ { label: "Arc", installRoot: path.join(appSupport, "Arc/User Data"), manifestDir: path.join(appSupport, "Arc/User Data/NativeMessagingHosts") },
1270
+ { label: "Opera", installRoot: path.join(appSupport, "com.operasoftware.Opera"), manifestDir: path.join(appSupport, "com.operasoftware.Opera/NativeMessagingHosts") }
1271
+ ];
1264
1272
  }
1265
1273
  if (process.platform === "linux") {
1266
- return path.join(os.homedir(), ".config/google-chrome/NativeMessagingHosts");
1274
+ const config = path.join(home, ".config");
1275
+ return [
1276
+ { label: "Google Chrome", installRoot: path.join(config, "google-chrome"), manifestDir: path.join(config, "google-chrome/NativeMessagingHosts") },
1277
+ { label: "Chromium", installRoot: path.join(config, "chromium"), manifestDir: path.join(config, "chromium/NativeMessagingHosts") },
1278
+ { label: "Microsoft Edge", installRoot: path.join(config, "microsoft-edge"), manifestDir: path.join(config, "microsoft-edge/NativeMessagingHosts") },
1279
+ { label: "Brave", installRoot: path.join(config, "BraveSoftware/Brave-Browser"), manifestDir: path.join(config, "BraveSoftware/Brave-Browser/NativeMessagingHosts") },
1280
+ { label: "Vivaldi", installRoot: path.join(config, "vivaldi"), manifestDir: path.join(config, "vivaldi/NativeMessagingHosts") },
1281
+ { label: "Opera", installRoot: path.join(config, "opera"), manifestDir: path.join(config, "opera/NativeMessagingHosts") }
1282
+ ];
1267
1283
  }
1268
1284
  throw new Error(`Unsupported platform for install: ${process.platform}`);
1269
1285
  }
1286
+ async function pathExists(p) {
1287
+ try {
1288
+ await stat(p);
1289
+ return true;
1290
+ } catch {
1291
+ return false;
1292
+ }
1293
+ }
1294
+ async function getInstalledBrowsers() {
1295
+ const all = getChromiumBrowserTargets();
1296
+ const installed = [];
1297
+ for (const target of all) {
1298
+ if (await pathExists(target.installRoot)) {
1299
+ installed.push(target);
1300
+ }
1301
+ }
1302
+ return installed;
1303
+ }
1270
1304
  function getDistDir() {
1271
1305
  return path.dirname(fileURLToPath(import.meta.url));
1272
1306
  }
@@ -1280,10 +1314,7 @@ exec "${process.execPath}" "${hostPath}"
1280
1314
  await chmod(wrapperPath, 493);
1281
1315
  return wrapperPath;
1282
1316
  }
1283
- async function writeManifest(wrapperPath) {
1284
- const manifestDir = getChromeManifestDir();
1285
- await mkdir(manifestDir, { recursive: true });
1286
- const manifestPath = path.join(manifestDir, `${NATIVE_HOST_NAME}.json`);
1317
+ async function writeManifestsForBrowsers(wrapperPath, browsers) {
1287
1318
  const manifest = {
1288
1319
  name: NATIVE_HOST_NAME,
1289
1320
  description: "Native host for Chrome Relay",
@@ -1291,9 +1322,16 @@ async function writeManifest(wrapperPath) {
1291
1322
  type: "stdio",
1292
1323
  allowed_origins: getDefaultAllowedOrigins()
1293
1324
  };
1294
- await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}
1295
- `, "utf8");
1296
- return manifestPath;
1325
+ const body = `${JSON.stringify(manifest, null, 2)}
1326
+ `;
1327
+ const written = [];
1328
+ for (const target of browsers) {
1329
+ await mkdir(target.manifestDir, { recursive: true });
1330
+ const manifestPath = path.join(target.manifestDir, `${NATIVE_HOST_NAME}.json`);
1331
+ await writeFile(manifestPath, body, "utf8");
1332
+ written.push({ browser: target.label, manifestPath });
1333
+ }
1334
+ return written;
1297
1335
  }
1298
1336
  function killStaleNativeHosts() {
1299
1337
  if (process.platform !== "darwin" && process.platform !== "linux") {
@@ -1322,28 +1360,66 @@ async function runInstall() {
1322
1360
  const distDir = getDistDir();
1323
1361
  const hostPath = path.join(distDir, "native-host.js");
1324
1362
  const wrapperPath = await writeWrapperScript(hostPath);
1325
- const manifestPath = await writeManifest(wrapperPath);
1363
+ const installed = await getInstalledBrowsers();
1364
+ if (installed.length === 0) {
1365
+ const all = getChromiumBrowserTargets();
1366
+ const fallback = all.find((t) => t.label === "Google Chrome");
1367
+ if (fallback) installed.push(fallback);
1368
+ }
1369
+ const writtenManifests = await writeManifestsForBrowsers(wrapperPath, installed);
1326
1370
  const { killed } = killStaleNativeHosts();
1327
1371
  console.log(`Installed Chrome Relay native host.`);
1328
1372
  console.log(`Wrapper: ${wrapperPath}`);
1329
- console.log(`Manifest: ${manifestPath}`);
1373
+ console.log(`Manifests written:`);
1374
+ for (const m of writtenManifests) {
1375
+ console.log(` \u2022 ${m.browser}: ${m.manifestPath}`);
1376
+ }
1330
1377
  console.log(`Local bridge port: ${DEFAULT_HTTP_PORT}`);
1331
1378
  console.log(`Allowed extension IDs: ${formatKnownExtensionIds()}`);
1332
1379
  if (killed > 0) {
1333
- console.log(`Reaped ${killed} stale native-host process${killed === 1 ? "" : "es"}; Chrome will respawn from the new manifest.`);
1380
+ console.log(`Reaped ${killed} stale native-host process${killed === 1 ? "" : "es"}; browsers will respawn from the new manifest.`);
1334
1381
  }
1335
1382
  }
1336
1383
  async function runDoctor() {
1337
1384
  try {
1338
1385
  const wrapperPath = path.join(APP_DIR, "run-host.sh");
1339
- const manifestPath = path.join(getChromeManifestDir(), `${NATIVE_HOST_NAME}.json`);
1340
1386
  await stat(wrapperPath);
1341
- await stat(manifestPath);
1342
- const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
1343
- const allowedOrigins = Array.isArray(manifest.allowed_origins) ? manifest.allowed_origins : [];
1344
- const missingOrigins = getDefaultAllowedOrigins().filter(
1345
- (origin) => !allowedOrigins.includes(origin)
1346
- );
1387
+ console.log(`Wrapper present: yes`);
1388
+ const installed = await getInstalledBrowsers();
1389
+ if (installed.length === 0) {
1390
+ console.log(`No Chromium-based browsers detected.`);
1391
+ console.log(`Tip: install Chrome / Arc / Brave / Edge / Chromium / Vivaldi / Opera then re-run "chrome-relay install".`);
1392
+ return false;
1393
+ }
1394
+ const required = getDefaultAllowedOrigins();
1395
+ let allHealthy = true;
1396
+ console.log(`Detected browsers (${installed.length}):`);
1397
+ for (const target of installed) {
1398
+ const manifestPath = path.join(target.manifestDir, `${NATIVE_HOST_NAME}.json`);
1399
+ const exists = await pathExists(manifestPath);
1400
+ if (!exists) {
1401
+ allHealthy = false;
1402
+ console.log(` \u2022 ${target.label}: manifest MISSING (${manifestPath})`);
1403
+ continue;
1404
+ }
1405
+ try {
1406
+ const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
1407
+ const allowedOrigins = Array.isArray(manifest.allowed_origins) ? manifest.allowed_origins : [];
1408
+ const missingOrigins = required.filter((o) => !allowedOrigins.includes(o));
1409
+ if (missingOrigins.length > 0) {
1410
+ allHealthy = false;
1411
+ console.log(` \u2022 ${target.label}: manifest present but missing origins: ${missingOrigins.join(", ")}`);
1412
+ } else {
1413
+ console.log(` \u2022 ${target.label}: ok`);
1414
+ }
1415
+ } catch (e) {
1416
+ allHealthy = false;
1417
+ console.log(` \u2022 ${target.label}: manifest unreadable (${e instanceof Error ? e.message : String(e)})`);
1418
+ }
1419
+ }
1420
+ if (!allHealthy) {
1421
+ console.log(`Tip: run "chrome-relay install" to refresh manifests for every detected browser.`);
1422
+ }
1347
1423
  let serverReachable = false;
1348
1424
  try {
1349
1425
  const response = await fetch(`http://127.0.0.1:${DEFAULT_HTTP_PORT}/ping`);
@@ -1351,19 +1427,12 @@ async function runDoctor() {
1351
1427
  } catch {
1352
1428
  serverReachable = false;
1353
1429
  }
1354
- console.log(`Wrapper present: yes`);
1355
- console.log(`Manifest present: yes`);
1356
1430
  console.log(`Allowed extension IDs: ${formatKnownExtensionIds()}`);
1357
- console.log(`Allowed origins: ${(manifest.allowed_origins ?? ["missing"]).join(", ")}`);
1358
- if (missingOrigins.length > 0) {
1359
- console.log(`Manifest missing origins: ${missingOrigins.join(", ")}`);
1360
- console.log(`Tip: run "chrome-relay install" to refresh the native host manifest.`);
1361
- }
1362
1431
  console.log(`Local bridge reachable: ${serverReachable ? "yes" : "no"}`);
1363
1432
  if (!serverReachable) {
1364
- console.log(`Tip: load the extension so it can launch the native host.`);
1433
+ console.log(`Tip: load the extension in one of the detected browsers so it can launch the native host.`);
1365
1434
  }
1366
- return true;
1435
+ return allHealthy;
1367
1436
  } catch (error) {
1368
1437
  console.error(error instanceof Error ? error.message : String(error));
1369
1438
  return false;
@@ -1372,6 +1441,12 @@ async function runDoctor() {
1372
1441
 
1373
1442
  // src/release-notes.ts
1374
1443
  var RELEASE_NOTES = {
1444
+ "0.5.22": [
1445
+ "Multi-browser install. `chrome-relay install` now writes the native-messaging manifest into every detected Chromium-fork browser's NativeMessagingHosts dir, not just Google Chrome's. Detected: Chrome, Chrome Canary, Chromium, Edge, Brave, Vivaldi, Arc, Opera (macOS + Linux paths). Detection is parent-dir existence \u2014 we never speculatively create profile dirs for browsers that aren't installed.",
1446
+ "Why this matters: the extension installs fine via Chrome Web Store in any Chromium fork, but the bridge silently failed because the host manifest was only at Chrome's path. Arc + Brave users hit `connectNative()` errors with no obvious cause.",
1447
+ "`chrome-relay doctor` now reports per-browser manifest status, so when a refresh is needed the failure points at the specific browser whose manifest drifted.",
1448
+ "Fallback: if no Chromium browser is detected on the machine, we still drop the manifest at Chrome's path so a later Chrome install picks it up."
1449
+ ],
1375
1450
  "0.5.21": [
1376
1451
  "Fix: `chrome-relay update` and `chrome-relay install` now SIGTERM any running native-host.js process before exiting, and `update` re-runs `install` from the freshly-installed binary. Chrome respawns the host from the new manifest on its next native-messaging request.",
1377
1452
  "Why this matters: Chrome's native messaging keeps the host process alive for the session. Pre-0.5.21, `chrome-relay update` refreshed the on-disk package but Chrome kept routing through the OLD host. The HTTP bridge served by that old host then reported its own embedded `CHROME_RELAY_VERSION`, which falsely tripped the cli-outdated nudge against the newer extension. Users running the very command the nudge told them to run found the nudge still firing afterwards \u2014 the worst kind of UX bug.",
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- var CHROME_RELAY_VERSION = true ? "0.5.21" : "0.0.0-dev";
2
+ var CHROME_RELAY_VERSION = true ? "0.5.22" : "0.0.0-dev";
3
3
  export {
4
4
  CHROME_RELAY_VERSION
5
5
  };
@@ -56,7 +56,7 @@ function toBridgeError(unknownErr, fallbackTool) {
56
56
  }
57
57
 
58
58
  // src/index.ts
59
- var CHROME_RELAY_VERSION = true ? "0.5.21" : "0.0.0-dev";
59
+ var CHROME_RELAY_VERSION = true ? "0.5.22" : "0.0.0-dev";
60
60
 
61
61
  // src/release-notes.ts
62
62
  function compareSemver(a, b) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-relay",
3
- "version": "0.5.21",
3
+ "version": "0.5.22",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",