vslides 1.0.9 → 1.0.10
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/cli.js +81 -26
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -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 } = require("node:fs");
|
|
3130
|
-
|
|
3129
|
+
const { unlinkSync: unlinkSync2 } = require("node:fs");
|
|
3130
|
+
unlinkSync2(AUTH_FILE);
|
|
3131
3131
|
} catch {
|
|
3132
3132
|
}
|
|
3133
3133
|
}
|
|
@@ -3354,10 +3354,13 @@ async function reconnectSession(slug, cliAuthToken) {
|
|
|
3354
3354
|
// src/lib/config.ts
|
|
3355
3355
|
var import_node_fs2 = require("node:fs");
|
|
3356
3356
|
var import_node_path2 = require("node:path");
|
|
3357
|
+
var import_node_os2 = require("node:os");
|
|
3357
3358
|
var CONFIG_FILE = ".vslides.json";
|
|
3358
3359
|
var GUIDE_FILE = ".vslides-guide.md";
|
|
3359
3360
|
var SLIDES_FILE = "slides.md";
|
|
3360
3361
|
var UPSTREAM_FILE = "upstream.md";
|
|
3362
|
+
var VSLIDES_DIR = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".vslides");
|
|
3363
|
+
var PENDING_LOGIN_FILE = (0, import_node_path2.join)(VSLIDES_DIR, "pending-login.json");
|
|
3361
3364
|
var GUIDE_CACHE_TTL = 24 * 60 * 60 * 1e3;
|
|
3362
3365
|
function getConfigPath() {
|
|
3363
3366
|
return (0, import_node_path2.join)(process.cwd(), CONFIG_FILE);
|
|
@@ -3452,6 +3455,34 @@ function requireToken() {
|
|
|
3452
3455
|
}
|
|
3453
3456
|
return { config, token: config.token };
|
|
3454
3457
|
}
|
|
3458
|
+
function ensureVslidesDir() {
|
|
3459
|
+
if (!(0, import_node_fs2.existsSync)(VSLIDES_DIR)) {
|
|
3460
|
+
(0, import_node_fs2.mkdirSync)(VSLIDES_DIR, { mode: 448 });
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3463
|
+
function readPendingLogin() {
|
|
3464
|
+
if (!(0, import_node_fs2.existsSync)(PENDING_LOGIN_FILE)) {
|
|
3465
|
+
return null;
|
|
3466
|
+
}
|
|
3467
|
+
try {
|
|
3468
|
+
const content = (0, import_node_fs2.readFileSync)(PENDING_LOGIN_FILE, "utf-8");
|
|
3469
|
+
return JSON.parse(content);
|
|
3470
|
+
} catch {
|
|
3471
|
+
return null;
|
|
3472
|
+
}
|
|
3473
|
+
}
|
|
3474
|
+
function writePendingLogin(pending) {
|
|
3475
|
+
ensureVslidesDir();
|
|
3476
|
+
(0, import_node_fs2.writeFileSync)(PENDING_LOGIN_FILE, JSON.stringify(pending, null, 2) + "\n");
|
|
3477
|
+
}
|
|
3478
|
+
function clearPendingLogin() {
|
|
3479
|
+
if ((0, import_node_fs2.existsSync)(PENDING_LOGIN_FILE)) {
|
|
3480
|
+
try {
|
|
3481
|
+
(0, import_node_fs2.unlinkSync)(PENDING_LOGIN_FILE);
|
|
3482
|
+
} catch {
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3455
3486
|
|
|
3456
3487
|
// src/lib/output.ts
|
|
3457
3488
|
function success(message) {
|
|
@@ -3674,12 +3705,12 @@ async function join3(urlOrCode) {
|
|
|
3674
3705
|
pollSecret,
|
|
3675
3706
|
previewUrl: `${getBaseUrl()}/slides/${slug}`
|
|
3676
3707
|
});
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3708
|
+
success(`Joined session: ${slug}`);
|
|
3709
|
+
url("VERIFY_URL", joinUrl);
|
|
3710
|
+
newline();
|
|
3711
|
+
info("ACTION_REQUIRED: Open the URL above in your browser to sign in");
|
|
3712
|
+
info("After signing in, run: vslides check --wait");
|
|
3713
|
+
info("Then run: vslides get");
|
|
3683
3714
|
}
|
|
3684
3715
|
|
|
3685
3716
|
// src/commands/share.ts
|
|
@@ -3690,14 +3721,14 @@ async function share() {
|
|
|
3690
3721
|
error(`Failed to get share info: ${JSON.stringify(result.data)}`);
|
|
3691
3722
|
process.exit(ExitCode.NetworkError);
|
|
3692
3723
|
}
|
|
3693
|
-
const { joinUrl } = result.data;
|
|
3694
|
-
|
|
3724
|
+
const { joinUrl, code } = result.data;
|
|
3725
|
+
info("Share with your co-editor:");
|
|
3726
|
+
newline();
|
|
3727
|
+
url("LINK", joinUrl);
|
|
3695
3728
|
newline();
|
|
3696
|
-
info("
|
|
3697
|
-
|
|
3698
|
-
info(
|
|
3699
|
-
info("3. Visit the URL and authenticate with @vercel.com account");
|
|
3700
|
-
info("4. Run: vslides get");
|
|
3729
|
+
info("OR if they use Claude Code, tell them to paste this:");
|
|
3730
|
+
newline();
|
|
3731
|
+
info(` /vslides join ${code}`);
|
|
3701
3732
|
}
|
|
3702
3733
|
|
|
3703
3734
|
// src/commands/list.ts
|
|
@@ -4159,11 +4190,15 @@ async function upload(file) {
|
|
|
4159
4190
|
error(`Failed to upload: ${JSON.stringify(result.data)}`);
|
|
4160
4191
|
process.exit(ExitCode.NetworkError);
|
|
4161
4192
|
}
|
|
4162
|
-
|
|
4193
|
+
success(`Uploaded: ${result.data.filename}`);
|
|
4163
4194
|
info(`PATH: ${result.data.path}`);
|
|
4164
4195
|
newline();
|
|
4165
|
-
info("Use in slides
|
|
4196
|
+
info("Use in slides frontmatter:");
|
|
4166
4197
|
info(` image: ${result.data.path}`);
|
|
4198
|
+
info(` grayscale: 0 # for full color (default is grayscale)`);
|
|
4199
|
+
newline();
|
|
4200
|
+
info("For avatar images in 1-title layout:");
|
|
4201
|
+
info(` subtitle1Image: ${result.data.path}`);
|
|
4167
4202
|
}
|
|
4168
4203
|
|
|
4169
4204
|
// src/commands/export.ts
|
|
@@ -4251,7 +4286,7 @@ var POLL_TIMEOUT2 = 12e4;
|
|
|
4251
4286
|
function sleep3(ms) {
|
|
4252
4287
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4253
4288
|
}
|
|
4254
|
-
async function login() {
|
|
4289
|
+
async function login(options = {}) {
|
|
4255
4290
|
const cachedAuth = getCachedAuth();
|
|
4256
4291
|
if (cachedAuth && isAuthValid(cachedAuth)) {
|
|
4257
4292
|
const daysLeft = Math.ceil((cachedAuth.expiresAt - Date.now()) / (24 * 60 * 60 * 1e3));
|
|
@@ -4259,6 +4294,11 @@ async function login() {
|
|
|
4259
4294
|
info("Run `vslides logout` to sign out first.");
|
|
4260
4295
|
return;
|
|
4261
4296
|
}
|
|
4297
|
+
const pendingLogin = readPendingLogin();
|
|
4298
|
+
if (pendingLogin && options.wait) {
|
|
4299
|
+
await pollForAuth(pendingLogin.slug, pendingLogin.pollSecret);
|
|
4300
|
+
return;
|
|
4301
|
+
}
|
|
4262
4302
|
const createResult = await createSession();
|
|
4263
4303
|
if (!createResult.ok) {
|
|
4264
4304
|
error(`Failed to create session: ${JSON.stringify(createResult.data)}`);
|
|
@@ -4266,11 +4306,22 @@ async function login() {
|
|
|
4266
4306
|
}
|
|
4267
4307
|
const { slug, pollSecret, verifyUrl } = createResult.data;
|
|
4268
4308
|
const authUrl = `${verifyUrl}?cliAuth=true`;
|
|
4269
|
-
|
|
4270
|
-
url("
|
|
4309
|
+
writePendingLogin({ slug, pollSecret, authUrl });
|
|
4310
|
+
url("VERIFY_URL", authUrl);
|
|
4271
4311
|
newline();
|
|
4272
|
-
info("
|
|
4312
|
+
info("ACTION_REQUIRED: Open the URL above in your browser to sign in");
|
|
4313
|
+
if (options.wait) {
|
|
4314
|
+
info("Waiting for authentication (2 minute timeout)...");
|
|
4315
|
+
newline();
|
|
4316
|
+
await pollForAuth(slug, pollSecret);
|
|
4317
|
+
} else {
|
|
4318
|
+
newline();
|
|
4319
|
+
info("Run `vslides login --wait` to wait for authentication to complete");
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4322
|
+
async function pollForAuth(slug, pollSecret) {
|
|
4273
4323
|
const startTime = Date.now();
|
|
4324
|
+
let pollCount = 0;
|
|
4274
4325
|
while (true) {
|
|
4275
4326
|
const result = await getSession(slug, pollSecret);
|
|
4276
4327
|
if (!result.ok) {
|
|
@@ -4282,21 +4333,25 @@ async function login() {
|
|
|
4282
4333
|
const validateResult = await validateCLIAuth(cliAuthToken);
|
|
4283
4334
|
if (validateResult.ok && validateResult.data.valid && validateResult.data.email && validateResult.data.expiresAt) {
|
|
4284
4335
|
saveCLIAuth(cliAuthToken, validateResult.data.email, validateResult.data.expiresAt);
|
|
4285
|
-
|
|
4336
|
+
clearPendingLogin();
|
|
4286
4337
|
success(`Logged in as ${validateResult.data.email} (valid for 7 days)`);
|
|
4287
4338
|
process.exit(ExitCode.Success);
|
|
4288
4339
|
}
|
|
4289
4340
|
}
|
|
4290
4341
|
if (Date.now() - startTime > POLL_TIMEOUT2) {
|
|
4291
|
-
newline();
|
|
4292
4342
|
error("Timeout waiting for authentication");
|
|
4293
4343
|
instructions([
|
|
4294
|
-
"Open the
|
|
4344
|
+
"Open the VERIFY_URL in your browser",
|
|
4295
4345
|
"Sign in with your @vercel.com account",
|
|
4296
|
-
"Run `vslides login` again"
|
|
4346
|
+
"Run `vslides login --wait` again"
|
|
4297
4347
|
]);
|
|
4298
4348
|
process.exit(ExitCode.Conflict);
|
|
4299
4349
|
}
|
|
4350
|
+
pollCount++;
|
|
4351
|
+
if (pollCount % 10 === 0) {
|
|
4352
|
+
const secondsLeft = Math.ceil((POLL_TIMEOUT2 - (Date.now() - startTime)) / 1e3);
|
|
4353
|
+
info(`Still waiting... (${secondsLeft}s remaining)`);
|
|
4354
|
+
}
|
|
4300
4355
|
await sleep3(POLL_INTERVAL2);
|
|
4301
4356
|
}
|
|
4302
4357
|
}
|
|
@@ -4361,7 +4416,7 @@ function wrapCommand(fn) {
|
|
|
4361
4416
|
};
|
|
4362
4417
|
}
|
|
4363
4418
|
program.name("vslides").description("CLI for Vercel Slides API").version("1.0.0");
|
|
4364
|
-
program.command("login").description("Authenticate with Vercel (valid for 7 days)").action(wrapCommand(login));
|
|
4419
|
+
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)));
|
|
4365
4420
|
program.command("logout").description("Sign out and revoke credentials").action(wrapCommand(logout));
|
|
4366
4421
|
program.command("whoami").description("Show current authentication status").option("--validate", "Validate token with server").action(wrapCommand((options) => whoami(options)));
|
|
4367
4422
|
program.command("init").description("Create a new session").action(wrapCommand(init));
|