@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/bin/claude-sync.js
CHANGED
|
@@ -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
|
|
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(
|
|
4664
|
-
return ora({ text: brandColor(
|
|
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
|
-
|
|
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
|
-
|
|
5667
|
-
const
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
if (
|
|
5671
|
-
console.log(` ${dim("
|
|
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
|
-
|
|
5674
|
-
|
|
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
|
-
|
|
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(["", ""
|
|
5709
|
-
logout: () => logoutCommand2().parseAsync(["", ""
|
|
5710
|
-
sync: () => syncCommand2().parseAsync(["", ""
|
|
5711
|
-
status: () => statusCommand2().parseAsync(["", ""
|
|
5712
|
-
whoami: () => whoamiCommand2().parseAsync(["", ""
|
|
5713
|
-
"device:add": () => deviceCommand2().parseAsync(["", "", "
|
|
5714
|
-
"device:list": () => deviceCommand2().parseAsync(["", "", "
|
|
5715
|
-
"device:remove": () =>
|
|
5716
|
-
|
|
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
|
-
|
|
5721
|
-
await handler();
|
|
5722
|
-
} catch {
|
|
5723
|
-
}
|
|
5789
|
+
await handler();
|
|
5724
5790
|
}
|
|
5725
5791
|
}
|
|
5726
5792
|
|