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