wensity 0.1.4 → 0.1.5
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 +140 -96
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { dirname as dirname5, join as join6 } from "path";
|
|
|
6
6
|
|
|
7
7
|
// src/constants.ts
|
|
8
8
|
var CLI_NAME = "wensity";
|
|
9
|
-
var CLI_VERSION = "0.1.
|
|
9
|
+
var CLI_VERSION = "0.1.5";
|
|
10
10
|
var CONFIG_FILE_NAME = "wensity.json";
|
|
11
11
|
var DEFAULT_API_ORIGIN = "https://ui.wensity.com";
|
|
12
12
|
var DEFAULT_REGISTRY_PATH = "/api/registry";
|
|
@@ -396,63 +396,13 @@ function requiredHome(env) {
|
|
|
396
396
|
throw new CliError("HOME is not set, so the CLI cannot locate ~/.config/wensity.");
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
-
// src/http.ts
|
|
400
|
-
async function requestJson(url, options = {}) {
|
|
401
|
-
const headers = new Headers(options.headers);
|
|
402
|
-
headers.set("accept", "application/json");
|
|
403
|
-
headers.set("user-agent", `${CLI_NAME}/${CLI_VERSION}`);
|
|
404
|
-
if (options.body && !headers.has("content-type")) {
|
|
405
|
-
headers.set("content-type", "application/json");
|
|
406
|
-
}
|
|
407
|
-
if (options.token) {
|
|
408
|
-
headers.set("authorization", `Bearer ${options.token}`);
|
|
409
|
-
}
|
|
410
|
-
let response;
|
|
411
|
-
try {
|
|
412
|
-
response = await fetch(url, { ...options, headers });
|
|
413
|
-
} catch (error) {
|
|
414
|
-
const message = error instanceof Error ? error.message : "Unknown network error";
|
|
415
|
-
throw new CliError(`Could not reach ${url}: ${message}`);
|
|
416
|
-
}
|
|
417
|
-
const text = await response.text();
|
|
418
|
-
const payload = parseJson(text);
|
|
419
|
-
if (!response.ok) {
|
|
420
|
-
const message = formatErrorMessage(payload) ?? response.statusText;
|
|
421
|
-
throw new CliError(`${response.status} ${message}`);
|
|
422
|
-
}
|
|
423
|
-
return payload;
|
|
424
|
-
}
|
|
425
|
-
function parseJson(text) {
|
|
426
|
-
if (!text.trim()) return null;
|
|
427
|
-
try {
|
|
428
|
-
return JSON.parse(text);
|
|
429
|
-
} catch {
|
|
430
|
-
throw new CliError("Registry returned invalid JSON.");
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
function formatErrorMessage(payload) {
|
|
434
|
-
if (!payload || typeof payload !== "object") return void 0;
|
|
435
|
-
const record = payload;
|
|
436
|
-
const code = typeof record.error === "string" ? record.error : void 0;
|
|
437
|
-
const message = typeof record.message === "string" ? record.message : code;
|
|
438
|
-
if (code === "pro_license_required") {
|
|
439
|
-
const base = message ?? "This component requires Wensity Pro.";
|
|
440
|
-
return `${base}
|
|
441
|
-
Upgrade here: https://ui.wensity.com/pricing`;
|
|
442
|
-
}
|
|
443
|
-
return message;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// src/package-manager.ts
|
|
447
|
-
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
448
|
-
import { spawnSync } from "child_process";
|
|
449
|
-
import { join as join4 } from "path";
|
|
450
|
-
|
|
451
399
|
// src/output.ts
|
|
452
400
|
import boxen from "boxen";
|
|
453
401
|
import Table from "cli-table3";
|
|
454
402
|
import ora from "ora";
|
|
455
403
|
import pc from "picocolors";
|
|
404
|
+
var BRAND_RED = "#cd1c18";
|
|
405
|
+
var PRICING_BLUE = "#2563eb";
|
|
456
406
|
var LOGO = [
|
|
457
407
|
"\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557",
|
|
458
408
|
"\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D",
|
|
@@ -475,33 +425,46 @@ function printJson(value) {
|
|
|
475
425
|
function formatList(items) {
|
|
476
426
|
return items.map((item) => ` ${pc.dim("\u2022")} ${item}`).join("\n");
|
|
477
427
|
}
|
|
428
|
+
function brandRed(message) {
|
|
429
|
+
return color(message, BRAND_RED);
|
|
430
|
+
}
|
|
431
|
+
function pricingBlue(message) {
|
|
432
|
+
return color(message, PRICING_BLUE);
|
|
433
|
+
}
|
|
478
434
|
function brandBanner(subtitle) {
|
|
479
|
-
const lines = [
|
|
480
|
-
|
|
435
|
+
const lines = [
|
|
436
|
+
"",
|
|
437
|
+
...LOGO.map((line) => brandRed(centerLine(line))),
|
|
438
|
+
pc.bold(centerLine("Wensity CLI"))
|
|
439
|
+
];
|
|
440
|
+
if (subtitle) lines.push(pc.dim(centerLine(subtitle)));
|
|
481
441
|
return lines.join("\n");
|
|
482
442
|
}
|
|
483
443
|
function printBrand(subtitle) {
|
|
484
444
|
print(brandBanner(subtitle));
|
|
485
445
|
}
|
|
446
|
+
function printTitle(title, subtitle) {
|
|
447
|
+
print(`${brandRed("\u25C6")} ${pc.bold(title)}${subtitle ? ` ${pc.dim(subtitle)}` : ""}`);
|
|
448
|
+
}
|
|
486
449
|
function success(message) {
|
|
487
450
|
return `${pc.green("\u2713")} ${message}`;
|
|
488
451
|
}
|
|
489
452
|
function failure(message) {
|
|
490
|
-
return `${
|
|
453
|
+
return `${brandRed("\u2715")} ${message}`;
|
|
491
454
|
}
|
|
492
455
|
function action(message) {
|
|
493
|
-
return `${
|
|
456
|
+
return `${brandRed("\u25C6")} ${message}`;
|
|
494
457
|
}
|
|
495
458
|
function badge(label, tone = "muted") {
|
|
496
459
|
const text = ` ${label.toUpperCase()} `;
|
|
497
|
-
if (tone === "pro") return
|
|
460
|
+
if (tone === "pro") return bgBrandRed(pc.white(pc.bold(text)));
|
|
498
461
|
if (tone === "free") return pc.bgGreen(pc.black(pc.bold(text)));
|
|
499
462
|
return pc.inverse(text);
|
|
500
463
|
}
|
|
501
464
|
function panel(title, body) {
|
|
502
465
|
const content = Array.isArray(body) ? body.join("\n") : body;
|
|
503
466
|
return boxen(content, {
|
|
504
|
-
title:
|
|
467
|
+
title: brandRed(pc.bold(title)),
|
|
505
468
|
titleAlignment: "left",
|
|
506
469
|
borderColor: "red",
|
|
507
470
|
borderStyle: "round",
|
|
@@ -512,12 +475,12 @@ function panel(title, body) {
|
|
|
512
475
|
function nextSteps(steps) {
|
|
513
476
|
return panel(
|
|
514
477
|
"Next steps",
|
|
515
|
-
steps.map((step) => `${
|
|
478
|
+
steps.map((step) => `${brandRed("\u203A")} ${pc.bold(step)}`)
|
|
516
479
|
);
|
|
517
480
|
}
|
|
518
481
|
function table(head, rows) {
|
|
519
482
|
const output = new Table({
|
|
520
|
-
head: head.map((item) =>
|
|
483
|
+
head: head.map((item) => brandRed(pc.bold(item))),
|
|
521
484
|
chars: {
|
|
522
485
|
top: "\u2500",
|
|
523
486
|
"top-mid": "\u252C",
|
|
@@ -566,10 +529,95 @@ async function withSpinner(text, task, successText = text) {
|
|
|
566
529
|
function formatCliError(message) {
|
|
567
530
|
return `${failure(message)}
|
|
568
531
|
|
|
569
|
-
${pc.dim("Need help?")} ${
|
|
532
|
+
${pc.dim("Need help?")} ${pricingBlue("https://ui.wensity.com/docs")}`;
|
|
533
|
+
}
|
|
534
|
+
function formatProRequiredError(resourceName, resourceType) {
|
|
535
|
+
return [
|
|
536
|
+
`${resourceName} is a Pro ${resourceType}.`,
|
|
537
|
+
brandRed("Create an API token from the Wensity dashboard, then run:"),
|
|
538
|
+
` ${brandRed("npx wensity login --token <token>")}`,
|
|
539
|
+
`Pricing: ${pricingBlue("https://ui.wensity.com/pricing")}`
|
|
540
|
+
].join("\n");
|
|
541
|
+
}
|
|
542
|
+
function color(message, hex) {
|
|
543
|
+
if (!shouldColor()) return message;
|
|
544
|
+
const [red, green, blue] = hexToRgb(hex);
|
|
545
|
+
return `\x1B[38;2;${red};${green};${blue}m${message}\x1B[39m`;
|
|
546
|
+
}
|
|
547
|
+
function bgBrandRed(message) {
|
|
548
|
+
if (!shouldColor()) return message;
|
|
549
|
+
const [red, green, blue] = hexToRgb(BRAND_RED);
|
|
550
|
+
return `\x1B[48;2;${red};${green};${blue}m${message}\x1B[49m`;
|
|
551
|
+
}
|
|
552
|
+
function shouldColor() {
|
|
553
|
+
if (process.env.FORCE_COLOR && process.env.FORCE_COLOR !== "0") return true;
|
|
554
|
+
return process.env.NO_COLOR === void 0 && process.env.FORCE_COLOR !== "0";
|
|
555
|
+
}
|
|
556
|
+
function hexToRgb(hex) {
|
|
557
|
+
const value = hex.replace("#", "");
|
|
558
|
+
return [
|
|
559
|
+
Number.parseInt(value.slice(0, 2), 16),
|
|
560
|
+
Number.parseInt(value.slice(2, 4), 16),
|
|
561
|
+
Number.parseInt(value.slice(4, 6), 16)
|
|
562
|
+
];
|
|
563
|
+
}
|
|
564
|
+
function centerLine(line) {
|
|
565
|
+
const columns = Math.min(process.stdout.columns || 80, 100);
|
|
566
|
+
const padding = Math.max(0, Math.floor((columns - line.length) / 2));
|
|
567
|
+
return `${" ".repeat(padding)}${line}`;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// src/http.ts
|
|
571
|
+
async function requestJson(url, options = {}) {
|
|
572
|
+
const headers = new Headers(options.headers);
|
|
573
|
+
headers.set("accept", "application/json");
|
|
574
|
+
headers.set("user-agent", `${CLI_NAME}/${CLI_VERSION}`);
|
|
575
|
+
if (options.body && !headers.has("content-type")) {
|
|
576
|
+
headers.set("content-type", "application/json");
|
|
577
|
+
}
|
|
578
|
+
if (options.token) {
|
|
579
|
+
headers.set("authorization", `Bearer ${options.token}`);
|
|
580
|
+
}
|
|
581
|
+
let response;
|
|
582
|
+
try {
|
|
583
|
+
response = await fetch(url, { ...options, headers });
|
|
584
|
+
} catch (error) {
|
|
585
|
+
const message = error instanceof Error ? error.message : "Unknown network error";
|
|
586
|
+
throw new CliError(`Could not reach ${url}: ${message}`);
|
|
587
|
+
}
|
|
588
|
+
const text = await response.text();
|
|
589
|
+
const payload = parseJson(text);
|
|
590
|
+
if (!response.ok) {
|
|
591
|
+
const message = formatErrorMessage(payload) ?? response.statusText;
|
|
592
|
+
throw new CliError(`${response.status} ${message}`);
|
|
593
|
+
}
|
|
594
|
+
return payload;
|
|
595
|
+
}
|
|
596
|
+
function parseJson(text) {
|
|
597
|
+
if (!text.trim()) return null;
|
|
598
|
+
try {
|
|
599
|
+
return JSON.parse(text);
|
|
600
|
+
} catch {
|
|
601
|
+
throw new CliError("Registry returned invalid JSON.");
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
function formatErrorMessage(payload) {
|
|
605
|
+
if (!payload || typeof payload !== "object") return void 0;
|
|
606
|
+
const record = payload;
|
|
607
|
+
const code = typeof record.error === "string" ? record.error : void 0;
|
|
608
|
+
const message = typeof record.message === "string" ? record.message : code;
|
|
609
|
+
if (code === "pro_license_required") {
|
|
610
|
+
const base = message ?? "This component requires Wensity Pro.";
|
|
611
|
+
return `${base}
|
|
612
|
+
Upgrade here: ${pricingBlue("https://ui.wensity.com/pricing")}`;
|
|
613
|
+
}
|
|
614
|
+
return message;
|
|
570
615
|
}
|
|
571
616
|
|
|
572
617
|
// src/package-manager.ts
|
|
618
|
+
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
619
|
+
import { spawnSync } from "child_process";
|
|
620
|
+
import { join as join4 } from "path";
|
|
573
621
|
function detectPackageManager(projectRoot) {
|
|
574
622
|
if (existsSync2(join4(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
575
623
|
if (existsSync2(join4(projectRoot, "bun.lockb")) || existsSync2(join4(projectRoot, "bun.lock"))) return "bun";
|
|
@@ -966,7 +1014,7 @@ async function initCommand(context, parsed) {
|
|
|
966
1014
|
const utilityRelativePath = toPosixPath(config.utils.endsWith(".ts") ? config.utils : `${config.utils}.ts`);
|
|
967
1015
|
const dependencies = ["clsx", "tailwind-merge"];
|
|
968
1016
|
if (dryRun) {
|
|
969
|
-
|
|
1017
|
+
printTitle("Project initialization preview");
|
|
970
1018
|
print(action("Would write:"));
|
|
971
1019
|
print(formatList([CONFIG_FILE_NAME, utilityRelativePath]));
|
|
972
1020
|
if (install) print(action(`Would install: ${dependencies.join(" ")}`));
|
|
@@ -979,16 +1027,16 @@ async function initCommand(context, parsed) {
|
|
|
979
1027
|
if (install) {
|
|
980
1028
|
runInstall(context.cwd, missingDependencies(context.cwd, dependencies));
|
|
981
1029
|
}
|
|
982
|
-
|
|
1030
|
+
printTitle("Project initialized");
|
|
983
1031
|
print(panel("Created", [
|
|
984
1032
|
success(CONFIG_FILE_NAME),
|
|
985
1033
|
success(utilityRelativePath),
|
|
986
1034
|
success(`registry: ${apiUrl}`)
|
|
987
1035
|
]));
|
|
988
1036
|
print(nextSteps([
|
|
989
|
-
"npx wensity list",
|
|
990
|
-
"npx wensity
|
|
991
|
-
"npx wensity
|
|
1037
|
+
"Browse available components: npx wensity list",
|
|
1038
|
+
"Browse premium blocks: npx wensity list --type block",
|
|
1039
|
+
"Install your chosen slug: npx wensity add <component-slug>"
|
|
992
1040
|
]));
|
|
993
1041
|
}
|
|
994
1042
|
async function loginCommand(context, parsed) {
|
|
@@ -1011,17 +1059,19 @@ async function loginCommand(context, parsed) {
|
|
|
1011
1059
|
printBrand("API token verified");
|
|
1012
1060
|
print(formatAccountPanel(whoami, path));
|
|
1013
1061
|
print(nextSteps(whoami.plan?.tier === "pro" ? [
|
|
1014
|
-
"npx wensity
|
|
1015
|
-
"npx wensity
|
|
1016
|
-
"npx wensity
|
|
1062
|
+
"Browse Pro components: npx wensity list",
|
|
1063
|
+
"Browse Pro blocks: npx wensity list --type block",
|
|
1064
|
+
"Install a component: npx wensity add <component-slug>",
|
|
1065
|
+
"Install a block: npx wensity add <block-slug> --type block"
|
|
1017
1066
|
] : [
|
|
1018
|
-
"npx wensity
|
|
1019
|
-
"
|
|
1067
|
+
"Browse free components: npx wensity list",
|
|
1068
|
+
"Install any Free slug from the table: npx wensity add <slug>",
|
|
1069
|
+
`Upgrade to unlock Pro components and blocks: ${pricingBlue("https://ui.wensity.com/pricing")}`
|
|
1020
1070
|
]));
|
|
1021
1071
|
}
|
|
1022
1072
|
async function logoutCommand(context) {
|
|
1023
1073
|
const removed = await deleteCredentials(context.env);
|
|
1024
|
-
|
|
1074
|
+
printTitle("Session");
|
|
1025
1075
|
print(removed ? success("Logged out of Wensity.") : action("No Wensity credentials were stored."));
|
|
1026
1076
|
}
|
|
1027
1077
|
async function whoamiCommand(context, parsed) {
|
|
@@ -1056,8 +1106,9 @@ async function listCommand(context, parsed) {
|
|
|
1056
1106
|
printBrand("Premium blocks");
|
|
1057
1107
|
print(formatBlockGroup(response2.blocks));
|
|
1058
1108
|
print(nextSteps([
|
|
1059
|
-
"
|
|
1060
|
-
|
|
1109
|
+
brandRed("Create an API token in the dashboard if you have Pro"),
|
|
1110
|
+
brandRed("Save the token: npx wensity login --token <token>"),
|
|
1111
|
+
"Install your chosen block: npx wensity add <block-slug> --type block"
|
|
1061
1112
|
]));
|
|
1062
1113
|
return;
|
|
1063
1114
|
}
|
|
@@ -1075,9 +1126,9 @@ async function listCommand(context, parsed) {
|
|
|
1075
1126
|
print(formatComponentGroup("Free", response.components.filter((component) => component.access !== "pro")));
|
|
1076
1127
|
print(formatComponentGroup("Pro", response.components.filter((component) => component.access === "pro")));
|
|
1077
1128
|
print(nextSteps([
|
|
1078
|
-
"npx wensity add
|
|
1079
|
-
"npx wensity login --token <
|
|
1080
|
-
"npx wensity list --type block"
|
|
1129
|
+
"Choose any Free slug above: npx wensity add <component-slug>",
|
|
1130
|
+
brandRed("For Pro slugs, save an API token: npx wensity login --token <token>"),
|
|
1131
|
+
"Browse layout blocks: npx wensity list --type block"
|
|
1081
1132
|
]));
|
|
1082
1133
|
}
|
|
1083
1134
|
function formatComponentGroup(label, components) {
|
|
@@ -1125,7 +1176,7 @@ Usage: wensity ${updateMode ? "update" : "add"} <slug>${resourceType === "block"
|
|
|
1125
1176
|
const plannedFiles = summarizeFiles(loaded.projectRoot, prepared.files);
|
|
1126
1177
|
const missing = missingDependencies(loaded.projectRoot, prepared.dependencies);
|
|
1127
1178
|
if (dryRun) {
|
|
1128
|
-
|
|
1179
|
+
printTitle(updateMode ? "Update preview" : "Install preview");
|
|
1129
1180
|
print(action("Would write:"));
|
|
1130
1181
|
print(formatList(plannedFiles));
|
|
1131
1182
|
if (install && missing.length > 0) print(action(`Would install: ${missing.join(" ")}`));
|
|
@@ -1135,18 +1186,21 @@ Usage: wensity ${updateMode ? "update" : "add"} <slug>${resourceType === "block"
|
|
|
1135
1186
|
if (install) {
|
|
1136
1187
|
runInstall(loaded.projectRoot, missing);
|
|
1137
1188
|
}
|
|
1138
|
-
|
|
1189
|
+
printTitle(updateMode ? "Component updated" : "Component installed");
|
|
1139
1190
|
print(panel(payload.name, [
|
|
1140
1191
|
success(`${updateMode ? "Updated" : "Added"} ${payload.slug}`),
|
|
1141
1192
|
...plannedFiles.map((file) => success(file))
|
|
1142
1193
|
]));
|
|
1143
1194
|
if (!install && missing.length > 0) {
|
|
1144
1195
|
warn(`Dependencies were not installed: ${missing.join(" ")}`);
|
|
1145
|
-
print(nextSteps([
|
|
1196
|
+
print(nextSteps([
|
|
1197
|
+
`Install skipped dependencies: npm install ${missing.join(" ")}`,
|
|
1198
|
+
"Run without --no-install next time to let Wensity install them automatically"
|
|
1199
|
+
]));
|
|
1146
1200
|
return;
|
|
1147
1201
|
}
|
|
1148
1202
|
print(nextSteps([
|
|
1149
|
-
"Import the
|
|
1203
|
+
"Import the installed file from your Wensity components folder",
|
|
1150
1204
|
resourceType === "block" ? "Customize the block copy, colors, and sections" : "Customize props and styling for your app"
|
|
1151
1205
|
]));
|
|
1152
1206
|
}
|
|
@@ -1172,12 +1226,7 @@ async function fetchComponentPayload(input) {
|
|
|
1172
1226
|
}
|
|
1173
1227
|
}
|
|
1174
1228
|
if (metadata.access === "pro") {
|
|
1175
|
-
throw new CliError(
|
|
1176
|
-
`${metadata.name} is a Pro component.`,
|
|
1177
|
-
`Create an API token from the Wensity dashboard, then run:`,
|
|
1178
|
-
` npx wensity login --token <token>`,
|
|
1179
|
-
`Upgrade: https://ui.wensity.com/pricing`
|
|
1180
|
-
].join("\n"));
|
|
1229
|
+
throw new CliError(formatProRequiredError(metadata.name, "component"));
|
|
1181
1230
|
}
|
|
1182
1231
|
const publicSourceEndpoint = metadata.endpoints?.registry ?? registrySlugUrl(input.registry, input.slug);
|
|
1183
1232
|
const endpoint = publicSourceEndpoint.startsWith("http") ? publicSourceEndpoint : joinUrl(registryOrigin(input.registry), publicSourceEndpoint);
|
|
@@ -1197,12 +1246,7 @@ async function fetchBlockPayload(input) {
|
|
|
1197
1246
|
`Found ${input.slug}`
|
|
1198
1247
|
);
|
|
1199
1248
|
if (!input.credentials) {
|
|
1200
|
-
throw new CliError(
|
|
1201
|
-
`${metadata.name} is a Pro block.`,
|
|
1202
|
-
`Create an API token from the Wensity dashboard, then run:`,
|
|
1203
|
-
` npx wensity login --token <token>`,
|
|
1204
|
-
`Upgrade: https://ui.wensity.com/pricing`
|
|
1205
|
-
].join("\n"));
|
|
1249
|
+
throw new CliError(formatProRequiredError(metadata.name, "block"));
|
|
1206
1250
|
}
|
|
1207
1251
|
const credentials = input.credentials;
|
|
1208
1252
|
const cliEndpoint = metadata.endpoints?.cli ?? `/api/cli/blocks/${input.slug}`;
|
|
@@ -1226,7 +1270,7 @@ function registryUrlForType(componentRegistry, resourceType, registryOverride) {
|
|
|
1226
1270
|
async function requireCredentials(env) {
|
|
1227
1271
|
const credentials = await readCredentials(env);
|
|
1228
1272
|
if (!credentials) {
|
|
1229
|
-
throw new CliError(
|
|
1273
|
+
throw new CliError(`Not logged in. ${brandRed("Run wensity login with an API token from the Wensity dashboard.")}`);
|
|
1230
1274
|
}
|
|
1231
1275
|
return credentials;
|
|
1232
1276
|
}
|
|
@@ -1251,7 +1295,7 @@ function formatHelp() {
|
|
|
1251
1295
|
nextSteps([
|
|
1252
1296
|
"npx wensity init",
|
|
1253
1297
|
"npx wensity list",
|
|
1254
|
-
"npx wensity add
|
|
1298
|
+
"npx wensity add <component-slug>"
|
|
1255
1299
|
])
|
|
1256
1300
|
].join("\n");
|
|
1257
1301
|
}
|