vectorvesper 0.2.1 → 0.3.0
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 +92 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -714,6 +714,37 @@ function recordInstall(components, installDir, projectRoot) {
|
|
|
714
714
|
}
|
|
715
715
|
writeManifest(projectRoot, manifest);
|
|
716
716
|
}
|
|
717
|
+
function findOrphanedFiles(components, installDir, projectRoot, previousManifest) {
|
|
718
|
+
const compDir = path5.join(projectRoot, installDir);
|
|
719
|
+
const currentTargets = /* @__PURE__ */ new Set();
|
|
720
|
+
for (const component of components) {
|
|
721
|
+
for (const file of component.files) currentTargets.add(file.target);
|
|
722
|
+
}
|
|
723
|
+
const orphans = [];
|
|
724
|
+
const seen = /* @__PURE__ */ new Set();
|
|
725
|
+
for (const component of components) {
|
|
726
|
+
const entry = previousManifest.components[component.slug];
|
|
727
|
+
if (!entry) continue;
|
|
728
|
+
for (const target of entry.files) {
|
|
729
|
+
if (currentTargets.has(target)) continue;
|
|
730
|
+
if (seen.has(target)) continue;
|
|
731
|
+
seen.add(target);
|
|
732
|
+
const absolutePath = path5.resolve(compDir, target);
|
|
733
|
+
const relativeFromRoot = path5.relative(projectRoot, absolutePath);
|
|
734
|
+
if (relativeFromRoot.startsWith("..") || path5.isAbsolute(relativeFromRoot)) continue;
|
|
735
|
+
if (!fs5.existsSync(absolutePath)) continue;
|
|
736
|
+
orphans.push({ absolutePath, relativePath: relativeFromRoot, target });
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return orphans;
|
|
740
|
+
}
|
|
741
|
+
function removeFiles(files) {
|
|
742
|
+
for (const file of files) {
|
|
743
|
+
if (fs5.existsSync(file.absolutePath)) {
|
|
744
|
+
fs5.rmSync(file.absolutePath, { force: true });
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
717
748
|
|
|
718
749
|
// src/utils/install.ts
|
|
719
750
|
import fs6 from "fs";
|
|
@@ -889,6 +920,39 @@ Installing dependencies with ${projectInfo.packageManager}...`));
|
|
|
889
920
|
console.log(` Run manually: ${pc6.bold(pc6.cyan(installCmd))}`);
|
|
890
921
|
}
|
|
891
922
|
}
|
|
923
|
+
async function handlePrune(orphans, slug, options) {
|
|
924
|
+
if (orphans.length === 0) return;
|
|
925
|
+
const list = orphans.map((o) => ` ${pc6.dim("\u2022")} ${pc6.cyan(o.relativePath)}`).join("\n");
|
|
926
|
+
let shouldPrune = options.prune === true;
|
|
927
|
+
if (!shouldPrune) {
|
|
928
|
+
console.log(
|
|
929
|
+
pc6.yellow(
|
|
930
|
+
`
|
|
931
|
+
\u{1F9F9} ${orphans.length} file(s) from a previous version of ${pc6.cyan(slug)} are no longer part of it:`
|
|
932
|
+
)
|
|
933
|
+
);
|
|
934
|
+
console.log(list);
|
|
935
|
+
if (options.yes) {
|
|
936
|
+
console.log(pc6.dim(` Re-run with ${pc6.cyan("--prune")} to remove them.`));
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
const answer = await confirm2({
|
|
940
|
+
message: "Remove these orphaned files?",
|
|
941
|
+
initialValue: true
|
|
942
|
+
});
|
|
943
|
+
if (isCancel2(answer) || !answer) {
|
|
944
|
+
console.log(pc6.dim(` Left in place. Run with ${pc6.cyan("--prune")} later to remove them.`));
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
shouldPrune = true;
|
|
948
|
+
}
|
|
949
|
+
removeFiles(orphans);
|
|
950
|
+
console.log(pc6.green(`
|
|
951
|
+
\u{1F9F9} Removed ${orphans.length} orphaned file(s):`));
|
|
952
|
+
for (const o of orphans) {
|
|
953
|
+
console.log(` ${pc6.red("\u2212")} ${pc6.cyan(o.relativePath)}`);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
892
956
|
async function addCommand(slug, options = {}) {
|
|
893
957
|
try {
|
|
894
958
|
validateSlug(slug);
|
|
@@ -959,6 +1023,13 @@ async function addCommand(slug, options = {}) {
|
|
|
959
1023
|
}
|
|
960
1024
|
const targetComponent = resolvedComponents[resolvedComponents.length - 1];
|
|
961
1025
|
const installPath = toForwardSlash(path7.join(componentInstallDir, targetComponent.slug));
|
|
1026
|
+
let orphans = [];
|
|
1027
|
+
try {
|
|
1028
|
+
const previousManifest = readManifest(projectRoot);
|
|
1029
|
+
orphans = findOrphanedFiles(resolvedComponents, componentInstallDir, projectRoot, previousManifest);
|
|
1030
|
+
} catch {
|
|
1031
|
+
orphans = [];
|
|
1032
|
+
}
|
|
962
1033
|
if (options.dryRun) {
|
|
963
1034
|
spinner.succeed(pc6.yellow("Dry-run: simulation completed. No files were written."));
|
|
964
1035
|
console.log(pc6.bold(pc6.yellow("\n[Dry Run] Files that would be created/modified:")));
|
|
@@ -966,6 +1037,13 @@ async function addCommand(slug, options = {}) {
|
|
|
966
1037
|
const status = fs7.existsSync(file.absolutePath) ? pc6.yellow("(exists, would overwrite)") : pc6.green("(new)");
|
|
967
1038
|
console.log(` ${pc6.cyan(file.relativePath)} ${status}`);
|
|
968
1039
|
}
|
|
1040
|
+
if (orphans.length > 0) {
|
|
1041
|
+
console.log(pc6.bold(pc6.yellow("\n[Dry Run] Orphaned files from a previous version:")));
|
|
1042
|
+
for (const o of orphans) {
|
|
1043
|
+
const note = options.prune ? pc6.red("(would remove)") : pc6.dim("(use --prune to remove)");
|
|
1044
|
+
console.log(` ${pc6.cyan(o.relativePath)} ${note}`);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
969
1047
|
const missing = getMissingDependencies(resolvedComponents, projectRoot);
|
|
970
1048
|
if (missing.length > 0) {
|
|
971
1049
|
console.log(pc6.yellow(`
|
|
@@ -979,6 +1057,7 @@ async function addCommand(slug, options = {}) {
|
|
|
979
1057
|
}
|
|
980
1058
|
if (filesToWrite.length === 0) {
|
|
981
1059
|
spinner.succeed(pc6.green("All files skipped (already up to date)."));
|
|
1060
|
+
await handlePrune(orphans, targetComponent.slug, options);
|
|
982
1061
|
return;
|
|
983
1062
|
}
|
|
984
1063
|
spinner.text = "Writing component files...";
|
|
@@ -1002,6 +1081,7 @@ async function addCommand(slug, options = {}) {
|
|
|
1002
1081
|
for (const file of filesToWrite) {
|
|
1003
1082
|
console.log(` ${pc6.green("\u2714")} ${pc6.cyan(file.relativePath)}`);
|
|
1004
1083
|
}
|
|
1084
|
+
await handlePrune(orphans, targetComponent.slug, options);
|
|
1005
1085
|
await handleDependencies(resolvedComponents, projectRoot, projectInfo, options);
|
|
1006
1086
|
printGuidance(targetComponent, {
|
|
1007
1087
|
alias: config.aliases.vv,
|
|
@@ -1076,6 +1156,7 @@ async function updateCommand(slug, options = {}) {
|
|
|
1076
1156
|
const updated = [];
|
|
1077
1157
|
const upToDate = [];
|
|
1078
1158
|
const failed = [];
|
|
1159
|
+
const updatedComponents = [];
|
|
1079
1160
|
for (const target of targets) {
|
|
1080
1161
|
spinner.text = `Updating ${pc7.cyan(target)}...`;
|
|
1081
1162
|
try {
|
|
@@ -1090,6 +1171,7 @@ async function updateCommand(slug, options = {}) {
|
|
|
1090
1171
|
writeFiles(planned.map((f) => ({ absolutePath: f.absolutePath, content: f.content })));
|
|
1091
1172
|
recordInstall(components, installDir, projectRoot);
|
|
1092
1173
|
updated.push(`${target} \u2192 ${remote.version}`);
|
|
1174
|
+
updatedComponents.push(...components);
|
|
1093
1175
|
} catch (error) {
|
|
1094
1176
|
const message = error instanceof Error ? error.message : String(error);
|
|
1095
1177
|
failed.push({ slug: target, reason: message });
|
|
@@ -1113,6 +1195,9 @@ async function updateCommand(slug, options = {}) {
|
|
|
1113
1195
|
for (const f of failed) console.log(` ${pc7.red("\u2716")} ${f.slug}: ${pc7.dim(f.reason)}`);
|
|
1114
1196
|
}
|
|
1115
1197
|
console.log("");
|
|
1198
|
+
if (updatedComponents.length > 0) {
|
|
1199
|
+
await handleDependencies(updatedComponents, projectRoot, projectInfo, options);
|
|
1200
|
+
}
|
|
1116
1201
|
if (failed.length > 0) process.exit(1);
|
|
1117
1202
|
}
|
|
1118
1203
|
|
|
@@ -1217,7 +1302,7 @@ Remove ${slug}
|
|
|
1217
1302
|
import fs9 from "fs";
|
|
1218
1303
|
import path9 from "path";
|
|
1219
1304
|
import pc9 from "picocolors";
|
|
1220
|
-
var CLI_VERSION = true ? "0.
|
|
1305
|
+
var CLI_VERSION = true ? "0.3.0" : "0.0.0-dev";
|
|
1221
1306
|
async function infoCommand() {
|
|
1222
1307
|
console.log(pc9.bold(pc9.cyan("\nVector Vesper Diagnostics\n")));
|
|
1223
1308
|
const projectInfo = detectProject();
|
|
@@ -1237,17 +1322,6 @@ async function infoCommand() {
|
|
|
1237
1322
|
console.log(` \u2022 Has src/ folder: ${pc9.cyan(projectInfo.hasSrcDir ? "Yes" : "No")}`);
|
|
1238
1323
|
console.log(` \u2022 Tailwind CSS: ${pc9.cyan(projectInfo.hasTailwind ? "Yes" : "No")}`);
|
|
1239
1324
|
console.log("");
|
|
1240
|
-
console.log(pc9.bold(pc9.white("Authentication:")));
|
|
1241
|
-
const token = getAuthToken();
|
|
1242
|
-
if (token) {
|
|
1243
|
-
const maskedKey = token.slice(0, 6) + "\u2026" + token.slice(-4);
|
|
1244
|
-
console.log(` \u2022 Status: ${pc9.green("Authenticated")}`);
|
|
1245
|
-
console.log(` \u2022 Key: ${pc9.cyan(maskedKey)}`);
|
|
1246
|
-
} else {
|
|
1247
|
-
console.log(` \u2022 Status: ${pc9.yellow("Anonymous (free tier)")}`);
|
|
1248
|
-
console.log(` ${pc9.dim(" Run")} ${pc9.cyan("npx vectorvesper login <key>")} ${pc9.dim("to unlock pro components")}`);
|
|
1249
|
-
}
|
|
1250
|
-
console.log("");
|
|
1251
1325
|
console.log(pc9.bold(pc9.white("Configuration (vv.config.json):")));
|
|
1252
1326
|
if (config) {
|
|
1253
1327
|
console.log(` \u2022 Framework Set: ${pc9.cyan(config.framework)}`);
|
|
@@ -1526,7 +1600,7 @@ async function whoamiCommand() {
|
|
|
1526
1600
|
}
|
|
1527
1601
|
|
|
1528
1602
|
// src/index.ts
|
|
1529
|
-
var version = true ? "0.
|
|
1603
|
+
var version = true ? "0.3.0" : "0.0.0-dev";
|
|
1530
1604
|
var program = new Command();
|
|
1531
1605
|
program.name("vv").description("Vector Vesper CLI \u2014 add visual components to your React project").version(version).option("--verbose", "Show detailed debug output").hook("preAction", (thisCommand) => {
|
|
1532
1606
|
const opts = thisCommand.opts();
|
|
@@ -1540,10 +1614,10 @@ program.command("init").description("Initialize Vector Vesper configuration in y
|
|
|
1540
1614
|
program.command("list").description("List all available components in the registry").action(async () => {
|
|
1541
1615
|
await listCommand();
|
|
1542
1616
|
});
|
|
1543
|
-
program.command("add <slug>").description("Add a component to your project").option("-o, --overwrite", "Overwrite existing files without prompting").option("-y, --yes", "Accept all default prompts").option("-d, --dry-run", "Simulate the installation without writing files").option("--no-install", "Skip auto-installing missing dependencies").action(async (slug, options) => {
|
|
1617
|
+
program.command("add <slug>").description("Add a component to your project").option("-o, --overwrite", "Overwrite existing files without prompting").option("-y, --yes", "Accept all default prompts").option("-d, --dry-run", "Simulate the installation without writing files").option("--no-install", "Skip auto-installing missing dependencies").option("--prune", "Remove files left over from a previous version of the component").action(async (slug, options) => {
|
|
1544
1618
|
await addCommand(slug, options);
|
|
1545
1619
|
});
|
|
1546
|
-
program.command("update [slug]").description("Update installed components to the latest registry version").option("-f, --force", "Re-write files even if the version already matches").action(async (slug, options) => {
|
|
1620
|
+
program.command("update [slug]").description("Update installed components to the latest registry version").option("-f, --force", "Re-write files even if the version already matches").option("-y, --yes", "Accept all prompts (auto-install missing dependencies)").option("--no-install", "Skip auto-installing missing dependencies").action(async (slug, options) => {
|
|
1547
1621
|
await updateCommand(slug, options);
|
|
1548
1622
|
});
|
|
1549
1623
|
program.command("remove <slug>").alias("rm").description("Remove an installed component and its files").option("-y, --yes", "Skip the confirmation prompt").action(async (slug, options) => {
|
|
@@ -1555,13 +1629,13 @@ program.command("info").description("Show project diagnostics and list installed
|
|
|
1555
1629
|
program.command("diff [slug]").description("Check for updates against the component registry").action(async (slug) => {
|
|
1556
1630
|
await diffCommand(slug);
|
|
1557
1631
|
});
|
|
1558
|
-
program.command("login <key>").description("Authenticate with a license key for pro components").action(async (key) => {
|
|
1632
|
+
program.command("login <key>", { hidden: true }).description("Authenticate with a license key for pro components").action(async (key) => {
|
|
1559
1633
|
await loginCommand(key);
|
|
1560
1634
|
});
|
|
1561
|
-
program.command("logout").description("Clear stored license credentials").action(async () => {
|
|
1635
|
+
program.command("logout", { hidden: true }).description("Clear stored license credentials").action(async () => {
|
|
1562
1636
|
await logoutCommand();
|
|
1563
1637
|
});
|
|
1564
|
-
program.command("whoami").description("Show current authentication status").action(async () => {
|
|
1638
|
+
program.command("whoami", { hidden: true }).description("Show current authentication status").action(async () => {
|
|
1565
1639
|
await whoamiCommand();
|
|
1566
1640
|
});
|
|
1567
1641
|
process.on("unhandledRejection", (error) => {
|