vslides 1.0.17 → 1.0.18

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.
Files changed (2) hide show
  1. package/dist/cli.js +174 -12
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -974,7 +974,7 @@ var require_command = __commonJS({
974
974
  var { Help: Help2 } = require_help();
975
975
  var { Option: Option2, DualOptions } = require_option();
976
976
  var { suggestSimilar } = require_suggestSimilar();
977
- var Command2 = class _Command extends EventEmitter {
977
+ var Command3 = class _Command extends EventEmitter {
978
978
  /**
979
979
  * Initialize a new `Command`.
980
980
  *
@@ -3031,7 +3031,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3031
3031
  return arg;
3032
3032
  });
3033
3033
  }
3034
- exports2.Command = Command2;
3034
+ exports2.Command = Command3;
3035
3035
  }
3036
3036
  });
3037
3037
 
@@ -3039,15 +3039,15 @@ Expecting one of '${allowedValues.join("', '")}'`);
3039
3039
  var require_commander = __commonJS({
3040
3040
  "node_modules/commander/index.js"(exports2) {
3041
3041
  var { Argument: Argument2 } = require_argument();
3042
- var { Command: Command2 } = require_command();
3042
+ var { Command: Command3 } = require_command();
3043
3043
  var { CommanderError: CommanderError2, InvalidArgumentError: InvalidArgumentError2 } = require_error();
3044
3044
  var { Help: Help2 } = require_help();
3045
3045
  var { Option: Option2 } = require_option();
3046
- exports2.program = new Command2();
3047
- exports2.createCommand = (name) => new Command2(name);
3046
+ exports2.program = new Command3();
3047
+ exports2.createCommand = (name) => new Command3(name);
3048
3048
  exports2.createOption = (flags, description) => new Option2(flags, description);
3049
3049
  exports2.createArgument = (name, description) => new Argument2(name, description);
3050
- exports2.Command = Command2;
3050
+ exports2.Command = Command3;
3051
3051
  exports2.Option = Option2;
3052
3052
  exports2.Argument = Argument2;
3053
3053
  exports2.Help = Help2;
@@ -3126,8 +3126,8 @@ function clearCLIAuth() {
3126
3126
  if ((0, import_node_fs.existsSync)(AUTH_FILE)) {
3127
3127
  try {
3128
3128
  (0, import_node_fs.writeFileSync)(AUTH_FILE, "{}");
3129
- const { unlinkSync: unlinkSync2 } = require("node:fs");
3130
- unlinkSync2(AUTH_FILE);
3129
+ const { unlinkSync: unlinkSync3 } = require("node:fs");
3130
+ unlinkSync3(AUTH_FILE);
3131
3131
  } catch {
3132
3132
  }
3133
3133
  }
@@ -3362,6 +3362,34 @@ async function reconnectSession(slug, cliAuthToken) {
3362
3362
  body: JSON.stringify({})
3363
3363
  });
3364
3364
  }
3365
+ async function getProfile(cliAuthToken) {
3366
+ return request("/api/auth/cli/profile", {
3367
+ headers: {
3368
+ "X-CLI-Auth-Token": cliAuthToken
3369
+ }
3370
+ });
3371
+ }
3372
+ async function setProfileField(cliAuthToken, field, value) {
3373
+ return request("/api/auth/cli/profile", {
3374
+ method: "POST",
3375
+ headers: {
3376
+ "X-CLI-Auth-Token": cliAuthToken,
3377
+ "Content-Type": "application/json"
3378
+ },
3379
+ body: JSON.stringify({ field, value })
3380
+ });
3381
+ }
3382
+ async function uploadProfileImage(cliAuthToken, filename, content) {
3383
+ return request("/api/auth/cli/profile/upload", {
3384
+ method: "POST",
3385
+ headers: {
3386
+ "X-CLI-Auth-Token": cliAuthToken,
3387
+ "X-Filename": filename,
3388
+ "Content-Type": "application/octet-stream"
3389
+ },
3390
+ body: content.toString("base64")
3391
+ });
3392
+ }
3365
3393
 
3366
3394
  // src/lib/config.ts
3367
3395
  var import_node_fs2 = require("node:fs");
@@ -3540,7 +3568,8 @@ var ExitCode = {
3540
3568
  Conflict: 1,
3541
3569
  AuthRequired: 2,
3542
3570
  NetworkError: 3,
3543
- ValidationError: 4
3571
+ ValidationError: 4,
3572
+ UsageError: 5
3544
3573
  };
3545
3574
 
3546
3575
  // src/commands/init.ts
@@ -4410,6 +4439,104 @@ async function logout() {
4410
4439
  }
4411
4440
 
4412
4441
  // src/commands/whoami.ts
4442
+ var import_node_fs6 = require("node:fs");
4443
+ var import_node_path5 = require("node:path");
4444
+
4445
+ // src/lib/profile.ts
4446
+ var import_node_fs5 = require("node:fs");
4447
+ var import_node_path4 = require("node:path");
4448
+ var import_node_os3 = require("node:os");
4449
+ var PROFILE_DIR = (0, import_node_path4.join)((0, import_node_os3.homedir)(), ".vslides");
4450
+ var PROFILE_FILE = (0, import_node_path4.join)(PROFILE_DIR, "profile.json");
4451
+ function ensureProfileDir() {
4452
+ if (!(0, import_node_fs5.existsSync)(PROFILE_DIR)) {
4453
+ (0, import_node_fs5.mkdirSync)(PROFILE_DIR, { mode: 448 });
4454
+ }
4455
+ }
4456
+ function getCachedProfile() {
4457
+ if (!(0, import_node_fs5.existsSync)(PROFILE_FILE)) {
4458
+ return null;
4459
+ }
4460
+ try {
4461
+ const content = (0, import_node_fs5.readFileSync)(PROFILE_FILE, "utf-8");
4462
+ const profile = JSON.parse(content);
4463
+ if (typeof profile !== "object" || profile === null) {
4464
+ return null;
4465
+ }
4466
+ return {
4467
+ name: profile.name ?? "",
4468
+ image: profile.image ?? "",
4469
+ role: profile.role ?? ""
4470
+ };
4471
+ } catch {
4472
+ return null;
4473
+ }
4474
+ }
4475
+ function saveCachedProfile(profile) {
4476
+ ensureProfileDir();
4477
+ (0, import_node_fs5.writeFileSync)(PROFILE_FILE, JSON.stringify(profile, null, 2) + "\n", { mode: 384 });
4478
+ (0, import_node_fs5.chmodSync)(PROFILE_FILE, 384);
4479
+ }
4480
+
4481
+ // src/commands/whoami.ts
4482
+ var VALID_FIELDS = ["name", "image", "role"];
4483
+ function isValidField(field) {
4484
+ return VALID_FIELDS.includes(field);
4485
+ }
4486
+ function isUrl(value) {
4487
+ return value.startsWith("http://") || value.startsWith("https://");
4488
+ }
4489
+ async function handleSet(token, field, value) {
4490
+ if (!isValidField(field)) {
4491
+ error(`Invalid field: ${field}`);
4492
+ info(`Valid fields: ${VALID_FIELDS.join(", ")}`);
4493
+ process.exit(ExitCode.UsageError);
4494
+ }
4495
+ if (field === "image") {
4496
+ if (isUrl(value)) {
4497
+ const result = await setProfileField(token, "image", value);
4498
+ if (!result.ok) {
4499
+ error("Failed to update profile");
4500
+ process.exit(ExitCode.NetworkError);
4501
+ }
4502
+ success(`Image updated to: ${value}`);
4503
+ saveCachedProfile({ name: result.data.name, image: result.data.image, role: result.data.role });
4504
+ } else {
4505
+ if (!(0, import_node_fs6.existsSync)(value)) {
4506
+ error(`File not found: ${value}`);
4507
+ process.exit(ExitCode.UsageError);
4508
+ }
4509
+ const content = (0, import_node_fs6.readFileSync)(value);
4510
+ const filename = (0, import_node_path5.basename)(value);
4511
+ info(`Uploading ${filename}...`);
4512
+ const uploadResult = await uploadProfileImage(token, filename, content);
4513
+ if (!uploadResult.ok) {
4514
+ const errorData = uploadResult.data;
4515
+ error(errorData.error || "Failed to upload image");
4516
+ info("Tip: You can also provide an image URL directly");
4517
+ process.exit(ExitCode.NetworkError);
4518
+ }
4519
+ success(`Image uploaded: ${uploadResult.data.url}`);
4520
+ const profileResult = await getProfile(token);
4521
+ if (profileResult.ok) {
4522
+ saveCachedProfile({
4523
+ name: profileResult.data.name,
4524
+ image: profileResult.data.image,
4525
+ role: profileResult.data.role
4526
+ });
4527
+ }
4528
+ }
4529
+ } else {
4530
+ const result = await setProfileField(token, field, value);
4531
+ if (!result.ok) {
4532
+ const errorData = result.data;
4533
+ error(errorData.error || "Failed to update profile");
4534
+ process.exit(ExitCode.NetworkError);
4535
+ }
4536
+ success(`${field.charAt(0).toUpperCase() + field.slice(1)} updated to: ${value}`);
4537
+ saveCachedProfile({ name: result.data.name, image: result.data.image, role: result.data.role });
4538
+ }
4539
+ }
4413
4540
  async function whoami(options = {}) {
4414
4541
  const cachedAuth = getCachedAuth();
4415
4542
  if (!cachedAuth) {
@@ -4422,6 +4549,12 @@ async function whoami(options = {}) {
4422
4549
  instructions(["Run `vslides login` to re-authenticate"]);
4423
4550
  process.exit(ExitCode.AuthRequired);
4424
4551
  }
4552
+ if (options.set && options.args && options.args.length >= 2) {
4553
+ const [field, ...valueParts] = options.args;
4554
+ const value = valueParts.join(" ");
4555
+ await handleSet(cachedAuth.token, field, value);
4556
+ return;
4557
+ }
4425
4558
  if (options.validate) {
4426
4559
  const result = await validateCLIAuth(cachedAuth.token);
4427
4560
  if (!result.ok || !result.data.valid) {
@@ -4430,10 +4563,31 @@ async function whoami(options = {}) {
4430
4563
  process.exit(ExitCode.AuthRequired);
4431
4564
  }
4432
4565
  }
4566
+ const profileResult = await getProfile(cachedAuth.token);
4567
+ let profile = getCachedProfile();
4568
+ if (profileResult.ok) {
4569
+ profile = {
4570
+ name: profileResult.data.name,
4571
+ image: profileResult.data.image,
4572
+ role: profileResult.data.role
4573
+ };
4574
+ saveCachedProfile(profile);
4575
+ } else if (!profile) {
4576
+ profile = { name: "", image: "", role: "" };
4577
+ }
4433
4578
  const daysLeft = Math.ceil((cachedAuth.expiresAt - Date.now()) / (24 * 60 * 60 * 1e3));
4434
- const expiresDate = new Date(cachedAuth.expiresAt).toLocaleDateString();
4435
- info(`Logged in as ${cachedAuth.email}`);
4579
+ const expiresDate = new Date(cachedAuth.expiresAt).toLocaleDateString("en-US", {
4580
+ month: "short",
4581
+ day: "numeric",
4582
+ year: "numeric"
4583
+ });
4584
+ info(`Name: ${profile.name || "(not set)"}`);
4585
+ info(`Image: ${profile.image || "(not set)"}`);
4586
+ info(`Role: ${profile.role || "(not set)"}`);
4587
+ info(`Email: ${cachedAuth.email}`);
4436
4588
  info(`Expires: ${expiresDate} (${daysLeft} day${daysLeft === 1 ? "" : "s"} remaining)`);
4589
+ newline();
4590
+ info("Tip: Use `vslides whoami --set <field> <value>` to update your profile");
4437
4591
  }
4438
4592
 
4439
4593
  // src/cli.ts
@@ -4456,7 +4610,15 @@ function wrapCommand(fn) {
4456
4610
  program.name("vslides").description("CLI for Vercel Slides API").version("1.0.0");
4457
4611
  program.command("login").description("Authenticate with Vercel (valid for 7 days)").option("--wait", "Wait for authentication to complete (2 min timeout)").action(wrapCommand((options) => login(options)));
4458
4612
  program.command("logout").description("Sign out and revoke credentials").action(wrapCommand(logout));
4459
- program.command("whoami").description("Show current authentication status").option("--validate", "Validate token with server").action(wrapCommand((options) => whoami(options)));
4613
+ program.command("whoami").description("Show current authentication status").option("--validate", "Validate token with server").option("--set <field> <value...>", false).action(
4614
+ wrapCommand((options) => {
4615
+ if (options.set && Array.isArray(options.set)) {
4616
+ const [field, ...valueParts] = options.set;
4617
+ return whoami({ ...options, set: true, args: [field, ...valueParts] });
4618
+ }
4619
+ return whoami(options);
4620
+ })
4621
+ );
4460
4622
  program.command("init").description("Create a new session").action(wrapCommand(init));
4461
4623
  program.command("check").description("Check session status").option("--wait", "Poll until running (60s timeout)").action(wrapCommand((options) => check(options)));
4462
4624
  program.command("join <url>").description("Join a shared session").action(wrapCommand(join3));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vslides",
3
- "version": "1.0.17",
3
+ "version": "1.0.18",
4
4
  "description": "CLI for Vercel Slides API",
5
5
  "license": "MIT",
6
6
  "author": "Vercel",