@claude-sync/cli 0.1.4 → 0.1.6

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.
@@ -4525,12 +4525,18 @@ var init_config = __esm({
4525
4525
  });
4526
4526
 
4527
4527
  // src/lib/api-client.ts
4528
- var ApiClient;
4528
+ var AuthExpiredError, ApiClient;
4529
4529
  var init_api_client = __esm({
4530
4530
  "src/lib/api-client.ts"() {
4531
4531
  "use strict";
4532
4532
  init_esm_shims();
4533
4533
  init_auth();
4534
+ AuthExpiredError = class extends Error {
4535
+ constructor() {
4536
+ super("Session expired");
4537
+ this.name = "AuthExpiredError";
4538
+ }
4539
+ };
4534
4540
  ApiClient = class {
4535
4541
  baseUrl;
4536
4542
  constructor(baseUrl) {
@@ -4555,7 +4561,7 @@ var init_api_client = __esm({
4555
4561
  clearTimeout(timeout);
4556
4562
  if (!response.ok) {
4557
4563
  if (response.status === 401) {
4558
- throw new Error("Session expired. Run `claude-sync login` to re-authenticate.");
4564
+ throw new AuthExpiredError();
4559
4565
  }
4560
4566
  const error2 = await response.json().catch(() => ({
4561
4567
  statusCode: response.status,
@@ -4660,8 +4666,8 @@ var init_auth = __esm({
4660
4666
  // src/lib/progress.ts
4661
4667
  import ora from "ora";
4662
4668
  import chalk from "chalk";
4663
- function createSpinner(text3) {
4664
- return ora({ text: brandColor(text3), spinner: "dots", color: "magenta" });
4669
+ function createSpinner(text4) {
4670
+ return ora({ text: brandColor(text4), spinner: "dots", color: "magenta" });
4665
4671
  }
4666
4672
  function formatBytes(bytes) {
4667
4673
  if (bytes === 0) return "0 B";
@@ -4927,6 +4933,7 @@ function deviceCommand() {
4927
4933
  printLabel("ID", response.id);
4928
4934
  } catch (err) {
4929
4935
  spinner.stop();
4936
+ if (err instanceof AuthExpiredError) throw err;
4930
4937
  printError(`Failed: ${err instanceof Error ? err.message : "Unknown error"}`);
4931
4938
  process.exit(1);
4932
4939
  }
@@ -4955,6 +4962,7 @@ function deviceCommand() {
4955
4962
  console.log();
4956
4963
  } catch (err) {
4957
4964
  spinner.stop();
4965
+ if (err instanceof AuthExpiredError) throw err;
4958
4966
  printError(`Failed: ${err instanceof Error ? err.message : "Unknown error"}`);
4959
4967
  process.exit(1);
4960
4968
  }
@@ -4973,6 +4981,7 @@ function deviceCommand() {
4973
4981
  printSuccess("Device removed.");
4974
4982
  } catch (err) {
4975
4983
  spinner.stop();
4984
+ if (err instanceof AuthExpiredError) throw err;
4976
4985
  printError(`Failed: ${err instanceof Error ? err.message : "Unknown error"}`);
4977
4986
  process.exit(1);
4978
4987
  }
@@ -4993,6 +5002,7 @@ function deviceCommand() {
4993
5002
  printSuccess(`Device renamed to ${brandBold(`"${response.name}"`)}`);
4994
5003
  } catch (err) {
4995
5004
  spinner.stop();
5005
+ if (err instanceof AuthExpiredError) throw err;
4996
5006
  printError(`Failed: ${err instanceof Error ? err.message : "Unknown error"}`);
4997
5007
  process.exit(1);
4998
5008
  }
@@ -5216,7 +5226,8 @@ async function handleFirstRun(client, config, cwd, ctx, manifest, projectDir, pr
5216
5226
  let devices;
5217
5227
  try {
5218
5228
  devices = await client.get("/api/devices");
5219
- } catch {
5229
+ } catch (err) {
5230
+ if (err instanceof AuthExpiredError) throw err;
5220
5231
  devices = [];
5221
5232
  }
5222
5233
  devicesSpinner.stop();
@@ -5277,8 +5288,9 @@ async function handleFirstRun(client, config, cwd, ctx, manifest, projectDir, pr
5277
5288
  let projects;
5278
5289
  try {
5279
5290
  projects = await client.get(`/api/devices/${deviceChoice}/projects`);
5280
- } catch {
5291
+ } catch (err) {
5281
5292
  spinner.stop();
5293
+ if (err instanceof AuthExpiredError) throw err;
5282
5294
  printError("Failed to load projects from device.");
5283
5295
  return "cancelled";
5284
5296
  }
@@ -5351,6 +5363,7 @@ async function crossMachinePull(client, deviceId, projectPath, fromDeviceId, pro
5351
5363
  });
5352
5364
  } catch (err) {
5353
5365
  spinner.stop();
5366
+ if (err instanceof AuthExpiredError) throw err;
5354
5367
  printError(`Pull failed: ${err instanceof Error ? err.message : "Unknown error"}`);
5355
5368
  return 0;
5356
5369
  }
@@ -5411,6 +5424,7 @@ async function pushPhase(client, deviceId, projectPath, manifest, projectDir, pr
5411
5424
  });
5412
5425
  } catch (err) {
5413
5426
  spinner.stop();
5427
+ if (err instanceof AuthExpiredError) throw err;
5414
5428
  printError(`Push failed: ${err instanceof Error ? err.message : "Unknown error"}`);
5415
5429
  return { uploaded: 0, projectId: projectId || "", failed: true };
5416
5430
  }
@@ -5472,6 +5486,7 @@ async function pullPhase(client, deviceId, projectPath, projectDir, projectId, o
5472
5486
  });
5473
5487
  } catch (err) {
5474
5488
  spinner.stop();
5489
+ if (err instanceof AuthExpiredError) throw err;
5475
5490
  printError(`Pull failed: ${err instanceof Error ? err.message : "Unknown error"}`);
5476
5491
  return { downloaded: 0, failed: true };
5477
5492
  }
@@ -5606,8 +5621,9 @@ function whoamiCommand() {
5606
5621
  printDivider();
5607
5622
  printLabel("Device", config.deviceName || dim("none"));
5608
5623
  printLabel("Device ID", config.deviceId || dim("not registered"));
5609
- } catch {
5624
+ } catch (err) {
5610
5625
  spinner.stop();
5626
+ if (err instanceof AuthExpiredError) throw err;
5611
5627
  printLabel("Email", config.email || dim("unknown"));
5612
5628
  printLabel("Device", config.deviceName || dim("none"));
5613
5629
  }
@@ -5642,7 +5658,8 @@ import { Command as Command7 } from "commander";
5642
5658
  init_esm_shims();
5643
5659
  init_theme();
5644
5660
  init_config();
5645
- import { select as select3, isCancel as isCancel4 } from "@clack/prompts";
5661
+ init_api_client();
5662
+ import { select as select3, text as text3, isCancel as isCancel4 } from "@clack/prompts";
5646
5663
  import chalk3 from "chalk";
5647
5664
  function buildMenu(loggedIn) {
5648
5665
  if (!loggedIn) {
@@ -5663,18 +5680,22 @@ function buildMenu(loggedIn) {
5663
5680
  }
5664
5681
  async function runTui() {
5665
5682
  printBanner();
5666
- const config = await loadConfig();
5667
- const loggedIn = isAuthenticated(config);
5668
- if (loggedIn) {
5669
- console.log(` ${dim("user")} ${brand(config.email || "unknown")}`);
5670
- if (config.deviceName) {
5671
- console.log(` ${dim("device")} ${brand(config.deviceName)}`);
5683
+ let loggedIn = isAuthenticated(await loadConfig());
5684
+ const printStatus = async () => {
5685
+ const config = await loadConfig();
5686
+ loggedIn = isAuthenticated(config);
5687
+ if (loggedIn) {
5688
+ console.log(` ${dim("user")} ${brand(config.email || "unknown")}`);
5689
+ if (config.deviceName) {
5690
+ console.log(` ${dim("device")} ${brand(config.deviceName)}`);
5691
+ }
5692
+ console.log();
5693
+ } else {
5694
+ console.log(` ${dim("Not logged in")}`);
5695
+ console.log();
5672
5696
  }
5673
- console.log();
5674
- } else {
5675
- console.log(` ${dim("Not logged in")}`);
5676
- console.log();
5677
- }
5697
+ };
5698
+ await printStatus();
5678
5699
  while (true) {
5679
5700
  const items = buildMenu(loggedIn);
5680
5701
  const options = [
@@ -5693,10 +5714,49 @@ async function runTui() {
5693
5714
  printOutro("Goodbye!");
5694
5715
  return;
5695
5716
  }
5696
- await executeCommand(choice);
5717
+ try {
5718
+ await executeCommand(choice);
5719
+ } catch (err) {
5720
+ if (err instanceof AuthExpiredError) {
5721
+ printError("Session expired. Please log in again.");
5722
+ console.log();
5723
+ try {
5724
+ const { loginCommand: loginCommand2 } = await Promise.resolve().then(() => (init_login(), login_exports));
5725
+ await loginCommand2().parseAsync(["", ""]);
5726
+ await printStatus();
5727
+ } catch {
5728
+ printError("Login failed.");
5729
+ }
5730
+ }
5731
+ }
5697
5732
  console.log();
5698
5733
  }
5699
5734
  }
5735
+ async function promptDeviceSelection(config) {
5736
+ const client = new ApiClient(config.apiUrl);
5737
+ let devices;
5738
+ try {
5739
+ devices = await client.get("/api/devices");
5740
+ } catch (err) {
5741
+ if (err instanceof AuthExpiredError) throw err;
5742
+ printError("Failed to fetch devices.");
5743
+ return null;
5744
+ }
5745
+ if (devices.length === 0) {
5746
+ printError("No devices registered.");
5747
+ return null;
5748
+ }
5749
+ const choice = await select3({
5750
+ message: brand("Select device"),
5751
+ options: devices.map((d) => ({
5752
+ value: d.id,
5753
+ label: d.name,
5754
+ hint: d.id === config.deviceId ? dim("current") : void 0
5755
+ }))
5756
+ });
5757
+ if (isCancel4(choice)) return null;
5758
+ return choice;
5759
+ }
5700
5760
  async function executeCommand(command) {
5701
5761
  const { loginCommand: loginCommand2 } = await Promise.resolve().then(() => (init_login(), login_exports));
5702
5762
  const { logoutCommand: logoutCommand2 } = await Promise.resolve().then(() => (init_logout(), logout_exports));
@@ -5704,23 +5764,29 @@ async function executeCommand(command) {
5704
5764
  const { syncCommand: syncCommand2 } = await Promise.resolve().then(() => (init_sync(), sync_exports));
5705
5765
  const { statusCommand: statusCommand2 } = await Promise.resolve().then(() => (init_status(), status_exports));
5706
5766
  const { whoamiCommand: whoamiCommand2 } = await Promise.resolve().then(() => (init_whoami(), whoami_exports));
5767
+ const config = await loadConfig();
5707
5768
  const handlers = {
5708
- login: () => loginCommand2().parseAsync(["", "", "login"]),
5709
- logout: () => logoutCommand2().parseAsync(["", "", "logout"]),
5710
- sync: () => syncCommand2().parseAsync(["", "", "sync"]),
5711
- status: () => statusCommand2().parseAsync(["", "", "status"]),
5712
- whoami: () => whoamiCommand2().parseAsync(["", "", "whoami"]),
5713
- "device:add": () => deviceCommand2().parseAsync(["", "", "device", "add"]),
5714
- "device:list": () => deviceCommand2().parseAsync(["", "", "device", "list"]),
5715
- "device:remove": () => deviceCommand2().parseAsync(["", "", "device", "remove"]),
5716
- "device:rename": () => deviceCommand2().parseAsync(["", "", "device", "rename"])
5769
+ login: () => loginCommand2().parseAsync(["", ""]),
5770
+ logout: () => logoutCommand2().parseAsync(["", ""]),
5771
+ sync: () => syncCommand2().parseAsync(["", ""]),
5772
+ status: () => statusCommand2().parseAsync(["", ""]),
5773
+ whoami: () => whoamiCommand2().parseAsync(["", ""]),
5774
+ "device:add": () => deviceCommand2().parseAsync(["", "", "add"]),
5775
+ "device:list": () => deviceCommand2().parseAsync(["", "", "list"]),
5776
+ "device:remove": async () => {
5777
+ const deviceId = await promptDeviceSelection(config);
5778
+ if (!deviceId) return;
5779
+ await deviceCommand2().parseAsync(["", "", "remove", deviceId]);
5780
+ },
5781
+ "device:rename": async () => {
5782
+ const name = await text3({ message: `${brand("New device name")}:` });
5783
+ if (isCancel4(name)) return;
5784
+ await deviceCommand2().parseAsync(["", "", "rename", name]);
5785
+ }
5717
5786
  };
5718
5787
  const handler = handlers[command];
5719
5788
  if (handler) {
5720
- try {
5721
- await handler();
5722
- } catch {
5723
- }
5789
+ await handler();
5724
5790
  }
5725
5791
  }
5726
5792