wensity 0.1.3 → 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 +250 -54
- package/package.json +7 -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.4";
|
|
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";
|
|
@@ -449,23 +449,124 @@ import { spawnSync } from "child_process";
|
|
|
449
449
|
import { join as join4 } from "path";
|
|
450
450
|
|
|
451
451
|
// src/output.ts
|
|
452
|
+
import boxen from "boxen";
|
|
453
|
+
import Table from "cli-table3";
|
|
454
|
+
import ora from "ora";
|
|
455
|
+
import pc from "picocolors";
|
|
456
|
+
var LOGO = [
|
|
457
|
+
"\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
|
+
"\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",
|
|
459
|
+
"\u2588\u2588\u2551 \u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2554\u255D ",
|
|
460
|
+
"\u2588\u2588\u2551\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2554\u255D ",
|
|
461
|
+
"\u255A\u2588\u2588\u2588\u2554\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 ",
|
|
462
|
+
" \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D "
|
|
463
|
+
];
|
|
452
464
|
function print(message = "") {
|
|
453
465
|
process.stdout.write(`${message}
|
|
454
466
|
`);
|
|
455
467
|
}
|
|
456
468
|
function warn(message) {
|
|
457
|
-
process.stderr.write(
|
|
458
|
-
`);
|
|
459
|
-
}
|
|
460
|
-
function info(message) {
|
|
461
|
-
process.stderr.write(`${message}
|
|
469
|
+
process.stderr.write(`${pc.yellow("Warning:")} ${message}
|
|
462
470
|
`);
|
|
463
471
|
}
|
|
464
472
|
function printJson(value) {
|
|
465
473
|
print(JSON.stringify(value, null, 2));
|
|
466
474
|
}
|
|
467
475
|
function formatList(items) {
|
|
468
|
-
return items.map((item) => `
|
|
476
|
+
return items.map((item) => ` ${pc.dim("\u2022")} ${item}`).join("\n");
|
|
477
|
+
}
|
|
478
|
+
function brandBanner(subtitle) {
|
|
479
|
+
const lines = [pc.red(LOGO.join("\n")), pc.bold("Wensity CLI")];
|
|
480
|
+
if (subtitle) lines.push(pc.dim(subtitle));
|
|
481
|
+
return lines.join("\n");
|
|
482
|
+
}
|
|
483
|
+
function printBrand(subtitle) {
|
|
484
|
+
print(brandBanner(subtitle));
|
|
485
|
+
}
|
|
486
|
+
function success(message) {
|
|
487
|
+
return `${pc.green("\u2713")} ${message}`;
|
|
488
|
+
}
|
|
489
|
+
function failure(message) {
|
|
490
|
+
return `${pc.red("\u2715")} ${message}`;
|
|
491
|
+
}
|
|
492
|
+
function action(message) {
|
|
493
|
+
return `${pc.red("\u25C6")} ${message}`;
|
|
494
|
+
}
|
|
495
|
+
function badge(label, tone = "muted") {
|
|
496
|
+
const text = ` ${label.toUpperCase()} `;
|
|
497
|
+
if (tone === "pro") return pc.bgRed(pc.white(pc.bold(text)));
|
|
498
|
+
if (tone === "free") return pc.bgGreen(pc.black(pc.bold(text)));
|
|
499
|
+
return pc.inverse(text);
|
|
500
|
+
}
|
|
501
|
+
function panel(title, body) {
|
|
502
|
+
const content = Array.isArray(body) ? body.join("\n") : body;
|
|
503
|
+
return boxen(content, {
|
|
504
|
+
title: pc.red(pc.bold(title)),
|
|
505
|
+
titleAlignment: "left",
|
|
506
|
+
borderColor: "red",
|
|
507
|
+
borderStyle: "round",
|
|
508
|
+
padding: 1,
|
|
509
|
+
margin: { top: 1, bottom: 0 }
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
function nextSteps(steps) {
|
|
513
|
+
return panel(
|
|
514
|
+
"Next steps",
|
|
515
|
+
steps.map((step) => `${pc.red("\u203A")} ${pc.bold(step)}`)
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
function table(head, rows) {
|
|
519
|
+
const output = new Table({
|
|
520
|
+
head: head.map((item) => pc.red(pc.bold(item))),
|
|
521
|
+
chars: {
|
|
522
|
+
top: "\u2500",
|
|
523
|
+
"top-mid": "\u252C",
|
|
524
|
+
"top-left": "\u256D",
|
|
525
|
+
"top-right": "\u256E",
|
|
526
|
+
bottom: "\u2500",
|
|
527
|
+
"bottom-mid": "\u2534",
|
|
528
|
+
"bottom-left": "\u2570",
|
|
529
|
+
"bottom-right": "\u256F",
|
|
530
|
+
left: "\u2502",
|
|
531
|
+
"left-mid": "\u251C",
|
|
532
|
+
mid: "\u2500",
|
|
533
|
+
"mid-mid": "\u253C",
|
|
534
|
+
right: "\u2502",
|
|
535
|
+
"right-mid": "\u2524",
|
|
536
|
+
middle: "\u2502"
|
|
537
|
+
},
|
|
538
|
+
style: {
|
|
539
|
+
border: [],
|
|
540
|
+
head: []
|
|
541
|
+
},
|
|
542
|
+
wordWrap: true
|
|
543
|
+
});
|
|
544
|
+
output.push(...rows);
|
|
545
|
+
return output.toString();
|
|
546
|
+
}
|
|
547
|
+
function startSpinner(text) {
|
|
548
|
+
return ora({
|
|
549
|
+
text,
|
|
550
|
+
color: "red",
|
|
551
|
+
spinner: "dots",
|
|
552
|
+
isEnabled: process.stderr.isTTY && process.env.CI !== "true"
|
|
553
|
+
}).start();
|
|
554
|
+
}
|
|
555
|
+
async function withSpinner(text, task, successText = text) {
|
|
556
|
+
const spinner = startSpinner(text);
|
|
557
|
+
try {
|
|
558
|
+
const result = await task();
|
|
559
|
+
spinner.succeed(successText);
|
|
560
|
+
return result;
|
|
561
|
+
} catch (error) {
|
|
562
|
+
spinner.fail(text);
|
|
563
|
+
throw error;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
function formatCliError(message) {
|
|
567
|
+
return `${failure(message)}
|
|
568
|
+
|
|
569
|
+
${pc.dim("Need help?")} ${pc.red("https://ui.wensity.com/docs")}`;
|
|
469
570
|
}
|
|
470
571
|
|
|
471
572
|
// src/package-manager.ts
|
|
@@ -819,7 +920,7 @@ async function run(context) {
|
|
|
819
920
|
return;
|
|
820
921
|
}
|
|
821
922
|
if (hasFlag(parsed, "help") || parsed.positionals.length === 0) {
|
|
822
|
-
print(
|
|
923
|
+
print(formatHelp());
|
|
823
924
|
return;
|
|
824
925
|
}
|
|
825
926
|
const [command, ...positionals] = parsed.positionals;
|
|
@@ -865,9 +966,10 @@ async function initCommand(context, parsed) {
|
|
|
865
966
|
const utilityRelativePath = toPosixPath(config.utils.endsWith(".ts") ? config.utils : `${config.utils}.ts`);
|
|
866
967
|
const dependencies = ["clsx", "tailwind-merge"];
|
|
867
968
|
if (dryRun) {
|
|
868
|
-
|
|
969
|
+
printBrand("Project initialization preview");
|
|
970
|
+
print(action("Would write:"));
|
|
869
971
|
print(formatList([CONFIG_FILE_NAME, utilityRelativePath]));
|
|
870
|
-
if (install) print(`Would install: ${dependencies.join(" ")}`);
|
|
972
|
+
if (install) print(action(`Would install: ${dependencies.join(" ")}`));
|
|
871
973
|
return;
|
|
872
974
|
}
|
|
873
975
|
await writeConfigFile(configPath, config, force);
|
|
@@ -877,7 +979,17 @@ async function initCommand(context, parsed) {
|
|
|
877
979
|
if (install) {
|
|
878
980
|
runInstall(context.cwd, missingDependencies(context.cwd, dependencies));
|
|
879
981
|
}
|
|
880
|
-
|
|
982
|
+
printBrand("Project initialized");
|
|
983
|
+
print(panel("Created", [
|
|
984
|
+
success(CONFIG_FILE_NAME),
|
|
985
|
+
success(utilityRelativePath),
|
|
986
|
+
success(`registry: ${apiUrl}`)
|
|
987
|
+
]));
|
|
988
|
+
print(nextSteps([
|
|
989
|
+
"npx wensity list",
|
|
990
|
+
"npx wensity add liquid-multimodal-input",
|
|
991
|
+
"npx wensity login --token <token>"
|
|
992
|
+
]));
|
|
881
993
|
}
|
|
882
994
|
async function loginCommand(context, parsed) {
|
|
883
995
|
const apiUrl = getStringOption(parsed, "api-url") ?? context.env.WENSITY_API_URL ?? DEFAULT_API_ORIGIN;
|
|
@@ -896,12 +1008,21 @@ async function loginCommand(context, parsed) {
|
|
|
896
1008
|
plan: whoami.plan,
|
|
897
1009
|
savedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
898
1010
|
});
|
|
899
|
-
|
|
900
|
-
print(
|
|
1011
|
+
printBrand("API token verified");
|
|
1012
|
+
print(formatAccountPanel(whoami, path));
|
|
1013
|
+
print(nextSteps(whoami.plan?.tier === "pro" ? [
|
|
1014
|
+
"npx wensity add gooey-navigation-menu",
|
|
1015
|
+
"npx wensity add monolith-hero --type block",
|
|
1016
|
+
"npx wensity whoami"
|
|
1017
|
+
] : [
|
|
1018
|
+
"npx wensity add liquid-multimodal-input",
|
|
1019
|
+
"Upgrade to unlock Pro components and blocks: https://ui.wensity.com/pricing"
|
|
1020
|
+
]));
|
|
901
1021
|
}
|
|
902
1022
|
async function logoutCommand(context) {
|
|
903
1023
|
const removed = await deleteCredentials(context.env);
|
|
904
|
-
|
|
1024
|
+
printBrand("Session");
|
|
1025
|
+
print(removed ? success("Logged out of Wensity.") : action("No Wensity credentials were stored."));
|
|
905
1026
|
}
|
|
906
1027
|
async function whoamiCommand(context, parsed) {
|
|
907
1028
|
const credentials = await requireCredentials(context.env);
|
|
@@ -912,10 +1033,8 @@ async function whoamiCommand(context, parsed) {
|
|
|
912
1033
|
printJson({ ...whoami, apiBaseUrl: credentials.apiBaseUrl, credentialsPath: credentialsPath(context.env) });
|
|
913
1034
|
return;
|
|
914
1035
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
print(`Plan: ${whoami.plan.tier}${whoami.plan.status ? ` (${whoami.plan.status})` : ""}`);
|
|
918
|
-
}
|
|
1036
|
+
printBrand("Account");
|
|
1037
|
+
print(formatAccountPanel(whoami, credentialsPath(context.env)));
|
|
919
1038
|
}
|
|
920
1039
|
async function listCommand(context, parsed) {
|
|
921
1040
|
const resourceType = getResourceType(parsed);
|
|
@@ -930,11 +1049,16 @@ async function listCommand(context, parsed) {
|
|
|
930
1049
|
return;
|
|
931
1050
|
}
|
|
932
1051
|
if (response2.blocks.length === 0) {
|
|
933
|
-
|
|
1052
|
+
printBrand("Blocks");
|
|
1053
|
+
print(action("No Wensity blocks found."));
|
|
934
1054
|
return;
|
|
935
1055
|
}
|
|
936
|
-
|
|
1056
|
+
printBrand("Premium blocks");
|
|
937
1057
|
print(formatBlockGroup(response2.blocks));
|
|
1058
|
+
print(nextSteps([
|
|
1059
|
+
"npx wensity login --token <pro-token>",
|
|
1060
|
+
`npx wensity add ${response2.blocks[0]?.slug ?? "<block-slug>"} --type block`
|
|
1061
|
+
]));
|
|
938
1062
|
return;
|
|
939
1063
|
}
|
|
940
1064
|
const response = await requestJson(registry);
|
|
@@ -943,32 +1067,39 @@ async function listCommand(context, parsed) {
|
|
|
943
1067
|
return;
|
|
944
1068
|
}
|
|
945
1069
|
if (response.components.length === 0) {
|
|
946
|
-
|
|
1070
|
+
printBrand("Components");
|
|
1071
|
+
print(action("No registry components found."));
|
|
947
1072
|
return;
|
|
948
1073
|
}
|
|
949
|
-
|
|
1074
|
+
printBrand("Components");
|
|
950
1075
|
print(formatComponentGroup("Free", response.components.filter((component) => component.access !== "pro")));
|
|
951
1076
|
print(formatComponentGroup("Pro", response.components.filter((component) => component.access === "pro")));
|
|
1077
|
+
print(nextSteps([
|
|
1078
|
+
"npx wensity add liquid-multimodal-input",
|
|
1079
|
+
"npx wensity login --token <pro-token>",
|
|
1080
|
+
"npx wensity list --type block"
|
|
1081
|
+
]));
|
|
952
1082
|
}
|
|
953
1083
|
function formatComponentGroup(label, components) {
|
|
954
|
-
const
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1084
|
+
const tone = label.toLowerCase() === "pro" ? "pro" : "free";
|
|
1085
|
+
const rows = components.map((component) => [
|
|
1086
|
+
component.slug,
|
|
1087
|
+
component.category ?? "uncategorized",
|
|
1088
|
+
badge(label, tone)
|
|
1089
|
+
]);
|
|
958
1090
|
return rows.length > 0 ? `
|
|
959
|
-
${label}
|
|
960
|
-
${
|
|
961
|
-
${label}
|
|
962
|
-
|
|
1091
|
+
${badge(label, tone)}
|
|
1092
|
+
${table(["Slug", "Category", "Access"], rows)}` : `
|
|
1093
|
+
${badge(label, tone)}
|
|
1094
|
+
${action("No components")}`;
|
|
963
1095
|
}
|
|
964
1096
|
function formatBlockGroup(blocks) {
|
|
965
|
-
const rows = blocks.map((block) =>
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
${rows.join("\n")}` : "\nPro\n No blocks";
|
|
1097
|
+
const rows = blocks.map((block) => [
|
|
1098
|
+
block.slug,
|
|
1099
|
+
block.category ?? "uncategorized",
|
|
1100
|
+
badge("Pro", "pro")
|
|
1101
|
+
]);
|
|
1102
|
+
return rows.length > 0 ? `${table(["Slug", "Category", "Access"], rows)}` : action("No blocks");
|
|
972
1103
|
}
|
|
973
1104
|
async function addCommand(context, parsed, positionals, updateMode) {
|
|
974
1105
|
const resourceType = getResourceType(parsed);
|
|
@@ -994,54 +1125,93 @@ Usage: wensity ${updateMode ? "update" : "add"} <slug>${resourceType === "block"
|
|
|
994
1125
|
const plannedFiles = summarizeFiles(loaded.projectRoot, prepared.files);
|
|
995
1126
|
const missing = missingDependencies(loaded.projectRoot, prepared.dependencies);
|
|
996
1127
|
if (dryRun) {
|
|
997
|
-
|
|
1128
|
+
printBrand(updateMode ? "Update preview" : "Install preview");
|
|
1129
|
+
print(action("Would write:"));
|
|
998
1130
|
print(formatList(plannedFiles));
|
|
999
|
-
if (install && missing.length > 0) print(`Would install: ${missing.join(" ")}`);
|
|
1131
|
+
if (install && missing.length > 0) print(action(`Would install: ${missing.join(" ")}`));
|
|
1000
1132
|
return;
|
|
1001
1133
|
}
|
|
1002
1134
|
await writePlannedFiles(prepared.files);
|
|
1003
1135
|
if (install) {
|
|
1004
1136
|
runInstall(loaded.projectRoot, missing);
|
|
1005
1137
|
}
|
|
1006
|
-
|
|
1007
|
-
print(
|
|
1008
|
-
|
|
1138
|
+
printBrand(updateMode ? "Component updated" : "Component installed");
|
|
1139
|
+
print(panel(payload.name, [
|
|
1140
|
+
success(`${updateMode ? "Updated" : "Added"} ${payload.slug}`),
|
|
1141
|
+
...plannedFiles.map((file) => success(file))
|
|
1142
|
+
]));
|
|
1009
1143
|
if (!install && missing.length > 0) {
|
|
1010
1144
|
warn(`Dependencies were not installed: ${missing.join(" ")}`);
|
|
1145
|
+
print(nextSteps([`Install dependencies: ${missing.join(" ")}`]));
|
|
1146
|
+
return;
|
|
1011
1147
|
}
|
|
1148
|
+
print(nextSteps([
|
|
1149
|
+
"Import the component from your Wensity components folder",
|
|
1150
|
+
resourceType === "block" ? "Customize the block copy, colors, and sections" : "Customize props and styling for your app"
|
|
1151
|
+
]));
|
|
1012
1152
|
}
|
|
1013
1153
|
async function fetchComponentPayload(input) {
|
|
1014
|
-
|
|
1015
|
-
|
|
1154
|
+
const metadata = await withSpinner(
|
|
1155
|
+
`Finding ${input.slug}`,
|
|
1156
|
+
() => requestJson(registryMetadataUrl(input.registry, input.slug)),
|
|
1157
|
+
`Found ${input.slug}`
|
|
1158
|
+
);
|
|
1016
1159
|
if (input.credentials) {
|
|
1160
|
+
const credentials = input.credentials;
|
|
1017
1161
|
const cliEndpoint = metadata.endpoints?.cli ?? `/api/cli/${input.slug}`;
|
|
1018
|
-
const endpoint2 = cliEndpoint.startsWith("http") ? cliEndpoint : joinUrl(
|
|
1162
|
+
const endpoint2 = cliEndpoint.startsWith("http") ? cliEndpoint : joinUrl(credentials.apiBaseUrl, cliEndpoint);
|
|
1019
1163
|
try {
|
|
1020
|
-
return await
|
|
1164
|
+
return await withSpinner(
|
|
1165
|
+
`Downloading ${metadata.name}`,
|
|
1166
|
+
() => requestJson(endpoint2, { token: credentials.token }),
|
|
1167
|
+
`Downloaded ${metadata.name}`
|
|
1168
|
+
);
|
|
1021
1169
|
} catch (error) {
|
|
1022
1170
|
if (metadata.access === "pro" || !isAuthFailure(error)) throw error;
|
|
1023
1171
|
warn("Saved Wensity credentials were rejected; falling back to the public free registry payload.");
|
|
1024
1172
|
}
|
|
1025
1173
|
}
|
|
1026
1174
|
if (metadata.access === "pro") {
|
|
1027
|
-
throw new CliError(
|
|
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"));
|
|
1028
1181
|
}
|
|
1029
1182
|
const publicSourceEndpoint = metadata.endpoints?.registry ?? registrySlugUrl(input.registry, input.slug);
|
|
1030
1183
|
const endpoint = publicSourceEndpoint.startsWith("http") ? publicSourceEndpoint : joinUrl(registryOrigin(input.registry), publicSourceEndpoint);
|
|
1031
|
-
return
|
|
1184
|
+
return withSpinner(
|
|
1185
|
+
`Downloading ${metadata.name}`,
|
|
1186
|
+
() => requestJson(endpoint),
|
|
1187
|
+
`Downloaded ${metadata.name}`
|
|
1188
|
+
);
|
|
1032
1189
|
}
|
|
1033
1190
|
function isAuthFailure(error) {
|
|
1034
1191
|
return error instanceof CliError && /^(401|403)\b/.test(error.message);
|
|
1035
1192
|
}
|
|
1036
1193
|
async function fetchBlockPayload(input) {
|
|
1037
|
-
|
|
1038
|
-
|
|
1194
|
+
const metadata = await withSpinner(
|
|
1195
|
+
`Finding ${input.slug}`,
|
|
1196
|
+
() => requestJson(registryMetadataUrl(input.registry, input.slug)),
|
|
1197
|
+
`Found ${input.slug}`
|
|
1198
|
+
);
|
|
1039
1199
|
if (!input.credentials) {
|
|
1040
|
-
throw new CliError(
|
|
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"));
|
|
1041
1206
|
}
|
|
1207
|
+
const credentials = input.credentials;
|
|
1042
1208
|
const cliEndpoint = metadata.endpoints?.cli ?? `/api/cli/blocks/${input.slug}`;
|
|
1043
|
-
const endpoint = cliEndpoint.startsWith("http") ? cliEndpoint : joinUrl(
|
|
1044
|
-
return
|
|
1209
|
+
const endpoint = cliEndpoint.startsWith("http") ? cliEndpoint : joinUrl(credentials.apiBaseUrl, cliEndpoint);
|
|
1210
|
+
return withSpinner(
|
|
1211
|
+
`Downloading ${metadata.name}`,
|
|
1212
|
+
() => requestJson(endpoint, { token: credentials.token }),
|
|
1213
|
+
`Downloaded ${metadata.name}`
|
|
1214
|
+
);
|
|
1045
1215
|
}
|
|
1046
1216
|
function getResourceType(parsed) {
|
|
1047
1217
|
const value = getStringOption(parsed, "type") ?? "component";
|
|
@@ -1072,6 +1242,32 @@ function registryOrigin(registry) {
|
|
|
1072
1242
|
const url = new URL(registry);
|
|
1073
1243
|
return `${url.protocol}//${url.host}`;
|
|
1074
1244
|
}
|
|
1245
|
+
function formatHelp() {
|
|
1246
|
+
return [
|
|
1247
|
+
brandBanner("Own your component source."),
|
|
1248
|
+
"",
|
|
1249
|
+
HELP_TEXT.trimEnd(),
|
|
1250
|
+
"",
|
|
1251
|
+
nextSteps([
|
|
1252
|
+
"npx wensity init",
|
|
1253
|
+
"npx wensity list",
|
|
1254
|
+
"npx wensity add liquid-multimodal-input"
|
|
1255
|
+
])
|
|
1256
|
+
].join("\n");
|
|
1257
|
+
}
|
|
1258
|
+
function formatAccountPanel(whoami, savedPath) {
|
|
1259
|
+
const isPro = whoami.plan?.tier === "pro";
|
|
1260
|
+
const lines = [
|
|
1261
|
+
`${badge(isPro ? "Pro" : "Free", isPro ? "pro" : "free")} ${whoami.user.email}`,
|
|
1262
|
+
whoami.plan?.status ? `Status: ${whoami.plan.status}` : "Status: active",
|
|
1263
|
+
`Credentials: ${savedPath}`,
|
|
1264
|
+
"",
|
|
1265
|
+
isPro ? success("Pro components unlocked") : success("Free components unlocked"),
|
|
1266
|
+
isPro ? success("Pro blocks unlocked") : action("Pro blocks locked until upgrade"),
|
|
1267
|
+
isPro ? success("API token verified") : action("Upgrade for premium source access")
|
|
1268
|
+
];
|
|
1269
|
+
return panel(isPro ? "Wensity Pro" : "Wensity Free", lines);
|
|
1270
|
+
}
|
|
1075
1271
|
async function writeTextFile(path, content) {
|
|
1076
1272
|
await mkdir4(dirname5(path), { recursive: true });
|
|
1077
1273
|
await writeFile4(path, content, "utf8");
|
|
@@ -1084,7 +1280,7 @@ run({
|
|
|
1084
1280
|
env: process.env
|
|
1085
1281
|
}).catch((error) => {
|
|
1086
1282
|
if (error instanceof CliError) {
|
|
1087
|
-
process.stderr.write(`${error.message}
|
|
1283
|
+
process.stderr.write(`${formatCliError(error.message)}
|
|
1088
1284
|
`);
|
|
1089
1285
|
process.exitCode = error.exitCode;
|
|
1090
1286
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wensity",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Wensity component registry CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -28,5 +28,11 @@
|
|
|
28
28
|
},
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"boxen": "^8.0.1",
|
|
34
|
+
"cli-table3": "^0.6.5",
|
|
35
|
+
"ora": "^9.4.0",
|
|
36
|
+
"picocolors": "^1.1.1"
|
|
31
37
|
}
|
|
32
38
|
}
|