vaultsy-cli 0.1.2 → 0.1.4
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/index.js +453 -273
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -259,72 +259,246 @@ var init_env = __esm({
|
|
|
259
259
|
// src/index.ts
|
|
260
260
|
import { Command } from "commander";
|
|
261
261
|
|
|
262
|
+
// src/commands/envs.ts
|
|
263
|
+
import * as p from "@clack/prompts";
|
|
264
|
+
import chalk from "chalk";
|
|
265
|
+
|
|
262
266
|
// ../shared/dist/enums.js
|
|
263
267
|
var EnvironmentType = ["development", "staging", "preview", "production"];
|
|
264
268
|
|
|
269
|
+
// src/commands/envs.ts
|
|
270
|
+
init_api();
|
|
271
|
+
init_env();
|
|
272
|
+
async function envsCommand(projectArg, opts) {
|
|
273
|
+
p.intro(chalk.bold.cyan("vaultsy envs"));
|
|
274
|
+
let envsToShow;
|
|
275
|
+
if (opts.env) {
|
|
276
|
+
if (!EnvironmentType.includes(opts.env)) {
|
|
277
|
+
p.log.error(
|
|
278
|
+
`Invalid environment "${opts.env}". Must be one of: ${EnvironmentType.join(", ")}.`
|
|
279
|
+
);
|
|
280
|
+
process.exit(1);
|
|
281
|
+
}
|
|
282
|
+
envsToShow = [opts.env];
|
|
283
|
+
} else {
|
|
284
|
+
envsToShow = [...EnvironmentType];
|
|
285
|
+
}
|
|
286
|
+
let projectId;
|
|
287
|
+
let projectTitle;
|
|
288
|
+
if (projectArg) {
|
|
289
|
+
projectId = projectArg;
|
|
290
|
+
} else {
|
|
291
|
+
const found = findProjectConfig();
|
|
292
|
+
if (found) {
|
|
293
|
+
projectId = found.config.project;
|
|
294
|
+
p.log.info(`Using project ${chalk.cyan(projectId)} from ${chalk.dim("vaultsy.json")}`);
|
|
295
|
+
} else {
|
|
296
|
+
const spinner9 = p.spinner();
|
|
297
|
+
spinner9.start("Fetching projects\u2026");
|
|
298
|
+
let projects;
|
|
299
|
+
try {
|
|
300
|
+
projects = await listProjects();
|
|
301
|
+
spinner9.stop(`Found ${projects.length} project${projects.length !== 1 ? "s" : ""}.`);
|
|
302
|
+
} catch (err) {
|
|
303
|
+
spinner9.stop("Failed to fetch projects.");
|
|
304
|
+
printApiError(err);
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
if (projects.length === 0) {
|
|
308
|
+
p.log.error("No projects found. Create one at your Vaultsy dashboard first.");
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
const selected = await p.select({
|
|
312
|
+
message: "Select a project",
|
|
313
|
+
options: projects.map((proj) => ({
|
|
314
|
+
value: proj.id,
|
|
315
|
+
label: proj.title,
|
|
316
|
+
hint: proj.id
|
|
317
|
+
}))
|
|
318
|
+
});
|
|
319
|
+
if (p.isCancel(selected)) {
|
|
320
|
+
p.cancel("Cancelled.");
|
|
321
|
+
process.exit(0);
|
|
322
|
+
}
|
|
323
|
+
projectId = selected;
|
|
324
|
+
projectTitle = projects.find((proj) => proj.id === selected)?.title;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
const spinner8 = p.spinner();
|
|
328
|
+
spinner8.start(
|
|
329
|
+
`Fetching ${envsToShow.length === 1 ? envsToShow[0] : "all"} environment${envsToShow.length !== 1 ? "s" : ""}\u2026`
|
|
330
|
+
);
|
|
331
|
+
let results;
|
|
332
|
+
try {
|
|
333
|
+
results = await Promise.all(
|
|
334
|
+
envsToShow.map(async (env) => {
|
|
335
|
+
try {
|
|
336
|
+
const res = await pullSecrets(projectId, env);
|
|
337
|
+
if (!projectTitle) projectTitle = res.project.title;
|
|
338
|
+
return { env, secrets: res.secrets, error: null };
|
|
339
|
+
} catch (err) {
|
|
340
|
+
const message = err instanceof ApiError ? `${err.status}: ${err.message}` : "Unknown error";
|
|
341
|
+
return { env, secrets: null, error: message };
|
|
342
|
+
}
|
|
343
|
+
})
|
|
344
|
+
);
|
|
345
|
+
spinner8.stop(`Loaded secrets for ${chalk.bold(projectTitle ?? projectId)}.`);
|
|
346
|
+
} catch (err) {
|
|
347
|
+
spinner8.stop("Failed to fetch secrets.");
|
|
348
|
+
printApiError(err);
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
const totalSecrets = results.reduce((sum, r) => sum + (r.secrets?.length ?? 0), 0);
|
|
352
|
+
if (totalSecrets === 0 && results.every((r) => r.error === null)) {
|
|
353
|
+
p.log.warn("No secrets found across any environment.");
|
|
354
|
+
p.outro(chalk.dim("Nothing to show."));
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const lines = [];
|
|
358
|
+
for (const result of results) {
|
|
359
|
+
const envLabel = envBadge(result.env);
|
|
360
|
+
lines.push("");
|
|
361
|
+
lines.push(envLabel);
|
|
362
|
+
lines.push(chalk.dim("\u2500".repeat(60)));
|
|
363
|
+
if (result.error !== null) {
|
|
364
|
+
lines.push(` ${chalk.red("\u2717")} Failed to load: ${chalk.dim(result.error)}`);
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (result.secrets === null || result.secrets.length === 0) {
|
|
368
|
+
lines.push(` ${chalk.dim("No secrets.")}`);
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
const maxKeyLen = Math.min(
|
|
372
|
+
Math.max(...result.secrets.map((s) => s.key.length), 3),
|
|
373
|
+
40
|
|
374
|
+
);
|
|
375
|
+
const maxValLen = opts.showValues ? Math.min(Math.max(...result.secrets.map((s) => s.value.length), 5), 60) : 16;
|
|
376
|
+
const colHeader = " " + chalk.bold(padEnd("KEY", maxKeyLen)) + chalk.dim(" ") + chalk.bold(padEnd(opts.showValues ? "VALUE" : "VALUE", maxValLen));
|
|
377
|
+
lines.push(colHeader);
|
|
378
|
+
lines.push(" " + chalk.dim("\xB7".repeat(maxKeyLen + maxValLen + 3)));
|
|
379
|
+
for (const secret of result.secrets) {
|
|
380
|
+
const key = chalk.cyan(padEnd(truncate(secret.key, 40), maxKeyLen));
|
|
381
|
+
let value;
|
|
382
|
+
if (opts.showValues) {
|
|
383
|
+
value = chalk.white(truncate(secret.value, 60));
|
|
384
|
+
} else {
|
|
385
|
+
value = chalk.dim("\u25CF".repeat(Math.min(secret.value.length, 12)) || "(empty)");
|
|
386
|
+
}
|
|
387
|
+
lines.push(` ${key} ${value}`);
|
|
388
|
+
}
|
|
389
|
+
lines.push(
|
|
390
|
+
" " + chalk.dim(
|
|
391
|
+
`${result.secrets.length} secret${result.secrets.length !== 1 ? "s" : ""}`
|
|
392
|
+
)
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
p.log.message(lines.join("\n"));
|
|
396
|
+
if (!opts.showValues) {
|
|
397
|
+
p.log.info(
|
|
398
|
+
`Values are hidden. Run with ${chalk.cyan("--show-values")} to reveal them.`
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
p.outro(
|
|
402
|
+
`${chalk.bold(projectTitle ?? projectId)} \u2014 ${totalSecrets} secret${totalSecrets !== 1 ? "s" : ""} across ${results.length} environment${results.length !== 1 ? "s" : ""}.`
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
var ENV_COLORS = {
|
|
406
|
+
development: chalk.green,
|
|
407
|
+
staging: chalk.yellow,
|
|
408
|
+
preview: chalk.blue,
|
|
409
|
+
production: chalk.red
|
|
410
|
+
};
|
|
411
|
+
function envBadge(env) {
|
|
412
|
+
const color = ENV_COLORS[env];
|
|
413
|
+
return ` ${color("\u25CF")} ${chalk.bold(color(env.toUpperCase()))}`;
|
|
414
|
+
}
|
|
415
|
+
function padEnd(str, length) {
|
|
416
|
+
const visible = str.replace(/\u001b\[[0-9;]*m/g, "");
|
|
417
|
+
const pad = Math.max(0, length - visible.length);
|
|
418
|
+
return str + " ".repeat(pad);
|
|
419
|
+
}
|
|
420
|
+
function truncate(str, max) {
|
|
421
|
+
return str.length > max ? str.slice(0, max - 1) + "\u2026" : str;
|
|
422
|
+
}
|
|
423
|
+
function printApiError(err) {
|
|
424
|
+
if (err instanceof ApiError) {
|
|
425
|
+
if (err.status === 401) {
|
|
426
|
+
p.log.error("Unauthorized. Run `vaultsy login` to re-authenticate.");
|
|
427
|
+
} else if (err.status === 404) {
|
|
428
|
+
p.log.error("Project not found. Check the project ID.");
|
|
429
|
+
} else {
|
|
430
|
+
p.log.error(`API error ${err.status}: ${err.message}`);
|
|
431
|
+
}
|
|
432
|
+
} else if (err instanceof Error) {
|
|
433
|
+
p.log.error(err.message);
|
|
434
|
+
} else {
|
|
435
|
+
p.log.error("An unexpected error occurred.");
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
265
439
|
// src/commands/login.ts
|
|
266
440
|
init_config();
|
|
267
441
|
init_api();
|
|
268
|
-
import * as
|
|
269
|
-
import
|
|
270
|
-
var DEFAULT_BASE_URL = "https://vaultsy.app";
|
|
442
|
+
import * as p2 from "@clack/prompts";
|
|
443
|
+
import chalk2 from "chalk";
|
|
444
|
+
var DEFAULT_BASE_URL = "https://vaultsy.vercel.app";
|
|
271
445
|
async function loginCommand(opts) {
|
|
272
|
-
|
|
446
|
+
p2.intro(chalk2.bold.cyan("vaultsy login"));
|
|
273
447
|
const baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
274
448
|
let token;
|
|
275
449
|
if (opts.token) {
|
|
276
450
|
token = opts.token;
|
|
277
451
|
} else {
|
|
278
|
-
|
|
279
|
-
const input = await
|
|
452
|
+
p2.log.info(`Create a token at ${chalk2.cyan(baseUrl + "/dashboard/settings")}`);
|
|
453
|
+
const input = await p2.password({
|
|
280
454
|
message: "Paste your API token",
|
|
281
455
|
validate(value) {
|
|
282
456
|
if (!value.trim()) return "Token is required.";
|
|
283
457
|
}
|
|
284
458
|
});
|
|
285
|
-
if (
|
|
286
|
-
|
|
459
|
+
if (p2.isCancel(input)) {
|
|
460
|
+
p2.cancel("Login cancelled.");
|
|
287
461
|
process.exit(0);
|
|
288
462
|
}
|
|
289
463
|
token = input.trim();
|
|
290
464
|
}
|
|
291
|
-
const
|
|
292
|
-
|
|
465
|
+
const spinner8 = p2.spinner();
|
|
466
|
+
spinner8.start("Verifying token\u2026");
|
|
293
467
|
let userName;
|
|
294
468
|
let userEmail;
|
|
295
469
|
try {
|
|
296
470
|
const me = await getMe({ baseUrl, token });
|
|
297
471
|
userName = me.name;
|
|
298
472
|
userEmail = me.email;
|
|
299
|
-
|
|
473
|
+
spinner8.stop("Token verified.");
|
|
300
474
|
} catch (err) {
|
|
301
|
-
|
|
475
|
+
spinner8.stop("Verification failed.");
|
|
302
476
|
if (err instanceof ApiError) {
|
|
303
477
|
if (err.status === 401) {
|
|
304
|
-
|
|
478
|
+
p2.log.error("Invalid or expired token. Generate a new one and try again.");
|
|
305
479
|
} else {
|
|
306
|
-
|
|
480
|
+
p2.log.error(`Server responded with ${err.status}: ${err.message}`);
|
|
307
481
|
}
|
|
308
482
|
} else {
|
|
309
|
-
|
|
483
|
+
p2.log.error(`Could not reach ${baseUrl}. Check your network connection.`);
|
|
310
484
|
}
|
|
311
485
|
process.exit(1);
|
|
312
486
|
}
|
|
313
487
|
writeConfig({ token, baseUrl });
|
|
314
|
-
|
|
315
|
-
`${
|
|
316
|
-
Config saved to ${
|
|
488
|
+
p2.outro(
|
|
489
|
+
`${chalk2.green("\u2713")} Logged in as ${chalk2.bold(userName)} ${chalk2.dim(`<${userEmail}>`)}
|
|
490
|
+
Config saved to ${chalk2.dim("~/.vaultsy/config.json")}`
|
|
317
491
|
);
|
|
318
492
|
}
|
|
319
493
|
|
|
320
494
|
// src/commands/pull.ts
|
|
321
|
-
import * as
|
|
322
|
-
import
|
|
495
|
+
import * as p3 from "@clack/prompts";
|
|
496
|
+
import chalk3 from "chalk";
|
|
323
497
|
import { resolve as resolve2 } from "path";
|
|
324
498
|
init_api();
|
|
325
499
|
init_env();
|
|
326
500
|
async function pullCommand(projectArg, envArg, opts) {
|
|
327
|
-
|
|
501
|
+
p3.intro(chalk3.bold.cyan("vaultsy pull"));
|
|
328
502
|
let projectId;
|
|
329
503
|
let projectTitle;
|
|
330
504
|
if (projectArg) {
|
|
@@ -333,24 +507,24 @@ async function pullCommand(projectArg, envArg, opts) {
|
|
|
333
507
|
const found = findProjectConfig();
|
|
334
508
|
if (found) {
|
|
335
509
|
projectId = found.config.project;
|
|
336
|
-
|
|
510
|
+
p3.log.info(`Using project ${chalk3.cyan(projectId)} from ${chalk3.dim("vaultsy.json")}`);
|
|
337
511
|
} else {
|
|
338
|
-
const
|
|
339
|
-
|
|
512
|
+
const spinner9 = p3.spinner();
|
|
513
|
+
spinner9.start("Fetching projects\u2026");
|
|
340
514
|
let projects;
|
|
341
515
|
try {
|
|
342
516
|
projects = await listProjects();
|
|
343
|
-
|
|
517
|
+
spinner9.stop(`Found ${projects.length} project${projects.length !== 1 ? "s" : ""}.`);
|
|
344
518
|
} catch (err) {
|
|
345
|
-
|
|
346
|
-
|
|
519
|
+
spinner9.stop("Failed to fetch projects.");
|
|
520
|
+
printApiError2(err);
|
|
347
521
|
process.exit(1);
|
|
348
522
|
}
|
|
349
523
|
if (projects.length === 0) {
|
|
350
|
-
|
|
524
|
+
p3.log.error("No projects found. Create one at your Vaultsy dashboard first.");
|
|
351
525
|
process.exit(1);
|
|
352
526
|
}
|
|
353
|
-
const selected = await
|
|
527
|
+
const selected = await p3.select({
|
|
354
528
|
message: "Select a project",
|
|
355
529
|
options: projects.map((proj) => ({
|
|
356
530
|
value: proj.id,
|
|
@@ -358,8 +532,8 @@ async function pullCommand(projectArg, envArg, opts) {
|
|
|
358
532
|
hint: proj.id
|
|
359
533
|
}))
|
|
360
534
|
});
|
|
361
|
-
if (
|
|
362
|
-
|
|
535
|
+
if (p3.isCancel(selected)) {
|
|
536
|
+
p3.cancel("Pull cancelled.");
|
|
363
537
|
process.exit(0);
|
|
364
538
|
}
|
|
365
539
|
projectId = selected;
|
|
@@ -369,7 +543,7 @@ async function pullCommand(projectArg, envArg, opts) {
|
|
|
369
543
|
let env;
|
|
370
544
|
if (envArg) {
|
|
371
545
|
if (!EnvironmentType.includes(envArg)) {
|
|
372
|
-
|
|
546
|
+
p3.log.error(
|
|
373
547
|
`Invalid environment "${envArg}". Must be one of: ${EnvironmentType.join(", ")}.`
|
|
374
548
|
);
|
|
375
549
|
process.exit(1);
|
|
@@ -378,7 +552,7 @@ async function pullCommand(projectArg, envArg, opts) {
|
|
|
378
552
|
} else {
|
|
379
553
|
const found = findProjectConfig();
|
|
380
554
|
const defaultEnv = found?.config.defaultEnv;
|
|
381
|
-
const selected = await
|
|
555
|
+
const selected = await p3.select({
|
|
382
556
|
message: "Select an environment",
|
|
383
557
|
options: EnvironmentType.map((e) => ({
|
|
384
558
|
value: e,
|
|
@@ -387,8 +561,8 @@ async function pullCommand(projectArg, envArg, opts) {
|
|
|
387
561
|
})),
|
|
388
562
|
initialValue: defaultEnv ?? "development"
|
|
389
563
|
});
|
|
390
|
-
if (
|
|
391
|
-
|
|
564
|
+
if (p3.isCancel(selected)) {
|
|
565
|
+
p3.cancel("Pull cancelled.");
|
|
392
566
|
process.exit(0);
|
|
393
567
|
}
|
|
394
568
|
env = selected;
|
|
@@ -396,68 +570,68 @@ async function pullCommand(projectArg, envArg, opts) {
|
|
|
396
570
|
const filename = opts.output ?? envFileName(env);
|
|
397
571
|
const outputPath = resolve2(process.cwd(), filename);
|
|
398
572
|
if (!opts.yes && !isGitIgnored(filename)) {
|
|
399
|
-
|
|
400
|
-
`${
|
|
573
|
+
p3.log.warn(
|
|
574
|
+
`${chalk3.yellow(filename)} does not appear to be in ${chalk3.dim(".gitignore")}.
|
|
401
575
|
Make sure you don't accidentally commit secrets to version control.`
|
|
402
576
|
);
|
|
403
|
-
const confirmed = await
|
|
577
|
+
const confirmed = await p3.confirm({
|
|
404
578
|
message: "Continue anyway?",
|
|
405
579
|
initialValue: false
|
|
406
580
|
});
|
|
407
|
-
if (
|
|
408
|
-
|
|
581
|
+
if (p3.isCancel(confirmed) || !confirmed) {
|
|
582
|
+
p3.cancel("Pull cancelled.");
|
|
409
583
|
process.exit(0);
|
|
410
584
|
}
|
|
411
585
|
}
|
|
412
|
-
const
|
|
413
|
-
|
|
586
|
+
const spinner8 = p3.spinner();
|
|
587
|
+
spinner8.start(`Pulling ${chalk3.cyan(env)} secrets\u2026`);
|
|
414
588
|
let result;
|
|
415
589
|
try {
|
|
416
590
|
result = await pullSecrets(projectId, env);
|
|
417
|
-
|
|
418
|
-
`Pulled ${result.secrets.length} secret${result.secrets.length !== 1 ? "s" : ""} from ${
|
|
591
|
+
spinner8.stop(
|
|
592
|
+
`Pulled ${result.secrets.length} secret${result.secrets.length !== 1 ? "s" : ""} from ${chalk3.bold(projectTitle ?? result.project.title)} / ${chalk3.cyan(env)}.`
|
|
419
593
|
);
|
|
420
594
|
} catch (err) {
|
|
421
|
-
|
|
422
|
-
|
|
595
|
+
spinner8.stop("Pull failed.");
|
|
596
|
+
printApiError2(err);
|
|
423
597
|
process.exit(1);
|
|
424
598
|
}
|
|
425
599
|
if (result.secrets.length === 0) {
|
|
426
|
-
|
|
427
|
-
|
|
600
|
+
p3.log.warn(`No secrets found for the ${chalk3.cyan(env)} environment.`);
|
|
601
|
+
p3.outro(chalk3.dim("Nothing written."));
|
|
428
602
|
return;
|
|
429
603
|
}
|
|
430
604
|
writeEnvFile(outputPath, result.secrets);
|
|
431
|
-
|
|
432
|
-
`${
|
|
433
|
-
${
|
|
605
|
+
p3.outro(
|
|
606
|
+
`${chalk3.green("\u2713")} Written to ${chalk3.bold(filename)}
|
|
607
|
+
${chalk3.dim(outputPath)}`
|
|
434
608
|
);
|
|
435
609
|
}
|
|
436
|
-
function
|
|
610
|
+
function printApiError2(err) {
|
|
437
611
|
if (err instanceof ApiError) {
|
|
438
612
|
if (err.status === 401) {
|
|
439
|
-
|
|
613
|
+
p3.log.error("Unauthorized. Run `vaultsy login` to re-authenticate.");
|
|
440
614
|
} else if (err.status === 404) {
|
|
441
|
-
|
|
615
|
+
p3.log.error("Project or environment not found. Check the project ID and environment name.");
|
|
442
616
|
} else {
|
|
443
|
-
|
|
617
|
+
p3.log.error(`API error ${err.status}: ${err.message}`);
|
|
444
618
|
}
|
|
445
619
|
} else if (err instanceof Error) {
|
|
446
|
-
|
|
620
|
+
p3.log.error(err.message);
|
|
447
621
|
} else {
|
|
448
|
-
|
|
622
|
+
p3.log.error("An unexpected error occurred.");
|
|
449
623
|
}
|
|
450
624
|
}
|
|
451
625
|
|
|
452
626
|
// src/commands/push.ts
|
|
453
|
-
import * as
|
|
454
|
-
import
|
|
627
|
+
import * as p4 from "@clack/prompts";
|
|
628
|
+
import chalk4 from "chalk";
|
|
455
629
|
import { resolve as resolve3 } from "path";
|
|
456
630
|
import { existsSync as existsSync3 } from "fs";
|
|
457
631
|
init_api();
|
|
458
632
|
init_env();
|
|
459
633
|
async function pushCommand(projectArg, envArg, opts) {
|
|
460
|
-
|
|
634
|
+
p4.intro(chalk4.bold.cyan("vaultsy push"));
|
|
461
635
|
let projectId;
|
|
462
636
|
let projectTitle;
|
|
463
637
|
if (projectArg) {
|
|
@@ -466,24 +640,24 @@ async function pushCommand(projectArg, envArg, opts) {
|
|
|
466
640
|
const found = findProjectConfig();
|
|
467
641
|
if (found) {
|
|
468
642
|
projectId = found.config.project;
|
|
469
|
-
|
|
643
|
+
p4.log.info(`Using project ${chalk4.cyan(projectId)} from ${chalk4.dim("vaultsy.json")}`);
|
|
470
644
|
} else {
|
|
471
|
-
const
|
|
472
|
-
|
|
645
|
+
const spinner8 = p4.spinner();
|
|
646
|
+
spinner8.start("Fetching projects\u2026");
|
|
473
647
|
let projects;
|
|
474
648
|
try {
|
|
475
649
|
projects = await listProjects();
|
|
476
|
-
|
|
650
|
+
spinner8.stop(`Found ${projects.length} project${projects.length !== 1 ? "s" : ""}.`);
|
|
477
651
|
} catch (err) {
|
|
478
|
-
|
|
479
|
-
|
|
652
|
+
spinner8.stop("Failed to fetch projects.");
|
|
653
|
+
printApiError3(err);
|
|
480
654
|
process.exit(1);
|
|
481
655
|
}
|
|
482
656
|
if (projects.length === 0) {
|
|
483
|
-
|
|
657
|
+
p4.log.error("No projects found. Create one at your Vaultsy dashboard first.");
|
|
484
658
|
process.exit(1);
|
|
485
659
|
}
|
|
486
|
-
const selected = await
|
|
660
|
+
const selected = await p4.select({
|
|
487
661
|
message: "Select a project",
|
|
488
662
|
options: projects.map((proj) => ({
|
|
489
663
|
value: proj.id,
|
|
@@ -491,8 +665,8 @@ async function pushCommand(projectArg, envArg, opts) {
|
|
|
491
665
|
hint: proj.id
|
|
492
666
|
}))
|
|
493
667
|
});
|
|
494
|
-
if (
|
|
495
|
-
|
|
668
|
+
if (p4.isCancel(selected)) {
|
|
669
|
+
p4.cancel("Push cancelled.");
|
|
496
670
|
process.exit(0);
|
|
497
671
|
}
|
|
498
672
|
projectId = selected;
|
|
@@ -502,7 +676,7 @@ async function pushCommand(projectArg, envArg, opts) {
|
|
|
502
676
|
let env;
|
|
503
677
|
if (envArg) {
|
|
504
678
|
if (!EnvironmentType.includes(envArg)) {
|
|
505
|
-
|
|
679
|
+
p4.log.error(
|
|
506
680
|
`Invalid environment "${envArg}". Must be one of: ${EnvironmentType.join(", ")}.`
|
|
507
681
|
);
|
|
508
682
|
process.exit(1);
|
|
@@ -511,7 +685,7 @@ async function pushCommand(projectArg, envArg, opts) {
|
|
|
511
685
|
} else {
|
|
512
686
|
const found = findProjectConfig();
|
|
513
687
|
const defaultEnv = found?.config.defaultEnv;
|
|
514
|
-
const selected = await
|
|
688
|
+
const selected = await p4.select({
|
|
515
689
|
message: "Select an environment",
|
|
516
690
|
options: EnvironmentType.map((e) => ({
|
|
517
691
|
value: e,
|
|
@@ -520,8 +694,8 @@ async function pushCommand(projectArg, envArg, opts) {
|
|
|
520
694
|
})),
|
|
521
695
|
initialValue: defaultEnv ?? "development"
|
|
522
696
|
});
|
|
523
|
-
if (
|
|
524
|
-
|
|
697
|
+
if (p4.isCancel(selected)) {
|
|
698
|
+
p4.cancel("Push cancelled.");
|
|
525
699
|
process.exit(0);
|
|
526
700
|
}
|
|
527
701
|
env = selected;
|
|
@@ -529,22 +703,22 @@ async function pushCommand(projectArg, envArg, opts) {
|
|
|
529
703
|
const filename = opts.input ?? envFileName(env);
|
|
530
704
|
const inputPath = resolve3(process.cwd(), filename);
|
|
531
705
|
if (!existsSync3(inputPath)) {
|
|
532
|
-
|
|
533
|
-
`File ${
|
|
534
|
-
Run ${
|
|
706
|
+
p4.log.error(
|
|
707
|
+
`File ${chalk4.bold(filename)} not found.
|
|
708
|
+
Run ${chalk4.cyan(`vaultsy pull ${projectId} ${env}`)} first, or specify a file with ${chalk4.dim("--input <file>")}.`
|
|
535
709
|
);
|
|
536
710
|
process.exit(1);
|
|
537
711
|
}
|
|
538
712
|
const localSecrets = readEnvFile(inputPath).filter((r) => r.key && r.value);
|
|
539
713
|
if (localSecrets.length === 0) {
|
|
540
|
-
|
|
541
|
-
|
|
714
|
+
p4.log.warn(`${chalk4.bold(filename)} is empty or contains no valid KEY=VALUE pairs.`);
|
|
715
|
+
p4.outro(chalk4.dim("Nothing pushed."));
|
|
542
716
|
return;
|
|
543
717
|
}
|
|
544
|
-
|
|
545
|
-
`Read ${
|
|
718
|
+
p4.log.info(
|
|
719
|
+
`Read ${chalk4.bold(String(localSecrets.length))} secret${localSecrets.length !== 1 ? "s" : ""} from ${chalk4.bold(filename)}.`
|
|
546
720
|
);
|
|
547
|
-
const diffSpinner =
|
|
721
|
+
const diffSpinner = p4.spinner();
|
|
548
722
|
diffSpinner.start("Computing diff against remote\u2026");
|
|
549
723
|
let remoteSecrets;
|
|
550
724
|
let resolvedTitle;
|
|
@@ -555,41 +729,41 @@ async function pushCommand(projectArg, envArg, opts) {
|
|
|
555
729
|
diffSpinner.stop("Diff computed.");
|
|
556
730
|
} catch (err) {
|
|
557
731
|
diffSpinner.stop("Failed to fetch remote secrets.");
|
|
558
|
-
|
|
732
|
+
printApiError3(err);
|
|
559
733
|
process.exit(1);
|
|
560
734
|
}
|
|
561
735
|
const diff = computeDiff(remoteSecrets, localSecrets);
|
|
562
736
|
printDiff(diff);
|
|
563
737
|
const hasChanges = diff.added.length > 0 || diff.modified.length > 0 || diff.removed.length > 0;
|
|
564
738
|
if (!hasChanges) {
|
|
565
|
-
|
|
739
|
+
p4.outro(`${chalk4.dim("No changes.")} Remote ${chalk4.cyan(env)} is already up to date.`);
|
|
566
740
|
return;
|
|
567
741
|
}
|
|
568
742
|
if (!opts.yes) {
|
|
569
|
-
const confirmed = await
|
|
570
|
-
message: `Push these changes to ${
|
|
743
|
+
const confirmed = await p4.confirm({
|
|
744
|
+
message: `Push these changes to ${chalk4.bold(resolvedTitle)} / ${chalk4.cyan(env)}?`,
|
|
571
745
|
initialValue: true
|
|
572
746
|
});
|
|
573
|
-
if (
|
|
574
|
-
|
|
747
|
+
if (p4.isCancel(confirmed) || !confirmed) {
|
|
748
|
+
p4.cancel("Push cancelled.");
|
|
575
749
|
process.exit(0);
|
|
576
750
|
}
|
|
577
751
|
}
|
|
578
|
-
const pushSpinner =
|
|
579
|
-
pushSpinner.start(`Pushing to ${
|
|
752
|
+
const pushSpinner = p4.spinner();
|
|
753
|
+
pushSpinner.start(`Pushing to ${chalk4.cyan(env)}\u2026`);
|
|
580
754
|
try {
|
|
581
755
|
const result = await pushSecrets(projectId, env, localSecrets);
|
|
582
756
|
const { added, modified, removed, unchanged } = result.changes;
|
|
583
757
|
pushSpinner.stop(
|
|
584
|
-
`Done. ${
|
|
758
|
+
`Done. ${chalk4.green(`+${added}`)} added, ${chalk4.yellow(`~${modified}`)} modified, ${chalk4.red(`-${removed}`)} removed, ${chalk4.dim(`${unchanged} unchanged`)}.`
|
|
585
759
|
);
|
|
586
760
|
} catch (err) {
|
|
587
761
|
pushSpinner.stop("Push failed.");
|
|
588
|
-
|
|
762
|
+
printApiError3(err);
|
|
589
763
|
process.exit(1);
|
|
590
764
|
}
|
|
591
|
-
|
|
592
|
-
`${
|
|
765
|
+
p4.outro(
|
|
766
|
+
`${chalk4.green("\u2713")} ${chalk4.bold(resolvedTitle)} / ${chalk4.cyan(env)} updated successfully.`
|
|
593
767
|
);
|
|
594
768
|
}
|
|
595
769
|
function computeDiff(remote, local) {
|
|
@@ -622,54 +796,54 @@ function computeDiff(remote, local) {
|
|
|
622
796
|
function printDiff(diff) {
|
|
623
797
|
const total = diff.added.length + diff.modified.length + diff.removed.length + diff.unchanged.length;
|
|
624
798
|
if (total === 0) {
|
|
625
|
-
|
|
799
|
+
p4.log.info(chalk4.dim("No secrets on remote or local."));
|
|
626
800
|
return;
|
|
627
801
|
}
|
|
628
802
|
const lines = [];
|
|
629
803
|
for (const key of diff.added) {
|
|
630
|
-
lines.push(` ${
|
|
804
|
+
lines.push(` ${chalk4.green("+")} ${chalk4.green(key)}`);
|
|
631
805
|
}
|
|
632
806
|
for (const key of diff.modified) {
|
|
633
|
-
lines.push(` ${
|
|
807
|
+
lines.push(` ${chalk4.yellow("~")} ${chalk4.yellow(key)}`);
|
|
634
808
|
}
|
|
635
809
|
for (const key of diff.removed) {
|
|
636
|
-
lines.push(` ${
|
|
810
|
+
lines.push(` ${chalk4.red("-")} ${chalk4.red(key)}`);
|
|
637
811
|
}
|
|
638
812
|
for (const key of diff.unchanged) {
|
|
639
|
-
lines.push(` ${
|
|
813
|
+
lines.push(` ${chalk4.dim("\xB7")} ${chalk4.dim(key)}`);
|
|
640
814
|
}
|
|
641
|
-
|
|
815
|
+
p4.log.message(lines.join("\n"));
|
|
642
816
|
const summary = [
|
|
643
|
-
diff.added.length > 0 ?
|
|
644
|
-
diff.modified.length > 0 ?
|
|
645
|
-
diff.removed.length > 0 ?
|
|
646
|
-
diff.unchanged.length > 0 ?
|
|
647
|
-
].filter(Boolean).join(
|
|
648
|
-
|
|
817
|
+
diff.added.length > 0 ? chalk4.green(`+${diff.added.length} to add`) : null,
|
|
818
|
+
diff.modified.length > 0 ? chalk4.yellow(`~${diff.modified.length} to modify`) : null,
|
|
819
|
+
diff.removed.length > 0 ? chalk4.red(`-${diff.removed.length} to remove`) : null,
|
|
820
|
+
diff.unchanged.length > 0 ? chalk4.dim(`${diff.unchanged.length} unchanged`) : null
|
|
821
|
+
].filter(Boolean).join(chalk4.dim(", "));
|
|
822
|
+
p4.log.info(summary);
|
|
649
823
|
}
|
|
650
|
-
function
|
|
824
|
+
function printApiError3(err) {
|
|
651
825
|
if (err instanceof ApiError) {
|
|
652
826
|
if (err.status === 401) {
|
|
653
|
-
|
|
827
|
+
p4.log.error("Unauthorized. Run `vaultsy login` to re-authenticate.");
|
|
654
828
|
} else if (err.status === 404) {
|
|
655
|
-
|
|
829
|
+
p4.log.error("Project or environment not found. Check the project ID and environment name.");
|
|
656
830
|
} else {
|
|
657
|
-
|
|
831
|
+
p4.log.error(`API error ${err.status}: ${err.message}`);
|
|
658
832
|
}
|
|
659
833
|
} else if (err instanceof Error) {
|
|
660
|
-
|
|
834
|
+
p4.log.error(err.message);
|
|
661
835
|
} else {
|
|
662
|
-
|
|
836
|
+
p4.log.error("An unexpected error occurred.");
|
|
663
837
|
}
|
|
664
838
|
}
|
|
665
839
|
|
|
666
840
|
// src/commands/history.ts
|
|
667
|
-
import * as
|
|
668
|
-
import
|
|
841
|
+
import * as p5 from "@clack/prompts";
|
|
842
|
+
import chalk5 from "chalk";
|
|
669
843
|
init_api();
|
|
670
844
|
init_env();
|
|
671
845
|
async function historyCommand(projectArg, envArg) {
|
|
672
|
-
|
|
846
|
+
p5.intro(chalk5.bold.cyan("vaultsy history"));
|
|
673
847
|
let projectId;
|
|
674
848
|
let projectTitle;
|
|
675
849
|
if (projectArg) {
|
|
@@ -678,24 +852,24 @@ async function historyCommand(projectArg, envArg) {
|
|
|
678
852
|
const found = findProjectConfig();
|
|
679
853
|
if (found) {
|
|
680
854
|
projectId = found.config.project;
|
|
681
|
-
|
|
855
|
+
p5.log.info(`Using project ${chalk5.cyan(projectId)} from ${chalk5.dim("vaultsy.json")}`);
|
|
682
856
|
} else {
|
|
683
|
-
const
|
|
684
|
-
|
|
857
|
+
const spinner9 = p5.spinner();
|
|
858
|
+
spinner9.start("Fetching projects\u2026");
|
|
685
859
|
let projects;
|
|
686
860
|
try {
|
|
687
861
|
projects = await listProjects();
|
|
688
|
-
|
|
862
|
+
spinner9.stop(`Found ${projects.length} project${projects.length !== 1 ? "s" : ""}.`);
|
|
689
863
|
} catch (err) {
|
|
690
|
-
|
|
691
|
-
|
|
864
|
+
spinner9.stop("Failed to fetch projects.");
|
|
865
|
+
printApiError4(err);
|
|
692
866
|
process.exit(1);
|
|
693
867
|
}
|
|
694
868
|
if (projects.length === 0) {
|
|
695
|
-
|
|
869
|
+
p5.log.error("No projects found. Create one at your Vaultsy dashboard first.");
|
|
696
870
|
process.exit(1);
|
|
697
871
|
}
|
|
698
|
-
const selected = await
|
|
872
|
+
const selected = await p5.select({
|
|
699
873
|
message: "Select a project",
|
|
700
874
|
options: projects.map((proj) => ({
|
|
701
875
|
value: proj.id,
|
|
@@ -703,8 +877,8 @@ async function historyCommand(projectArg, envArg) {
|
|
|
703
877
|
hint: proj.id
|
|
704
878
|
}))
|
|
705
879
|
});
|
|
706
|
-
if (
|
|
707
|
-
|
|
880
|
+
if (p5.isCancel(selected)) {
|
|
881
|
+
p5.cancel("Cancelled.");
|
|
708
882
|
process.exit(0);
|
|
709
883
|
}
|
|
710
884
|
projectId = selected;
|
|
@@ -714,7 +888,7 @@ async function historyCommand(projectArg, envArg) {
|
|
|
714
888
|
let env;
|
|
715
889
|
if (envArg) {
|
|
716
890
|
if (!EnvironmentType.includes(envArg)) {
|
|
717
|
-
|
|
891
|
+
p5.log.error(
|
|
718
892
|
`Invalid environment "${envArg}". Must be one of: ${EnvironmentType.join(", ")}.`
|
|
719
893
|
);
|
|
720
894
|
process.exit(1);
|
|
@@ -723,7 +897,7 @@ async function historyCommand(projectArg, envArg) {
|
|
|
723
897
|
} else {
|
|
724
898
|
const found = findProjectConfig();
|
|
725
899
|
const defaultEnv = found?.config.defaultEnv;
|
|
726
|
-
const selected = await
|
|
900
|
+
const selected = await p5.select({
|
|
727
901
|
message: "Select an environment",
|
|
728
902
|
options: EnvironmentType.map((e) => ({
|
|
729
903
|
value: e,
|
|
@@ -732,57 +906,57 @@ async function historyCommand(projectArg, envArg) {
|
|
|
732
906
|
})),
|
|
733
907
|
initialValue: defaultEnv ?? "development"
|
|
734
908
|
});
|
|
735
|
-
if (
|
|
736
|
-
|
|
909
|
+
if (p5.isCancel(selected)) {
|
|
910
|
+
p5.cancel("Cancelled.");
|
|
737
911
|
process.exit(0);
|
|
738
912
|
}
|
|
739
913
|
env = selected;
|
|
740
914
|
}
|
|
741
|
-
const
|
|
742
|
-
|
|
915
|
+
const spinner8 = p5.spinner();
|
|
916
|
+
spinner8.start(`Fetching history for ${chalk5.cyan(env)}\u2026`);
|
|
743
917
|
let result;
|
|
744
918
|
try {
|
|
745
919
|
result = await listVersions(projectId, env);
|
|
746
|
-
|
|
747
|
-
`${result.versions.length} snapshot${result.versions.length !== 1 ? "s" : ""} for ${
|
|
920
|
+
spinner8.stop(
|
|
921
|
+
`${result.versions.length} snapshot${result.versions.length !== 1 ? "s" : ""} for ${chalk5.bold(projectTitle ?? result.project.title)} / ${chalk5.cyan(env)}.`
|
|
748
922
|
);
|
|
749
923
|
} catch (err) {
|
|
750
|
-
|
|
751
|
-
|
|
924
|
+
spinner8.stop("Failed to fetch history.");
|
|
925
|
+
printApiError4(err);
|
|
752
926
|
process.exit(1);
|
|
753
927
|
}
|
|
754
928
|
if (result.versions.length === 0) {
|
|
755
|
-
|
|
756
|
-
|
|
929
|
+
p5.log.warn(`No version history found for the ${chalk5.cyan(env)} environment.`);
|
|
930
|
+
p5.outro(chalk5.dim("Nothing to show."));
|
|
757
931
|
return;
|
|
758
932
|
}
|
|
759
933
|
const COL_VER = 7;
|
|
760
934
|
const COL_SECRETS = 7;
|
|
761
935
|
const COL_BY = 20;
|
|
762
936
|
const COL_DATE = 22;
|
|
763
|
-
const header =
|
|
764
|
-
const divider =
|
|
937
|
+
const header = chalk5.bold(padEnd2("#", COL_VER)) + chalk5.dim(" \u2502 ") + chalk5.bold(padEnd2("VERSION ID", 26)) + chalk5.dim(" \u2502 ") + chalk5.bold(padEnd2("KEYS", COL_SECRETS)) + chalk5.dim(" \u2502 ") + chalk5.bold(padEnd2("CREATED BY", COL_BY)) + chalk5.dim(" \u2502 ") + chalk5.bold(padEnd2("DATE", COL_DATE));
|
|
938
|
+
const divider = chalk5.dim(
|
|
765
939
|
"\u2500".repeat(COL_VER) + "\u2500\u253C\u2500" + "\u2500".repeat(26) + "\u2500\u253C\u2500" + "\u2500".repeat(COL_SECRETS) + "\u2500\u253C\u2500" + "\u2500".repeat(COL_BY) + "\u2500\u253C\u2500" + "\u2500".repeat(COL_DATE)
|
|
766
940
|
);
|
|
767
941
|
const rows = result.versions.map((v, i) => {
|
|
768
942
|
const isLatest = i === 0;
|
|
769
|
-
const vNum = isLatest ?
|
|
770
|
-
const vId =
|
|
771
|
-
const secrets =
|
|
772
|
-
const by =
|
|
773
|
-
const date =
|
|
774
|
-
const latestBadge = isLatest ?
|
|
775
|
-
return vNum +
|
|
943
|
+
const vNum = isLatest ? chalk5.green(padEnd2(`v${v.versionNumber}`, COL_VER)) : chalk5.dim(padEnd2(`v${v.versionNumber}`, COL_VER));
|
|
944
|
+
const vId = chalk5.dim(padEnd2(v.id, 26));
|
|
945
|
+
const secrets = padEnd2(String(v.secretCount), COL_SECRETS);
|
|
946
|
+
const by = padEnd2(v.createdBy?.name ?? chalk5.italic("system"), COL_BY);
|
|
947
|
+
const date = padEnd2(formatDate(v.createdAt), COL_DATE);
|
|
948
|
+
const latestBadge = isLatest ? chalk5.green(" \u2190 latest") : "";
|
|
949
|
+
return vNum + chalk5.dim(" \u2502 ") + vId + chalk5.dim(" \u2502 ") + secrets + chalk5.dim(" \u2502 ") + by + chalk5.dim(" \u2502 ") + date + latestBadge;
|
|
776
950
|
});
|
|
777
951
|
const lines = [header, divider, ...rows];
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
`To rollback, run: ${
|
|
952
|
+
p5.log.message(lines.join("\n"));
|
|
953
|
+
p5.log.info(
|
|
954
|
+
`To rollback, run: ${chalk5.cyan(`vaultsy rollback ${projectId} ${env} <VERSION_ID>`)}`
|
|
781
955
|
);
|
|
782
|
-
|
|
956
|
+
p5.outro(chalk5.dim("Done."));
|
|
783
957
|
}
|
|
784
958
|
var ANSI_REGEX = new RegExp("\x1B\\[[0-9;]*m", "g");
|
|
785
|
-
function
|
|
959
|
+
function padEnd2(str, length) {
|
|
786
960
|
const visible = str.replace(ANSI_REGEX, "");
|
|
787
961
|
const pad = Math.max(0, length - visible.length);
|
|
788
962
|
return str + " ".repeat(pad);
|
|
@@ -800,29 +974,29 @@ function formatDate(iso) {
|
|
|
800
974
|
});
|
|
801
975
|
return `${date}, ${time}`;
|
|
802
976
|
}
|
|
803
|
-
function
|
|
977
|
+
function printApiError4(err) {
|
|
804
978
|
if (err instanceof ApiError) {
|
|
805
979
|
if (err.status === 401) {
|
|
806
|
-
|
|
980
|
+
p5.log.error("Unauthorized. Run `vaultsy login` to re-authenticate.");
|
|
807
981
|
} else if (err.status === 404) {
|
|
808
|
-
|
|
982
|
+
p5.log.error("Project or environment not found. Check the project ID and environment name.");
|
|
809
983
|
} else {
|
|
810
|
-
|
|
984
|
+
p5.log.error(`API error ${err.status}: ${err.message}`);
|
|
811
985
|
}
|
|
812
986
|
} else if (err instanceof Error) {
|
|
813
|
-
|
|
987
|
+
p5.log.error(err.message);
|
|
814
988
|
} else {
|
|
815
|
-
|
|
989
|
+
p5.log.error("An unexpected error occurred.");
|
|
816
990
|
}
|
|
817
991
|
}
|
|
818
992
|
|
|
819
993
|
// src/commands/rollback.ts
|
|
820
|
-
import * as
|
|
821
|
-
import
|
|
994
|
+
import * as p6 from "@clack/prompts";
|
|
995
|
+
import chalk6 from "chalk";
|
|
822
996
|
init_api();
|
|
823
997
|
init_env();
|
|
824
998
|
async function rollbackCommand(projectArg, envArg, versionIdArg, opts) {
|
|
825
|
-
|
|
999
|
+
p6.intro(chalk6.bold.cyan("vaultsy rollback"));
|
|
826
1000
|
let projectId;
|
|
827
1001
|
let projectTitle;
|
|
828
1002
|
if (projectArg) {
|
|
@@ -831,24 +1005,24 @@ async function rollbackCommand(projectArg, envArg, versionIdArg, opts) {
|
|
|
831
1005
|
const found = findProjectConfig();
|
|
832
1006
|
if (found) {
|
|
833
1007
|
projectId = found.config.project;
|
|
834
|
-
|
|
1008
|
+
p6.log.info(`Using project ${chalk6.cyan(projectId)} from ${chalk6.dim("vaultsy.json")}`);
|
|
835
1009
|
} else {
|
|
836
|
-
const
|
|
837
|
-
|
|
1010
|
+
const spinner9 = p6.spinner();
|
|
1011
|
+
spinner9.start("Fetching projects\u2026");
|
|
838
1012
|
let projects;
|
|
839
1013
|
try {
|
|
840
1014
|
projects = await listProjects();
|
|
841
|
-
|
|
1015
|
+
spinner9.stop(`Found ${projects.length} project${projects.length !== 1 ? "s" : ""}.`);
|
|
842
1016
|
} catch (err) {
|
|
843
|
-
|
|
844
|
-
|
|
1017
|
+
spinner9.stop("Failed to fetch projects.");
|
|
1018
|
+
printApiError5(err);
|
|
845
1019
|
process.exit(1);
|
|
846
1020
|
}
|
|
847
1021
|
if (projects.length === 0) {
|
|
848
|
-
|
|
1022
|
+
p6.log.error("No projects found. Create one at your Vaultsy dashboard first.");
|
|
849
1023
|
process.exit(1);
|
|
850
1024
|
}
|
|
851
|
-
const selected = await
|
|
1025
|
+
const selected = await p6.select({
|
|
852
1026
|
message: "Select a project",
|
|
853
1027
|
options: projects.map((proj) => ({
|
|
854
1028
|
value: proj.id,
|
|
@@ -856,8 +1030,8 @@ async function rollbackCommand(projectArg, envArg, versionIdArg, opts) {
|
|
|
856
1030
|
hint: proj.id
|
|
857
1031
|
}))
|
|
858
1032
|
});
|
|
859
|
-
if (
|
|
860
|
-
|
|
1033
|
+
if (p6.isCancel(selected)) {
|
|
1034
|
+
p6.cancel("Rollback cancelled.");
|
|
861
1035
|
process.exit(0);
|
|
862
1036
|
}
|
|
863
1037
|
projectId = selected;
|
|
@@ -867,7 +1041,7 @@ async function rollbackCommand(projectArg, envArg, versionIdArg, opts) {
|
|
|
867
1041
|
let env;
|
|
868
1042
|
if (envArg) {
|
|
869
1043
|
if (!EnvironmentType.includes(envArg)) {
|
|
870
|
-
|
|
1044
|
+
p6.log.error(
|
|
871
1045
|
`Invalid environment "${envArg}". Must be one of: ${EnvironmentType.join(", ")}.`
|
|
872
1046
|
);
|
|
873
1047
|
process.exit(1);
|
|
@@ -876,7 +1050,7 @@ async function rollbackCommand(projectArg, envArg, versionIdArg, opts) {
|
|
|
876
1050
|
} else {
|
|
877
1051
|
const found = findProjectConfig();
|
|
878
1052
|
const defaultEnv = found?.config.defaultEnv;
|
|
879
|
-
const selected = await
|
|
1053
|
+
const selected = await p6.select({
|
|
880
1054
|
message: "Select an environment",
|
|
881
1055
|
options: EnvironmentType.map((e) => ({
|
|
882
1056
|
value: e,
|
|
@@ -885,8 +1059,8 @@ async function rollbackCommand(projectArg, envArg, versionIdArg, opts) {
|
|
|
885
1059
|
})),
|
|
886
1060
|
initialValue: defaultEnv ?? "development"
|
|
887
1061
|
});
|
|
888
|
-
if (
|
|
889
|
-
|
|
1062
|
+
if (p6.isCancel(selected)) {
|
|
1063
|
+
p6.cancel("Rollback cancelled.");
|
|
890
1064
|
process.exit(0);
|
|
891
1065
|
}
|
|
892
1066
|
env = selected;
|
|
@@ -896,25 +1070,25 @@ async function rollbackCommand(projectArg, envArg, versionIdArg, opts) {
|
|
|
896
1070
|
if (versionIdArg) {
|
|
897
1071
|
versionId = versionIdArg;
|
|
898
1072
|
} else {
|
|
899
|
-
const
|
|
900
|
-
|
|
1073
|
+
const spinner9 = p6.spinner();
|
|
1074
|
+
spinner9.start(`Fetching version history for ${chalk6.cyan(env)}\u2026`);
|
|
901
1075
|
let versionsResult;
|
|
902
1076
|
try {
|
|
903
1077
|
versionsResult = await listVersions(projectId, env);
|
|
904
|
-
|
|
1078
|
+
spinner9.stop(
|
|
905
1079
|
`Found ${versionsResult.versions.length} snapshot${versionsResult.versions.length !== 1 ? "s" : ""}.`
|
|
906
1080
|
);
|
|
907
1081
|
} catch (err) {
|
|
908
|
-
|
|
909
|
-
|
|
1082
|
+
spinner9.stop("Failed to fetch version history.");
|
|
1083
|
+
printApiError5(err);
|
|
910
1084
|
process.exit(1);
|
|
911
1085
|
}
|
|
912
1086
|
if (versionsResult.versions.length === 0) {
|
|
913
|
-
|
|
1087
|
+
p6.log.error(`No version history found for the ${chalk6.cyan(env)} environment.`);
|
|
914
1088
|
process.exit(1);
|
|
915
1089
|
}
|
|
916
1090
|
const pickable = versionsResult.versions;
|
|
917
|
-
const selected = await
|
|
1091
|
+
const selected = await p6.select({
|
|
918
1092
|
message: "Select a version to roll back to",
|
|
919
1093
|
options: pickable.map((v, i) => ({
|
|
920
1094
|
value: v.id,
|
|
@@ -922,8 +1096,8 @@ async function rollbackCommand(projectArg, envArg, versionIdArg, opts) {
|
|
|
922
1096
|
hint: i === 0 ? "current" : v.createdBy?.name ? `by ${v.createdBy.name}` : void 0
|
|
923
1097
|
}))
|
|
924
1098
|
});
|
|
925
|
-
if (
|
|
926
|
-
|
|
1099
|
+
if (p6.isCancel(selected)) {
|
|
1100
|
+
p6.cancel("Rollback cancelled.");
|
|
927
1101
|
process.exit(0);
|
|
928
1102
|
}
|
|
929
1103
|
versionId = selected;
|
|
@@ -931,34 +1105,34 @@ async function rollbackCommand(projectArg, envArg, versionIdArg, opts) {
|
|
|
931
1105
|
projectTitle ??= versionsResult.project.title;
|
|
932
1106
|
}
|
|
933
1107
|
if (!opts.yes) {
|
|
934
|
-
const label = versionNumber !== void 0 ? `v${versionNumber} (${
|
|
935
|
-
|
|
936
|
-
`This will overwrite all ${
|
|
1108
|
+
const label = versionNumber !== void 0 ? `v${versionNumber} (${chalk6.dim(versionId)})` : chalk6.dim(versionId);
|
|
1109
|
+
p6.log.warn(
|
|
1110
|
+
`This will overwrite all ${chalk6.bold(env)} secrets with the state from snapshot ${label}.
|
|
937
1111
|
A new snapshot will be created automatically so you can undo this rollback too.`
|
|
938
1112
|
);
|
|
939
|
-
const confirmed = await
|
|
940
|
-
message: `Roll back ${
|
|
1113
|
+
const confirmed = await p6.confirm({
|
|
1114
|
+
message: `Roll back ${chalk6.bold(projectTitle ?? projectId)} / ${chalk6.cyan(env)} to ${label}?`,
|
|
941
1115
|
initialValue: false
|
|
942
1116
|
});
|
|
943
|
-
if (
|
|
944
|
-
|
|
1117
|
+
if (p6.isCancel(confirmed) || !confirmed) {
|
|
1118
|
+
p6.cancel("Rollback cancelled.");
|
|
945
1119
|
process.exit(0);
|
|
946
1120
|
}
|
|
947
1121
|
}
|
|
948
|
-
const
|
|
949
|
-
|
|
1122
|
+
const spinner8 = p6.spinner();
|
|
1123
|
+
spinner8.start("Rolling back\u2026");
|
|
950
1124
|
try {
|
|
951
1125
|
const result = await rollback(projectId, env, versionId);
|
|
952
1126
|
const { added, modified, removed, unchanged } = result.changes;
|
|
953
|
-
|
|
954
|
-
`Rolled back to v${result.rolledBackTo.versionNumber}. ${
|
|
1127
|
+
spinner8.stop(
|
|
1128
|
+
`Rolled back to v${result.rolledBackTo.versionNumber}. ${chalk6.green(`+${added}`)} added, ${chalk6.yellow(`~${modified}`)} modified, ${chalk6.red(`-${removed}`)} removed, ${chalk6.dim(`${unchanged} unchanged`)}.`
|
|
955
1129
|
);
|
|
956
|
-
|
|
957
|
-
`${
|
|
1130
|
+
p6.outro(
|
|
1131
|
+
`${chalk6.green("\u2713")} ${chalk6.bold(projectTitle ?? result.project.title)} / ${chalk6.cyan(env)} rolled back to ${chalk6.bold(`v${result.rolledBackTo.versionNumber}`)}.`
|
|
958
1132
|
);
|
|
959
1133
|
} catch (err) {
|
|
960
|
-
|
|
961
|
-
|
|
1134
|
+
spinner8.stop("Rollback failed.");
|
|
1135
|
+
printApiError5(err);
|
|
962
1136
|
process.exit(1);
|
|
963
1137
|
}
|
|
964
1138
|
}
|
|
@@ -973,38 +1147,38 @@ function formatDate2(iso) {
|
|
|
973
1147
|
minute: "2-digit"
|
|
974
1148
|
});
|
|
975
1149
|
}
|
|
976
|
-
function
|
|
1150
|
+
function printApiError5(err) {
|
|
977
1151
|
if (err instanceof ApiError) {
|
|
978
1152
|
if (err.status === 401) {
|
|
979
|
-
|
|
1153
|
+
p6.log.error("Unauthorized. Run `vaultsy login` to re-authenticate.");
|
|
980
1154
|
} else if (err.status === 404) {
|
|
981
|
-
|
|
1155
|
+
p6.log.error("Project or environment not found. Check the project ID and environment name.");
|
|
982
1156
|
} else {
|
|
983
|
-
|
|
1157
|
+
p6.log.error(`API error ${err.status}: ${err.message}`);
|
|
984
1158
|
}
|
|
985
1159
|
} else if (err instanceof Error) {
|
|
986
|
-
|
|
1160
|
+
p6.log.error(err.message);
|
|
987
1161
|
} else {
|
|
988
|
-
|
|
1162
|
+
p6.log.error("An unexpected error occurred.");
|
|
989
1163
|
}
|
|
990
1164
|
}
|
|
991
1165
|
|
|
992
1166
|
// src/commands/run.ts
|
|
993
|
-
import * as
|
|
994
|
-
import
|
|
1167
|
+
import * as p7 from "@clack/prompts";
|
|
1168
|
+
import chalk7 from "chalk";
|
|
995
1169
|
import { spawn } from "child_process";
|
|
996
1170
|
init_api();
|
|
997
1171
|
init_env();
|
|
998
1172
|
async function runCommand(projectArg, envArg, commandArgs, _opts) {
|
|
999
1173
|
if (commandArgs.length === 0) {
|
|
1000
|
-
|
|
1174
|
+
p7.log.error(
|
|
1001
1175
|
`No command specified.
|
|
1002
|
-
Usage: ${
|
|
1003
|
-
Example: ${
|
|
1176
|
+
Usage: ${chalk7.cyan("vaultsy run <project> <env> -- <command> [args...]")}
|
|
1177
|
+
Example: ${chalk7.dim("vaultsy run my-app production -- node server.js")}`
|
|
1004
1178
|
);
|
|
1005
1179
|
process.exit(1);
|
|
1006
1180
|
}
|
|
1007
|
-
|
|
1181
|
+
p7.intro(chalk7.bold.cyan("vaultsy run"));
|
|
1008
1182
|
let projectId;
|
|
1009
1183
|
let projectTitle;
|
|
1010
1184
|
if (projectArg) {
|
|
@@ -1013,24 +1187,24 @@ async function runCommand(projectArg, envArg, commandArgs, _opts) {
|
|
|
1013
1187
|
const found = findProjectConfig();
|
|
1014
1188
|
if (found) {
|
|
1015
1189
|
projectId = found.config.project;
|
|
1016
|
-
|
|
1190
|
+
p7.log.info(`Using project ${chalk7.cyan(projectId)} from ${chalk7.dim("vaultsy.json")}`);
|
|
1017
1191
|
} else {
|
|
1018
|
-
const
|
|
1019
|
-
|
|
1192
|
+
const spinner9 = p7.spinner();
|
|
1193
|
+
spinner9.start("Fetching projects\u2026");
|
|
1020
1194
|
let projects;
|
|
1021
1195
|
try {
|
|
1022
1196
|
projects = await listProjects();
|
|
1023
|
-
|
|
1197
|
+
spinner9.stop(`Found ${projects.length} project${projects.length !== 1 ? "s" : ""}.`);
|
|
1024
1198
|
} catch (err) {
|
|
1025
|
-
|
|
1026
|
-
|
|
1199
|
+
spinner9.stop("Failed to fetch projects.");
|
|
1200
|
+
printApiError6(err);
|
|
1027
1201
|
process.exit(1);
|
|
1028
1202
|
}
|
|
1029
1203
|
if (projects.length === 0) {
|
|
1030
|
-
|
|
1204
|
+
p7.log.error("No projects found. Create one at your Vaultsy dashboard first.");
|
|
1031
1205
|
process.exit(1);
|
|
1032
1206
|
}
|
|
1033
|
-
const selected = await
|
|
1207
|
+
const selected = await p7.select({
|
|
1034
1208
|
message: "Select a project",
|
|
1035
1209
|
options: projects.map((proj) => ({
|
|
1036
1210
|
value: proj.id,
|
|
@@ -1038,8 +1212,8 @@ async function runCommand(projectArg, envArg, commandArgs, _opts) {
|
|
|
1038
1212
|
hint: proj.id
|
|
1039
1213
|
}))
|
|
1040
1214
|
});
|
|
1041
|
-
if (
|
|
1042
|
-
|
|
1215
|
+
if (p7.isCancel(selected)) {
|
|
1216
|
+
p7.cancel("Run cancelled.");
|
|
1043
1217
|
process.exit(0);
|
|
1044
1218
|
}
|
|
1045
1219
|
projectId = selected;
|
|
@@ -1049,7 +1223,7 @@ async function runCommand(projectArg, envArg, commandArgs, _opts) {
|
|
|
1049
1223
|
let env;
|
|
1050
1224
|
if (envArg) {
|
|
1051
1225
|
if (!EnvironmentType.includes(envArg)) {
|
|
1052
|
-
|
|
1226
|
+
p7.log.error(
|
|
1053
1227
|
`Invalid environment "${envArg}". Must be one of: ${EnvironmentType.join(", ")}.`
|
|
1054
1228
|
);
|
|
1055
1229
|
process.exit(1);
|
|
@@ -1058,7 +1232,7 @@ async function runCommand(projectArg, envArg, commandArgs, _opts) {
|
|
|
1058
1232
|
} else {
|
|
1059
1233
|
const found = findProjectConfig();
|
|
1060
1234
|
const defaultEnv = found?.config.defaultEnv;
|
|
1061
|
-
const selected = await
|
|
1235
|
+
const selected = await p7.select({
|
|
1062
1236
|
message: "Select an environment",
|
|
1063
1237
|
options: EnvironmentType.map((e) => ({
|
|
1064
1238
|
value: e,
|
|
@@ -1067,25 +1241,25 @@ async function runCommand(projectArg, envArg, commandArgs, _opts) {
|
|
|
1067
1241
|
})),
|
|
1068
1242
|
initialValue: defaultEnv ?? "development"
|
|
1069
1243
|
});
|
|
1070
|
-
if (
|
|
1071
|
-
|
|
1244
|
+
if (p7.isCancel(selected)) {
|
|
1245
|
+
p7.cancel("Run cancelled.");
|
|
1072
1246
|
process.exit(0);
|
|
1073
1247
|
}
|
|
1074
1248
|
env = selected;
|
|
1075
1249
|
}
|
|
1076
|
-
const
|
|
1077
|
-
|
|
1250
|
+
const spinner8 = p7.spinner();
|
|
1251
|
+
spinner8.start(`Pulling ${chalk7.cyan(env)} secrets\u2026`);
|
|
1078
1252
|
let secrets;
|
|
1079
1253
|
try {
|
|
1080
1254
|
const result = await pullSecrets(projectId, env);
|
|
1081
1255
|
secrets = result.secrets;
|
|
1082
1256
|
projectTitle ??= result.project.title;
|
|
1083
|
-
|
|
1084
|
-
`Injecting ${secrets.length} secret${secrets.length !== 1 ? "s" : ""} from ${
|
|
1257
|
+
spinner8.stop(
|
|
1258
|
+
`Injecting ${secrets.length} secret${secrets.length !== 1 ? "s" : ""} from ${chalk7.bold(projectTitle)} / ${chalk7.cyan(env)}.`
|
|
1085
1259
|
);
|
|
1086
1260
|
} catch (err) {
|
|
1087
|
-
|
|
1088
|
-
|
|
1261
|
+
spinner8.stop("Failed to pull secrets.");
|
|
1262
|
+
printApiError6(err);
|
|
1089
1263
|
process.exit(1);
|
|
1090
1264
|
}
|
|
1091
1265
|
const injectedEnv = {
|
|
@@ -1095,13 +1269,13 @@ async function runCommand(projectArg, envArg, commandArgs, _opts) {
|
|
|
1095
1269
|
// shell env wins
|
|
1096
1270
|
};
|
|
1097
1271
|
if (secrets.length > 0) {
|
|
1098
|
-
const keyList = secrets.map((s) =>
|
|
1099
|
-
|
|
1272
|
+
const keyList = secrets.map((s) => chalk7.dim(s.key)).join(", ");
|
|
1273
|
+
p7.log.info(`Injecting: ${keyList}`);
|
|
1100
1274
|
} else {
|
|
1101
|
-
|
|
1275
|
+
p7.log.warn("No secrets found \u2014 running with current environment only.");
|
|
1102
1276
|
}
|
|
1103
1277
|
const [bin, ...args] = commandArgs;
|
|
1104
|
-
|
|
1278
|
+
p7.log.step(`${chalk7.bold("$")} ${chalk7.white([bin, ...args].join(" "))}`);
|
|
1105
1279
|
process.stdout.write("");
|
|
1106
1280
|
const child = spawn(bin, args, {
|
|
1107
1281
|
env: injectedEnv,
|
|
@@ -1120,12 +1294,12 @@ async function runCommand(projectArg, envArg, commandArgs, _opts) {
|
|
|
1120
1294
|
process.on("SIGHUP", () => forwardSignal("SIGHUP"));
|
|
1121
1295
|
child.on("error", (err) => {
|
|
1122
1296
|
if (err.code === "ENOENT") {
|
|
1123
|
-
|
|
1124
|
-
`Command not found: ${
|
|
1297
|
+
p7.log.error(
|
|
1298
|
+
`Command not found: ${chalk7.bold(bin)}
|
|
1125
1299
|
Make sure it is installed and available in your PATH.`
|
|
1126
1300
|
);
|
|
1127
1301
|
} else {
|
|
1128
|
-
|
|
1302
|
+
p7.log.error(`Failed to start process: ${err.message}`);
|
|
1129
1303
|
}
|
|
1130
1304
|
process.exit(1);
|
|
1131
1305
|
});
|
|
@@ -1136,7 +1310,7 @@ async function runCommand(projectArg, envArg, commandArgs, _opts) {
|
|
|
1136
1310
|
}
|
|
1137
1311
|
const exitCode = code ?? 1;
|
|
1138
1312
|
if (exitCode !== 0) {
|
|
1139
|
-
|
|
1313
|
+
p7.log.warn(`Process exited with code ${chalk7.bold(String(exitCode))}.`);
|
|
1140
1314
|
}
|
|
1141
1315
|
process.exit(exitCode);
|
|
1142
1316
|
});
|
|
@@ -1166,19 +1340,19 @@ function signalToNumber(signal) {
|
|
|
1166
1340
|
};
|
|
1167
1341
|
return map[signal] ?? 0;
|
|
1168
1342
|
}
|
|
1169
|
-
function
|
|
1343
|
+
function printApiError6(err) {
|
|
1170
1344
|
if (err instanceof ApiError) {
|
|
1171
1345
|
if (err.status === 401) {
|
|
1172
|
-
|
|
1346
|
+
p7.log.error("Unauthorized. Run `vaultsy login` to re-authenticate.");
|
|
1173
1347
|
} else if (err.status === 404) {
|
|
1174
|
-
|
|
1348
|
+
p7.log.error("Project or environment not found. Check the project ID and environment name.");
|
|
1175
1349
|
} else {
|
|
1176
|
-
|
|
1350
|
+
p7.log.error(`API error ${err.status}: ${err.message}`);
|
|
1177
1351
|
}
|
|
1178
1352
|
} else if (err instanceof Error) {
|
|
1179
|
-
|
|
1353
|
+
p7.log.error(err.message);
|
|
1180
1354
|
} else {
|
|
1181
|
-
|
|
1355
|
+
p7.log.error("An unexpected error occurred.");
|
|
1182
1356
|
}
|
|
1183
1357
|
}
|
|
1184
1358
|
|
|
@@ -1193,14 +1367,14 @@ program.command("login").description("Authenticate with your Vaultsy instance an
|
|
|
1193
1367
|
});
|
|
1194
1368
|
program.command("logout").description("Remove locally stored credentials (~/.vaultsy/config.json)").action(async () => {
|
|
1195
1369
|
const { clearConfig: clearConfig2, configExists: configExists2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
1196
|
-
const
|
|
1197
|
-
const
|
|
1370
|
+
const p8 = await import("@clack/prompts");
|
|
1371
|
+
const chalk8 = (await import("chalk")).default;
|
|
1198
1372
|
if (!configExists2()) {
|
|
1199
|
-
|
|
1373
|
+
p8.log.warn("No credentials found \u2014 already logged out.");
|
|
1200
1374
|
return;
|
|
1201
1375
|
}
|
|
1202
1376
|
clearConfig2();
|
|
1203
|
-
|
|
1377
|
+
p8.log.success(chalk8.green("\u2713") + " Logged out. Credentials removed.");
|
|
1204
1378
|
});
|
|
1205
1379
|
program.command("pull [project] [env]").description("Pull secrets from Vaultsy and write them to a local .env file").option("-o, --output <file>", "Output file path (default: .env or .env.<env>)").option("-y, --yes", "Skip confirmation prompts").action(
|
|
1206
1380
|
async (project, env, opts) => {
|
|
@@ -1212,6 +1386,12 @@ program.command("push [project] [env]").description("Push secrets from a local .
|
|
|
1212
1386
|
await pushCommand(project, env, opts);
|
|
1213
1387
|
}
|
|
1214
1388
|
);
|
|
1389
|
+
program.command("envs [project]").description("Show secrets for a project across all environments (values hidden by default)").option(
|
|
1390
|
+
"-e, --env <env>",
|
|
1391
|
+
"Show only a specific environment (development, staging, preview, production)"
|
|
1392
|
+
).option("-s, --show-values", "Reveal secret values in the output").action(async (project, opts) => {
|
|
1393
|
+
await envsCommand(project, opts);
|
|
1394
|
+
});
|
|
1215
1395
|
program.command("history [project] [env]").description("List version snapshots for an environment").action(async (project, env) => {
|
|
1216
1396
|
await historyCommand(project, env);
|
|
1217
1397
|
});
|
|
@@ -1233,35 +1413,35 @@ program.command("run [project] [env]").description(
|
|
|
1233
1413
|
program.command("init").description(
|
|
1234
1414
|
"Create a vaultsy.json in the current directory to pin a project and default environment"
|
|
1235
1415
|
).action(async () => {
|
|
1236
|
-
const
|
|
1237
|
-
const
|
|
1416
|
+
const p8 = await import("@clack/prompts");
|
|
1417
|
+
const chalk8 = (await import("chalk")).default;
|
|
1238
1418
|
const { listProjects: listProjects2 } = await Promise.resolve().then(() => (init_api(), api_exports));
|
|
1239
1419
|
const { writeProjectConfig: writeProjectConfig2, findProjectConfig: findProjectConfig2 } = await Promise.resolve().then(() => (init_env(), env_exports));
|
|
1240
|
-
|
|
1420
|
+
p8.intro(chalk8.bold.cyan("vaultsy init"));
|
|
1241
1421
|
const existing = findProjectConfig2();
|
|
1242
1422
|
if (existing) {
|
|
1243
|
-
|
|
1244
|
-
`A ${
|
|
1423
|
+
p8.log.warn(
|
|
1424
|
+
`A ${chalk8.bold("vaultsy.json")} already exists at ${chalk8.dim(existing.dir)}.
|
|
1245
1425
|
Delete it first if you want to re-initialise.`
|
|
1246
1426
|
);
|
|
1247
1427
|
process.exit(0);
|
|
1248
1428
|
}
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1429
|
+
const spinner8 = p8.spinner();
|
|
1430
|
+
spinner8.start("Fetching your projects\u2026");
|
|
1251
1431
|
let projects;
|
|
1252
1432
|
try {
|
|
1253
1433
|
projects = await listProjects2();
|
|
1254
|
-
|
|
1434
|
+
spinner8.stop(`Found ${projects.length} project${projects.length !== 1 ? "s" : ""}.`);
|
|
1255
1435
|
} catch (err) {
|
|
1256
|
-
|
|
1257
|
-
if (err instanceof Error)
|
|
1436
|
+
spinner8.stop("Failed to fetch projects.");
|
|
1437
|
+
if (err instanceof Error) p8.log.error(err.message);
|
|
1258
1438
|
process.exit(1);
|
|
1259
1439
|
}
|
|
1260
1440
|
if (projects.length === 0) {
|
|
1261
|
-
|
|
1441
|
+
p8.log.error("No projects found. Create one at your Vaultsy dashboard first.");
|
|
1262
1442
|
process.exit(1);
|
|
1263
1443
|
}
|
|
1264
|
-
const selectedProject = await
|
|
1444
|
+
const selectedProject = await p8.select({
|
|
1265
1445
|
message: "Which project does this directory belong to?",
|
|
1266
1446
|
options: projects.map((proj) => ({
|
|
1267
1447
|
value: proj.id,
|
|
@@ -1269,37 +1449,37 @@ program.command("init").description(
|
|
|
1269
1449
|
hint: proj.id
|
|
1270
1450
|
}))
|
|
1271
1451
|
});
|
|
1272
|
-
if (
|
|
1273
|
-
|
|
1452
|
+
if (p8.isCancel(selectedProject)) {
|
|
1453
|
+
p8.cancel("Init cancelled.");
|
|
1274
1454
|
process.exit(0);
|
|
1275
1455
|
}
|
|
1276
|
-
const selectedEnv = await
|
|
1456
|
+
const selectedEnv = await p8.select({
|
|
1277
1457
|
message: "Default environment for this directory?",
|
|
1278
1458
|
options: EnvironmentType.map((e) => ({ value: e, label: e })),
|
|
1279
1459
|
initialValue: "development"
|
|
1280
1460
|
});
|
|
1281
|
-
if (
|
|
1282
|
-
|
|
1461
|
+
if (p8.isCancel(selectedEnv)) {
|
|
1462
|
+
p8.cancel("Init cancelled.");
|
|
1283
1463
|
process.exit(0);
|
|
1284
1464
|
}
|
|
1285
1465
|
writeProjectConfig2({ project: selectedProject, defaultEnv: selectedEnv });
|
|
1286
|
-
|
|
1287
|
-
`${
|
|
1288
|
-
Run ${
|
|
1466
|
+
p8.outro(
|
|
1467
|
+
`${chalk8.green("\u2713")} Created ${chalk8.bold("vaultsy.json")}
|
|
1468
|
+
Run ${chalk8.cyan("vaultsy pull")} or ${chalk8.cyan("vaultsy push")} with no arguments from this directory.`
|
|
1289
1469
|
);
|
|
1290
1470
|
});
|
|
1291
1471
|
program.command("whoami").description("Show the currently authenticated user").action(async () => {
|
|
1292
|
-
const
|
|
1293
|
-
const
|
|
1472
|
+
const p8 = await import("@clack/prompts");
|
|
1473
|
+
const chalk8 = (await import("chalk")).default;
|
|
1294
1474
|
const { getMe: getMe2 } = await Promise.resolve().then(() => (init_api(), api_exports));
|
|
1295
1475
|
try {
|
|
1296
1476
|
const me = await getMe2();
|
|
1297
|
-
|
|
1477
|
+
p8.log.success(`Logged in as ${chalk8.bold(me.name)} ${chalk8.dim(`<${me.email}>`)}`);
|
|
1298
1478
|
} catch (err) {
|
|
1299
1479
|
if (err instanceof Error) {
|
|
1300
|
-
|
|
1480
|
+
p8.log.error(err.message);
|
|
1301
1481
|
} else {
|
|
1302
|
-
|
|
1482
|
+
p8.log.error("Not authenticated. Run `vaultsy login` first.");
|
|
1303
1483
|
}
|
|
1304
1484
|
process.exit(1);
|
|
1305
1485
|
}
|