@kud/foxhop-cli 1.1.1 → 1.1.3

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
@@ -3,7 +3,7 @@
3
3
  // src/cli.ts
4
4
  import { defineCommand, runMain } from "citty";
5
5
  import { spawn } from "child_process";
6
- import { existsSync as existsSync3 } from "fs";
6
+ import { existsSync as existsSync3, unlinkSync } from "fs";
7
7
 
8
8
  // src/config.ts
9
9
  import { mkdirSync, readFileSync, writeFileSync, existsSync } from "fs";
@@ -197,11 +197,19 @@ var install = () => {
197
197
  const distDir = dirname(fileURLToPath(import.meta.url));
198
198
  const hostEntry = join3(distDir, "host-cli.js");
199
199
  chmodSync(hostEntry, 493);
200
+ const wrapperPath = join3(distDir, "host-launch.sh");
201
+ writeFileSync2(
202
+ wrapperPath,
203
+ `#!/bin/sh
204
+ exec ${JSON.stringify(process.execPath)} ${JSON.stringify(hostEntry)} "$@"
205
+ `
206
+ );
207
+ chmodSync(wrapperPath, 493);
200
208
  mkdirSync2(MANIFEST_DIR, { recursive: true });
201
209
  const manifest = {
202
210
  name: HOST_NAME,
203
211
  description: "foxhop native messaging host",
204
- path: hostEntry,
212
+ path: wrapperPath,
205
213
  type: "stdio",
206
214
  allowed_extensions: [EXTENSION_ID]
207
215
  };
@@ -209,7 +217,8 @@ var install = () => {
209
217
  process.stdout.write(
210
218
  `foxhop: installed native host manifest
211
219
  manifest \u2192 ${MANIFEST_PATH}
212
- host \u2192 ${hostEntry}
220
+ host \u2192 ${wrapperPath}
221
+ node \u2192 ${process.execPath}
213
222
  `
214
223
  );
215
224
  };
@@ -289,6 +298,20 @@ var clearScripts = (dir = defaultScriptsDir()) => {
289
298
 
290
299
  // src/cli.ts
291
300
  import { fileURLToPath as fileURLToPath2 } from "url";
301
+
302
+ // src/ui.ts
303
+ var enabled = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;
304
+ var paint = (code) => (text) => enabled ? `\x1B[${code}m${text}\x1B[0m` : text;
305
+ var bold = paint(1);
306
+ var dim = paint(2);
307
+ var red = paint(31);
308
+ var green = paint(32);
309
+ var yellow = paint(33);
310
+ var cyan = paint(36);
311
+ var ok = (message) => `${green("\u2713")} ${message}`;
312
+ var fail = (message) => `${red("\u2717")} ${message}`;
313
+
314
+ // src/cli.ts
292
315
  var browserApp = () => process.env.FOXHOP_BROWSER ?? "Firefox Nightly";
293
316
  var runOpen = (args) => {
294
317
  const child = spawn("/usr/bin/open", args, {
@@ -341,7 +364,9 @@ var focus = defineCommand({
341
364
  } : resolveNamed(String(args.name ?? ""));
342
365
  if (!request) {
343
366
  console.error(
344
- `foxhop: no target named "${args.name}". Edit ${CONFIG_PATH}, or run \`foxhop list\` / \`foxhop init\`.`
367
+ fail(
368
+ `no target named "${args.name}". Edit ${CONFIG_PATH}, or run \`foxhop list\` / \`foxhop init\`.`
369
+ )
345
370
  );
346
371
  process.exit(1);
347
372
  }
@@ -349,15 +374,30 @@ var focus = defineCommand({
349
374
  const ack = await sendToHost(request);
350
375
  if (ack?.ok && ack.action !== "not-found") foreground();
351
376
  else
377
+ console.error(fail(ack?.error ?? "no matching tab and no url to open"));
378
+ } catch (error) {
379
+ const code = error?.code;
380
+ if (code === "ECONNREFUSED" || code === "ENOENT") {
381
+ if (existsSync3(SOCKET_PATH)) {
382
+ try {
383
+ unlinkSync(SOCKET_PATH);
384
+ } catch {
385
+ }
386
+ }
352
387
  console.error(
353
- `foxhop: ${ack?.error ?? "no matching tab and no url to open"}`
388
+ fail(
389
+ "foxhop host not running. Run `foxhop install`, then restart Firefox (or reload the extension)."
390
+ )
354
391
  );
355
- } catch {
392
+ process.exit(1);
393
+ }
356
394
  if ("url" in request && request.url) {
357
395
  openUrl(request.url);
358
396
  } else {
359
397
  console.error(
360
- "foxhop: cannot reach the host \u2014 is Firefox running with the foxhop extension?"
398
+ fail(
399
+ "cannot reach the host \u2014 is Firefox running with the foxhop extension?"
400
+ )
361
401
  );
362
402
  process.exit(1);
363
403
  }
@@ -386,7 +426,9 @@ var list = defineCommand({
386
426
  }
387
427
  if (!targets.length) {
388
428
  console.log(
389
- `No targets yet. Run \`foxhop init\` for an example, or edit ${CONFIG_PATH}.`
429
+ dim(
430
+ `No targets yet. Run \`foxhop init\` for an example, or edit ${CONFIG_PATH}.`
431
+ )
390
432
  );
391
433
  return;
392
434
  }
@@ -394,9 +436,12 @@ var list = defineCommand({
394
436
  ...targets.filter((target) => target.favorite),
395
437
  ...targets.filter((target) => !target.favorite)
396
438
  ];
439
+ const width = Math.max(...ordered.map((target) => target.name.length));
397
440
  for (const target of ordered) {
398
- const star = target.favorite ? "\u2605 " : " ";
399
- console.log(`${star}${target.name.padEnd(16)} ${target.match}`);
441
+ const star = target.favorite ? yellow("\u2605") : " ";
442
+ console.log(
443
+ `${star} ${cyan(target.name.padEnd(width))} ${dim(target.match)}`
444
+ );
400
445
  }
401
446
  }
402
447
  });
@@ -412,13 +457,13 @@ var tabs = defineCommand({
412
457
  }
413
458
  if (!openTabs.length) {
414
459
  console.error(
415
- "foxhop: no tabs (is Firefox running with the foxhop extension?)"
460
+ fail("no tabs \u2014 is Firefox running with the foxhop extension?")
416
461
  );
417
462
  process.exit(1);
418
463
  }
419
464
  for (const tab of openTabs) {
420
- console.log(`${tab.title}
421
- ${tab.url}`);
465
+ console.log(`${bold(tab.title)}
466
+ ${dim(tab.url)}`);
422
467
  }
423
468
  }
424
469
  });
@@ -429,7 +474,7 @@ var init = defineCommand({
429
474
  },
430
475
  run: () => {
431
476
  const path = writeExampleConfig();
432
- console.log(`foxhop: wrote example config and schema next to ${path}`);
477
+ console.log(ok(`wrote example config + schema \u2192 ${dim(path)}`));
433
478
  }
434
479
  });
435
480
  var installCommand = defineCommand({
@@ -463,7 +508,9 @@ var syncCommand = defineCommand({
463
508
  return;
464
509
  }
465
510
  console.log(
466
- `foxhop: removed ${cleared.removed} script(s) from ${cleared.dir}`
511
+ ok(
512
+ `removed ${bold(String(cleared.removed))} script(s) \u2192 ${dim(cleared.dir)}`
513
+ )
467
514
  );
468
515
  return;
469
516
  }
@@ -477,10 +524,14 @@ var syncCommand = defineCommand({
477
524
  return;
478
525
  }
479
526
  console.log(
480
- `foxhop: wrote ${result.written} script(s)` + (result.removed ? `, removed ${result.removed} stale` : "") + ` in ${result.dir}`
527
+ ok(
528
+ `wrote ${bold(String(result.written))} script(s)` + (result.removed ? `, removed ${result.removed} stale` : "") + ` \u2192 ${dim(result.dir)}`
529
+ )
481
530
  );
482
531
  console.log(
483
- "Add that folder in Raycast \u2192 Extensions \u2192 Script Commands \u2192 Add Directories, then assign hotkeys."
532
+ dim(
533
+ "Add that folder in Raycast \u2192 Extensions \u2192 Script Commands \u2192 Add Directories, then assign hotkeys."
534
+ )
484
535
  );
485
536
  }
486
537
  });
@@ -519,7 +570,7 @@ var add = defineCommand({
519
570
  const matchArg = args.match ? String(args.match) : void 0;
520
571
  const source = url ?? matchArg;
521
572
  if (!source) {
522
- console.error("foxhop: provide a URL or --match");
573
+ console.error(fail("provide a URL or --match"));
523
574
  process.exit(1);
524
575
  }
525
576
  const derived = deriveTarget(source);
@@ -534,7 +585,7 @@ var add = defineCommand({
534
585
  pick: args.pick,
535
586
  favorite: args.favorite || existing?.favorite ? true : void 0
536
587
  });
537
- console.log(`foxhop: saved "${name}"`);
588
+ console.log(ok(`saved ${bold(name)}`));
538
589
  autoSync();
539
590
  }
540
591
  });
@@ -550,10 +601,10 @@ var remove = defineCommand({
550
601
  run: ({ args }) => {
551
602
  const { removed } = removeTarget(String(args.name));
552
603
  if (!removed) {
553
- console.error(`foxhop: no target named "${args.name}"`);
604
+ console.error(fail(`no target named "${args.name}"`));
554
605
  process.exit(1);
555
606
  }
556
- console.log(`foxhop: removed "${args.name}"`);
607
+ console.log(ok(`removed ${bold(String(args.name))}`));
557
608
  autoSync();
558
609
  }
559
610
  });
@@ -572,11 +623,13 @@ var fav = defineCommand({
572
623
  run: ({ args }) => {
573
624
  const { favorite, found } = toggleFavorite(String(args.name));
574
625
  if (!found) {
575
- console.error(`foxhop: no target named "${args.name}"`);
626
+ console.error(fail(`no target named "${args.name}"`));
576
627
  process.exit(1);
577
628
  }
578
629
  console.log(
579
- `foxhop: "${args.name}" ${favorite ? "favourited \u2605" : "unfavourited"}`
630
+ ok(
631
+ `${bold(String(args.name))} ${favorite ? yellow("favourited \u2605") : "unfavourited"}`
632
+ )
580
633
  );
581
634
  }
582
635
  });
package/dist/host-cli.js CHANGED
@@ -58,13 +58,18 @@ var runHost = () => {
58
58
  resolve(ack);
59
59
  })
60
60
  );
61
- process.stdin.on("end", () => process.exit(0));
62
- if (existsSync(SOCKET_PATH)) {
61
+ const cleanup = () => {
63
62
  try {
64
- unlinkSync(SOCKET_PATH);
63
+ if (existsSync(SOCKET_PATH)) unlinkSync(SOCKET_PATH);
65
64
  } catch {
66
65
  }
67
- }
66
+ };
67
+ process.stdin.on("end", () => {
68
+ cleanup();
69
+ process.exit(0);
70
+ });
71
+ process.on("exit", cleanup);
72
+ cleanup();
68
73
  const server = net.createServer((socket) => {
69
74
  socket.setEncoding("utf8");
70
75
  let raw = "";
@@ -107,11 +112,19 @@ var install = () => {
107
112
  const distDir = dirname(fileURLToPath(import.meta.url));
108
113
  const hostEntry = join2(distDir, "host-cli.js");
109
114
  chmodSync(hostEntry, 493);
115
+ const wrapperPath = join2(distDir, "host-launch.sh");
116
+ writeFileSync(
117
+ wrapperPath,
118
+ `#!/bin/sh
119
+ exec ${JSON.stringify(process.execPath)} ${JSON.stringify(hostEntry)} "$@"
120
+ `
121
+ );
122
+ chmodSync(wrapperPath, 493);
110
123
  mkdirSync(MANIFEST_DIR, { recursive: true });
111
124
  const manifest = {
112
125
  name: HOST_NAME,
113
126
  description: "foxhop native messaging host",
114
- path: hostEntry,
127
+ path: wrapperPath,
115
128
  type: "stdio",
116
129
  allowed_extensions: [EXTENSION_ID]
117
130
  };
@@ -119,7 +132,8 @@ var install = () => {
119
132
  process.stdout.write(
120
133
  `foxhop: installed native host manifest
121
134
  manifest \u2192 ${MANIFEST_PATH}
122
- host \u2192 ${hostEntry}
135
+ host \u2192 ${wrapperPath}
136
+ node \u2192 ${process.execPath}
123
137
  `
124
138
  );
125
139
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/foxhop-cli",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "foxhop CLI and native messaging host — focus specific Firefox tabs from macOS",
5
5
  "type": "module",
6
6
  "license": "MIT",