claudemesh-cli 1.0.0-alpha.14 → 1.0.0-alpha.15

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.
@@ -4422,19 +4422,38 @@ function prompt(question) {
4422
4422
  return new Promise((resolve) => {
4423
4423
  rl.question(question, (a) => {
4424
4424
  rl.close();
4425
- resolve(a.trim().toLowerCase());
4425
+ resolve(a.trim());
4426
4426
  });
4427
4427
  });
4428
4428
  }
4429
+ function getUserId(token) {
4430
+ try {
4431
+ const payload = JSON.parse(Buffer.from(token.split(".")[1], "base64url").toString());
4432
+ return payload.sub ?? "";
4433
+ } catch {
4434
+ return "";
4435
+ }
4436
+ }
4437
+ async function isOwner(slug, userId) {
4438
+ try {
4439
+ const res = await request({
4440
+ path: `/cli/meshes?user_id=${userId}`,
4441
+ baseUrl: BROKER_HTTP3
4442
+ });
4443
+ return res.meshes?.find((m) => m.slug === slug)?.is_owner ?? false;
4444
+ } catch {
4445
+ return false;
4446
+ }
4447
+ }
4429
4448
  async function deleteMesh(slug, opts = {}) {
4449
+ const config = readConfig();
4430
4450
  if (!slug) {
4431
- const config = readConfig();
4432
4451
  if (config.meshes.length === 0) {
4433
- console.error(" No meshes to delete.");
4452
+ console.error(" No meshes to remove.");
4434
4453
  return EXIT.NOT_FOUND;
4435
4454
  }
4436
4455
  console.log(`
4437
- Select mesh to delete:
4456
+ Select mesh to remove:
4438
4457
  `);
4439
4458
  config.meshes.forEach((m, i) => {
4440
4459
  console.log(` ${bold(String(i + 1) + ")")} ${m.slug} ${dim("(" + m.name + ")")}`);
@@ -4448,45 +4467,69 @@ async function deleteMesh(slug, opts = {}) {
4448
4467
  }
4449
4468
  slug = config.meshes[idx].slug;
4450
4469
  }
4470
+ const auth = getStoredToken();
4471
+ const userId = auth ? getUserId(auth.session_token) : "";
4472
+ const ownerCheck = userId ? await isOwner(slug, userId) : false;
4451
4473
  if (!opts.yes) {
4452
4474
  console.log(`
4453
- ${red("Warning:")} This will permanently delete ${bold(slug)}.`);
4454
- const answer = await prompt(` Type "${slug}" to confirm: `);
4455
- if (answer !== slug.toLowerCase()) {
4456
- console.log(" Cancelled.");
4457
- return EXIT.USER_CANCELLED;
4458
- }
4459
- }
4460
- const auth = getStoredToken();
4461
- if (auth) {
4462
- try {
4463
- let userId = "";
4464
- try {
4465
- const payload = JSON.parse(Buffer.from(auth.session_token.split(".")[1], "base64url").toString());
4466
- userId = payload.sub ?? "";
4467
- } catch {}
4468
- if (userId) {
4469
- await request({
4470
- path: `/cli/mesh/${slug}`,
4471
- method: "DELETE",
4472
- body: { user_id: userId },
4473
- baseUrl: BROKER_HTTP3
4474
- });
4475
- console.log(` ${green(icons.check)} Deleted "${slug}" from server.`);
4476
- }
4477
- } catch (err) {
4478
- const msg = err instanceof Error ? err.message : String(err);
4479
- if (msg.includes("403")) {
4480
- console.log(` ${dim("Not the owner — removing from local config only.")}`);
4481
- } else if (msg.includes("404")) {
4482
- console.log(` ${dim("Mesh not found on server removing locally.")}`);
4483
- } else {
4484
- console.log(` ${dim("Could not delete from server: " + msg)}`);
4475
+ ${bold(slug)}
4476
+ `);
4477
+ if (ownerCheck) {
4478
+ console.log(` ${bold("1)")} Remove from this device only ${dim("(keep on server)")}`);
4479
+ console.log(` ${bold("2)")} ${red("Delete everywhere")} ${dim("(removes for all members)")}`);
4480
+ console.log(` ${bold("3)")} Cancel`);
4481
+ console.log("");
4482
+ const choice = await prompt(" Choice [1]: ") || "1";
4483
+ if (choice === "3") {
4484
+ console.log(" Cancelled.");
4485
+ return EXIT.USER_CANCELLED;
4486
+ }
4487
+ if (choice === "2") {
4488
+ console.log(`
4489
+ ${red("Warning:")} This will delete ${bold(slug)} for all members.`);
4490
+ const confirm = await prompt(` Type "${slug}" to confirm: `);
4491
+ if (confirm.toLowerCase() !== slug.toLowerCase()) {
4492
+ console.log(" Cancelled.");
4493
+ return EXIT.USER_CANCELLED;
4494
+ }
4495
+ try {
4496
+ await request({
4497
+ path: `/cli/mesh/${slug}`,
4498
+ method: "DELETE",
4499
+ body: { user_id: userId },
4500
+ baseUrl: BROKER_HTTP3
4501
+ });
4502
+ console.log(` ${green(icons.check)} Deleted "${slug}" from server.`);
4503
+ } catch (err) {
4504
+ const msg = err instanceof Error ? err.message : String(err);
4505
+ console.error(` ${icons.cross} Server delete failed: ${msg}`);
4506
+ }
4507
+ leaveMesh(slug);
4508
+ console.log(` ${green(icons.check)} Removed from local config.`);
4509
+ return EXIT.SUCCESS;
4510
+ }
4511
+ } else {
4512
+ console.log(` ${bold("1)")} Remove from this device ${dim("(you can re-add later)")}`);
4513
+ console.log(` ${bold("2)")} Cancel`);
4514
+ if (!ownerCheck && userId) {
4515
+ console.log(dim(`
4516
+ ${yellow(icons.warn)} Only the mesh owner can delete it from the server.`));
4517
+ }
4518
+ console.log("");
4519
+ const choice = await prompt(" Choice [1]: ") || "1";
4520
+ if (choice === "2") {
4521
+ console.log(" Cancelled.");
4522
+ return EXIT.USER_CANCELLED;
4485
4523
  }
4486
4524
  }
4487
4525
  }
4488
- leaveMesh(slug);
4489
- console.log(` ${green(icons.check)} Removed "${slug}" from local config.`);
4526
+ const removed = leaveMesh(slug);
4527
+ if (removed) {
4528
+ console.log(` ${green(icons.check)} Removed "${slug}" from this device.`);
4529
+ console.log(dim(` Re-add anytime with: claudemesh mesh add <invite-url>`));
4530
+ } else {
4531
+ console.error(` Mesh "${slug}" not found in local config.`);
4532
+ }
4490
4533
  return EXIT.SUCCESS;
4491
4534
  }
4492
4535
  var BROKER_HTTP3;
@@ -9876,4 +9919,4 @@ main().catch((err) => {
9876
9919
  process.exit(EXIT.INTERNAL_ERROR);
9877
9920
  });
9878
9921
 
9879
- //# debugId=E76259A581E1545264756E2164756E21
9922
+ //# debugId=CB53B1FA4B95E06264756E2164756E21