vectorvesper 1.2.0 → 2.0.1

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 CHANGED
@@ -1,304 +1,33 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ detectProject,
4
+ fetchComponent,
5
+ fetchRegistryIndex
6
+ } from "./chunk-HOJ3DQSV.js";
7
+ import {
8
+ getAuthToken,
9
+ getGlobalConfigPath,
10
+ loadConfig,
11
+ loadGlobalConfig,
12
+ logger,
13
+ resolveAlias,
14
+ saveGlobalConfig,
15
+ setVerbose,
16
+ validateSlug,
17
+ writeConfig
18
+ } from "./chunk-SFP5K3ZO.js";
2
19
 
3
20
  // src/index.ts
4
21
  import { Command } from "commander";
5
22
 
6
- // src/utils/logger.ts
7
- import pc from "picocolors";
8
- var verboseMode = false;
9
- function setVerbose(enabled) {
10
- verboseMode = enabled;
11
- }
12
- var logger = {
13
- /** Standard info message */
14
- info(message) {
15
- console.log(message);
16
- },
17
- /** Success message with green checkmark */
18
- success(message) {
19
- console.log(`${pc.green("\u2714")} ${message}`);
20
- },
21
- /** Warning message */
22
- warn(message) {
23
- console.log(pc.yellow(`\u26A0\uFE0F ${message}`));
24
- },
25
- /** Error message */
26
- error(message) {
27
- console.error(pc.red(`\u274C ${message}`));
28
- },
29
- /** Debug message — only shown when --verbose is active */
30
- debug(message) {
31
- if (verboseMode) {
32
- console.log(pc.dim(` [debug] ${message}`));
33
- }
34
- },
35
- /** Blank line */
36
- break() {
37
- console.log("");
38
- }
39
- };
40
-
41
23
  // src/commands/init.ts
42
24
  import { intro, outro, select, text, confirm, isCancel } from "@clack/prompts";
43
- import pc2 from "picocolors";
44
- import fs3 from "fs";
45
- import path3 from "path";
46
-
47
- // src/utils/project.ts
25
+ import pc from "picocolors";
48
26
  import fs from "fs";
49
27
  import path from "path";
50
- function detectProject(cwd = process.cwd()) {
51
- const rootPath = cwd;
52
- let packageManager = "npm";
53
- if (fs.existsSync(path.join(rootPath, "pnpm-lock.yaml"))) {
54
- packageManager = "pnpm";
55
- } else if (fs.existsSync(path.join(rootPath, "yarn.lock"))) {
56
- packageManager = "yarn";
57
- } else if (fs.existsSync(path.join(rootPath, "bun.lockb")) || fs.existsSync(path.join(rootPath, "bun.lock"))) {
58
- packageManager = "bun";
59
- }
60
- const isTypeScript = fs.existsSync(path.join(rootPath, "tsconfig.json"));
61
- const hasSrcDir = fs.existsSync(path.join(rootPath, "src"));
62
- const pkgPath = path.join(rootPath, "package.json");
63
- let dependencies = {};
64
- let devDependencies = {};
65
- if (fs.existsSync(pkgPath)) {
66
- try {
67
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
68
- dependencies = pkg.dependencies || {};
69
- devDependencies = pkg.devDependencies || {};
70
- } catch {
71
- }
72
- }
73
- const allDeps = { ...dependencies, ...devDependencies };
74
- const tailwindConfigs = [
75
- "tailwind.config.js",
76
- "tailwind.config.ts",
77
- "tailwind.config.cjs",
78
- "tailwind.config.mjs"
79
- ];
80
- const hasTailwindConfig = tailwindConfigs.some(
81
- (config) => fs.existsSync(path.join(rootPath, config))
82
- );
83
- const hasTailwindDep = "tailwindcss" in allDeps || "@tailwindcss/postcss" in allDeps || "@tailwindcss/vite" in allDeps;
84
- const hasTailwind = hasTailwindConfig || hasTailwindDep;
85
- let framework = "unknown";
86
- let nextRouter;
87
- if (dependencies["next"] || devDependencies["next"]) {
88
- framework = "next";
89
- const searchPath = hasSrcDir ? path.join(rootPath, "src") : rootPath;
90
- if (fs.existsSync(path.join(searchPath, "app"))) {
91
- nextRouter = "app";
92
- } else if (fs.existsSync(path.join(searchPath, "pages"))) {
93
- nextRouter = "pages";
94
- } else {
95
- nextRouter = "app";
96
- }
97
- } else if (dependencies["vite"] || devDependencies["vite"] || fs.existsSync(path.join(rootPath, "vite.config.ts")) || fs.existsSync(path.join(rootPath, "vite.config.js"))) {
98
- framework = "vite";
99
- }
100
- return {
101
- packageManager,
102
- isTypeScript,
103
- framework,
104
- nextRouter,
105
- hasSrcDir,
106
- hasTailwind,
107
- rootPath
108
- };
109
- }
110
-
111
- // src/utils/config.ts
112
- import fs2 from "fs";
113
- import path2 from "path";
114
- import os from "os";
115
-
116
- // src/utils/types.ts
117
- import { z } from "zod";
118
- var SLUG_REGEX = /^[a-z0-9][a-z0-9-]*$/;
119
- function validateSlug(slug) {
120
- if (!SLUG_REGEX.test(slug)) {
121
- throw new Error(
122
- `Invalid component slug "${slug}". Slugs must contain only lowercase letters, numbers, and hyphens, and cannot start with a hyphen.`
123
- );
124
- }
125
- }
126
- var ComponentFileSchema = z.object({
127
- path: z.string(),
128
- target: z.string(),
129
- type: z.enum(["component", "types", "shader", "lib", "docs"]),
130
- content: z.string()
131
- });
132
- var RegistryComponentSchema = z.object({
133
- slug: z.string(),
134
- name: z.string(),
135
- title: z.string(),
136
- description: z.string(),
137
- version: z.string(),
138
- tier: z.enum(["free", "pro"]),
139
- category: z.string(),
140
- type: z.string(),
141
- frameworks: z.array(z.string()),
142
- files: z.array(ComponentFileSchema),
143
- dependencies: z.array(z.string()),
144
- devDependencies: z.array(z.string()),
145
- registryDependencies: z.array(z.string()),
146
- requiresClient: z.boolean(),
147
- supportsReducedMotion: z.boolean(),
148
- usesWebGL: z.boolean(),
149
- usesPointer: z.boolean(),
150
- usesScroll: z.boolean(),
151
- // Optional metadata — kept in sync with the registry builder schema.
152
- // Declared here (rather than relying on .passthrough()) so the CLI can
153
- // read them with full type-safety for post-install guidance.
154
- entry: z.string().optional(),
155
- exportName: z.string().optional(),
156
- usesTailwind: z.boolean().optional(),
157
- fallbacks: z.array(z.string()).optional(),
158
- recipes: z.array(z.string()).optional(),
159
- docsUrl: z.string().optional(),
160
- previewUrl: z.string().optional()
161
- }).passthrough();
162
- var IndexComponentSchema = z.object({
163
- slug: z.string(),
164
- name: z.string(),
165
- title: z.string(),
166
- description: z.string(),
167
- version: z.string(),
168
- tier: z.enum(["free", "pro"]),
169
- category: z.string(),
170
- type: z.string(),
171
- frameworks: z.array(z.string()),
172
- files: z.array(z.object({
173
- path: z.string(),
174
- target: z.string(),
175
- type: z.enum(["component", "types", "shader", "lib", "docs"])
176
- })),
177
- dependencies: z.array(z.string()),
178
- devDependencies: z.array(z.string()),
179
- registryDependencies: z.array(z.string()),
180
- requiresClient: z.boolean(),
181
- supportsReducedMotion: z.boolean(),
182
- usesWebGL: z.boolean(),
183
- usesPointer: z.boolean(),
184
- usesScroll: z.boolean(),
185
- entry: z.string().optional(),
186
- exportName: z.string().optional(),
187
- usesTailwind: z.boolean().optional()
188
- }).passthrough();
189
- var RegistryIndexSchema = z.object({
190
- version: z.string(),
191
- components: z.array(IndexComponentSchema)
192
- });
193
- var VVConfigSchema = z.object({
194
- tsx: z.boolean(),
195
- framework: z.enum(["next", "vite", "unknown"]),
196
- aliases: z.object({
197
- vv: z.string()
198
- })
199
- });
200
- var VVGlobalConfigSchema = z.object({
201
- // Auth — license key for paid components
202
- auth: z.object({
203
- token: z.string().optional(),
204
- email: z.string().optional(),
205
- tier: z.enum(["free", "pro", "team"]).optional(),
206
- expiresAt: z.string().optional()
207
- }).optional(),
208
- // Preferences
209
- telemetry: z.boolean().optional()
210
- }).passthrough();
211
- var ManifestEntrySchema = z.object({
212
- version: z.string(),
213
- installedAt: z.string(),
214
- installedOn: z.string(),
215
- files: z.array(z.string())
216
- });
217
- var ManifestSchema = z.object({
218
- components: z.record(z.string(), ManifestEntrySchema)
219
- });
220
-
221
- // src/utils/config.ts
222
- var CONFIG_FILE_NAME = "vv.config.json";
223
- function getConfigPath(cwd = process.cwd()) {
224
- return path2.join(cwd, CONFIG_FILE_NAME);
225
- }
226
- function loadConfig(cwd = process.cwd()) {
227
- const configPath = getConfigPath(cwd);
228
- if (!fs2.existsSync(configPath)) {
229
- return null;
230
- }
231
- let raw;
232
- try {
233
- const content = fs2.readFileSync(configPath, "utf-8");
234
- raw = JSON.parse(content);
235
- } catch {
236
- throw new Error(
237
- `Failed to parse vv.config.json \u2014 the file contains invalid JSON. Delete it and run "npx vectorvesper init" to regenerate.`
238
- );
239
- }
240
- const result = VVConfigSchema.safeParse(raw);
241
- if (!result.success) {
242
- const issues = result.error.issues.map((i) => ` \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
243
- throw new Error(
244
- `Invalid vv.config.json \u2014 schema validation failed:
245
- ${issues}
246
- Delete the file and run "npx vectorvesper init" to regenerate.`
247
- );
248
- }
249
- return result.data;
250
- }
251
- function writeConfig(config, cwd = process.cwd()) {
252
- const configPath = getConfigPath(cwd);
253
- fs2.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
254
- }
255
- var GLOBAL_CONFIG_DIR = path2.join(os.homedir(), ".vv");
256
- var GLOBAL_CONFIG_PATH = path2.join(GLOBAL_CONFIG_DIR, "config.json");
257
- function getGlobalConfigPath() {
258
- return GLOBAL_CONFIG_PATH;
259
- }
260
- function loadGlobalConfig() {
261
- if (!fs2.existsSync(GLOBAL_CONFIG_PATH)) {
262
- return {};
263
- }
264
- try {
265
- const content = fs2.readFileSync(GLOBAL_CONFIG_PATH, "utf-8");
266
- const raw = JSON.parse(content);
267
- const result = VVGlobalConfigSchema.safeParse(raw);
268
- if (!result.success) {
269
- logger.debug(`Global config validation failed: ${result.error.message}`);
270
- return {};
271
- }
272
- return result.data;
273
- } catch {
274
- logger.debug("Failed to parse global config, using defaults.");
275
- return {};
276
- }
277
- }
278
- function saveGlobalConfig(config) {
279
- if (!fs2.existsSync(GLOBAL_CONFIG_DIR)) {
280
- fs2.mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true });
281
- }
282
- fs2.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
283
- }
284
- function getAuthToken() {
285
- const config = loadGlobalConfig();
286
- return config.auth?.token;
287
- }
288
- function resolveAlias(alias, hasSrcDir) {
289
- if (alias.startsWith("@/")) {
290
- return alias.replace("@/", hasSrcDir ? "src/" : "");
291
- }
292
- if (alias.startsWith("~/")) {
293
- return alias.replace("~/", hasSrcDir ? "src/" : "");
294
- }
295
- return alias;
296
- }
297
-
298
- // src/commands/init.ts
299
28
  async function initCommand(options = {}) {
300
29
  console.log("");
301
- intro(pc2.cyan(pc2.bold(" Vector Vesper Setup ")));
30
+ intro(pc.cyan(pc.bold(" Vector Vesper Setup ")));
302
31
  const projectInfo = detectProject();
303
32
  let tsx = projectInfo.isTypeScript;
304
33
  let framework = projectInfo.framework;
@@ -308,39 +37,39 @@ async function initCommand(options = {}) {
308
37
  const existingConfig = loadConfig();
309
38
  if (existingConfig) {
310
39
  const shouldOverwrite = await confirm({
311
- message: pc2.yellow("vv.config.json already exists. Overwrite it?"),
40
+ message: pc.yellow("vv.config.json already exists. Overwrite it?"),
312
41
  initialValue: false
313
42
  });
314
43
  if (isCancel(shouldOverwrite) || !shouldOverwrite) {
315
- outro(pc2.red("Setup cancelled."));
44
+ outro(pc.red("Setup cancelled."));
316
45
  return;
317
46
  }
318
47
  }
319
48
  } catch (error) {
320
49
  const message = error instanceof Error ? error.message : String(error);
321
- console.log(pc2.yellow(`
50
+ console.log(pc.yellow(`
322
51
  \u26A0\uFE0F ${message}
323
52
  `));
324
53
  const shouldReplace = await confirm({
325
- message: pc2.yellow("Replace the corrupted config?"),
54
+ message: pc.yellow("Replace the corrupted config?"),
326
55
  initialValue: true
327
56
  });
328
57
  if (isCancel(shouldReplace) || !shouldReplace) {
329
- outro(pc2.red("Setup cancelled."));
58
+ outro(pc.red("Setup cancelled."));
330
59
  return;
331
60
  }
332
61
  }
333
62
  const tsxResponse = await confirm({
334
- message: `Use TypeScript? ${pc2.dim(`(Detected: ${projectInfo.isTypeScript ? "Yes" : "No"})`)}`,
63
+ message: `Use TypeScript? ${pc.dim(`(Detected: ${projectInfo.isTypeScript ? "Yes" : "No"})`)}`,
335
64
  initialValue: projectInfo.isTypeScript
336
65
  });
337
66
  if (isCancel(tsxResponse)) {
338
- outro(pc2.red("Setup cancelled."));
67
+ outro(pc.red("Setup cancelled."));
339
68
  return;
340
69
  }
341
70
  tsx = tsxResponse;
342
71
  const frameworkResponse = await select({
343
- message: `Configure your framework: ${pc2.dim(`(Detected: ${projectInfo.framework})`)}`,
72
+ message: `Configure your framework: ${pc.dim(`(Detected: ${projectInfo.framework})`)}`,
344
73
  options: [
345
74
  { value: "next", label: "Next.js" },
346
75
  { value: "vite", label: "Vite" },
@@ -349,7 +78,7 @@ async function initCommand(options = {}) {
349
78
  initialValue: projectInfo.framework
350
79
  });
351
80
  if (isCancel(frameworkResponse)) {
352
- outro(pc2.red("Setup cancelled."));
81
+ outro(pc.red("Setup cancelled."));
353
82
  return;
354
83
  }
355
84
  framework = frameworkResponse;
@@ -365,15 +94,15 @@ async function initCommand(options = {}) {
365
94
  }
366
95
  });
367
96
  if (isCancel(aliasResponse)) {
368
- outro(pc2.red("Setup cancelled."));
97
+ outro(pc.red("Setup cancelled."));
369
98
  return;
370
99
  }
371
100
  aliasInput = aliasResponse;
372
101
  } else {
373
- console.log(pc2.dim(` \u26A1 Running in non-interactive mode (-y)`));
374
- console.log(pc2.dim(` \u2022 TypeScript: ${tsx ? "Yes" : "No"}`));
375
- console.log(pc2.dim(` \u2022 Framework: ${framework}`));
376
- console.log(pc2.dim(` \u2022 Components Alias: ${aliasInput}`));
102
+ console.log(pc.dim(` \u26A1 Running in non-interactive mode (-y)`));
103
+ console.log(pc.dim(` \u2022 TypeScript: ${tsx ? "Yes" : "No"}`));
104
+ console.log(pc.dim(` \u2022 Framework: ${framework}`));
105
+ console.log(pc.dim(` \u2022 Components Alias: ${aliasInput}`));
377
106
  }
378
107
  const config = {
379
108
  tsx,
@@ -385,190 +114,34 @@ async function initCommand(options = {}) {
385
114
  try {
386
115
  writeConfig(config);
387
116
  const targetLocalDir = resolveAlias(aliasInput, projectInfo.hasSrcDir);
388
- const absoluteTargetDir = path3.join(process.cwd(), targetLocalDir);
389
- if (!fs3.existsSync(absoluteTargetDir)) {
390
- fs3.mkdirSync(absoluteTargetDir, { recursive: true });
117
+ const absoluteTargetDir = path.join(process.cwd(), targetLocalDir);
118
+ if (!fs.existsSync(absoluteTargetDir)) {
119
+ fs.mkdirSync(absoluteTargetDir, { recursive: true });
391
120
  }
392
- const manifestPath = path3.join(process.cwd(), "vv-manifest.json");
393
- if (!fs3.existsSync(manifestPath)) {
394
- fs3.writeFileSync(manifestPath, JSON.stringify({ components: {} }, null, 2), "utf-8");
121
+ const manifestPath = path.join(process.cwd(), "vv-manifest.json");
122
+ if (!fs.existsSync(manifestPath)) {
123
+ fs.writeFileSync(manifestPath, JSON.stringify({ components: {} }, null, 2), "utf-8");
395
124
  }
396
125
  console.log("");
397
126
  outro(
398
- `${pc2.green(pc2.bold("\u2714 Success!"))} Vector Vesper initialized.
127
+ `${pc.green(pc.bold("\u2714 Success!"))} Vector Vesper initialized.
399
128
 
400
- \u2022 Configuration written to ${pc2.cyan("vv.config.json")}
401
- \u2022 Target directory created at ${pc2.cyan(targetLocalDir)}
402
- \u2022 Manifest created at ${pc2.cyan("vv-manifest.json")}
129
+ \u2022 Configuration written to ${pc.cyan("vv.config.json")}
130
+ \u2022 Target directory created at ${pc.cyan(targetLocalDir)}
131
+ \u2022 Manifest created at ${pc.cyan("vv-manifest.json")}
403
132
 
404
- \u{1F449} Next, run: ${pc2.bold(pc2.cyan("npx vectorvesper add <slug>"))} to add a component.`
133
+ \u{1F449} Next, run: ${pc.bold(pc.cyan("npx vectorvesper add <slug>"))} to add a component.`
405
134
  );
406
135
  } catch (error) {
407
136
  const message = error instanceof Error ? error.message : String(error);
408
- outro(pc2.red(`Failed to initialize: ${message}`));
137
+ outro(pc.red(`Failed to initialize: ${message}`));
409
138
  process.exit(1);
410
139
  }
411
140
  }
412
141
 
413
142
  // src/commands/list.ts
414
- import pc3 from "picocolors";
143
+ import pc2 from "picocolors";
415
144
  import ora from "ora";
416
-
417
- // src/utils/registry.ts
418
- import fs4 from "fs";
419
- import path4 from "path";
420
- import { fileURLToPath } from "url";
421
- var DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/vectorvesper/vv-components/main/r";
422
- var FETCH_TIMEOUT_MS = 15e3;
423
- var MAX_RETRIES = 1;
424
- var RETRY_DELAY_MS = 1e3;
425
- function getRegistryBaseUrl() {
426
- return process.env.VV_REGISTRY_URL || DEFAULT_REGISTRY_URL;
427
- }
428
- function handleHttpError(status, url) {
429
- switch (status) {
430
- case 401:
431
- throw new Error(
432
- `Authentication required. This component requires a valid license key.
433
- \u{1F449} Run "npx vectorvesper login <your-license-key>" to authenticate.
434
- \u{1F511} Get a license at https://vectorvesper.dev/pricing`
435
- );
436
- case 402:
437
- throw new Error(
438
- `This is a Pro component and requires a license.
439
- \u{1F449} Get lifetime access at https://vectorvesper.dev/pricing
440
- \u{1F4A1} Run "npx vectorvesper list" to see all free components.`
441
- );
442
- case 403:
443
- throw new Error(
444
- `Access denied. Your license doesn't include this component.
445
- \u{1F449} Check your account at https://vectorvesper.dev/account
446
- \u{1F4A1} Run "npx vectorvesper whoami" to see your current access.`
447
- );
448
- case 404:
449
- throw new Error(
450
- `Component not found in the registry.
451
- \u{1F449} Run "npx vectorvesper list" to see all available components.`
452
- );
453
- case 429:
454
- throw new Error(
455
- `Rate limited by the registry. Please wait a moment and try again.`
456
- );
457
- default:
458
- throw new Error(
459
- `Registry request failed: HTTP ${status}
460
- URL: ${url}`
461
- );
462
- }
463
- }
464
- async function fetchWithRetry(url) {
465
- const token = getAuthToken();
466
- const headers = {
467
- "User-Agent": "vv-cli",
468
- "Accept": "application/json"
469
- };
470
- const isPublicRegistry = url.includes("raw.githubusercontent.com");
471
- if (token && !isPublicRegistry) {
472
- headers["Authorization"] = `Bearer ${token}`;
473
- logger.debug(`Using auth token for request`);
474
- }
475
- let lastError = null;
476
- for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
477
- try {
478
- if (attempt > 0) {
479
- logger.debug(`Retry attempt ${attempt} for ${url}`);
480
- await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY_MS * attempt));
481
- }
482
- logger.debug(`Fetching: ${url}`);
483
- const response = await fetch(url, {
484
- headers,
485
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
486
- });
487
- if (!response.ok) {
488
- if (response.status >= 400 && response.status < 500) {
489
- handleHttpError(response.status, url);
490
- }
491
- throw new Error(`HTTP ${response.status}`);
492
- }
493
- return await response.text();
494
- } catch (error) {
495
- if (error instanceof Error) {
496
- if (error.message.includes("Authentication required") || error.message.includes("Pro component") || error.message.includes("Access denied") || error.message.includes("not found in the registry")) {
497
- throw error;
498
- }
499
- if (error.name === "TimeoutError" || error.name === "AbortError") {
500
- lastError = new Error(
501
- `Request timed out after ${FETCH_TIMEOUT_MS / 1e3}s. Check your internet connection or try again.`
502
- );
503
- continue;
504
- }
505
- lastError = error;
506
- } else {
507
- lastError = new Error(String(error));
508
- }
509
- }
510
- }
511
- throw lastError || new Error(`Failed to fetch: ${url}`);
512
- }
513
- async function fetchRegistryData(urlOrPath) {
514
- if (urlOrPath.startsWith("http://") || urlOrPath.startsWith("https://")) {
515
- if (urlOrPath.startsWith("http://") && !urlOrPath.includes("localhost") && !urlOrPath.includes("127.0.0.1")) {
516
- logger.warn("Using insecure HTTP for registry. Consider switching to HTTPS.");
517
- }
518
- return fetchWithRetry(urlOrPath);
519
- }
520
- let cleanPath = urlOrPath;
521
- if (urlOrPath.startsWith("file://")) {
522
- cleanPath = fileURLToPath(urlOrPath);
523
- }
524
- cleanPath = path4.resolve(cleanPath);
525
- if (!fs4.existsSync(cleanPath)) {
526
- throw new Error(`Registry path not found: ${cleanPath}`);
527
- }
528
- logger.debug(`Reading local registry: ${cleanPath}`);
529
- return fs4.readFileSync(cleanPath, "utf-8");
530
- }
531
- async function fetchRegistryIndex() {
532
- const baseUrl = getRegistryBaseUrl();
533
- const url = baseUrl.endsWith("/") ? `${baseUrl}registry.json` : `${baseUrl}/registry.json`;
534
- const content = await fetchRegistryData(url);
535
- let raw;
536
- try {
537
- raw = JSON.parse(content);
538
- } catch {
539
- throw new Error("Failed to parse registry index \u2014 received invalid JSON.");
540
- }
541
- const result = RegistryIndexSchema.safeParse(raw);
542
- if (!result.success) {
543
- logger.debug(`Registry index validation errors: ${result.error.message}`);
544
- throw new Error("Registry index failed validation. The registry may be corrupted or incompatible with this CLI version.");
545
- }
546
- return result.data;
547
- }
548
- async function fetchComponent(slug) {
549
- validateSlug(slug);
550
- const baseUrl = getRegistryBaseUrl();
551
- const url = baseUrl.endsWith("/") ? `${baseUrl}${slug}.json` : `${baseUrl}/${slug}.json`;
552
- const content = await fetchRegistryData(url);
553
- let raw;
554
- try {
555
- raw = JSON.parse(content);
556
- } catch {
557
- throw new Error(`Failed to parse component "${slug}" \u2014 received invalid JSON.`);
558
- }
559
- const result = RegistryComponentSchema.safeParse(raw);
560
- if (!result.success) {
561
- const issues = result.error.issues.map((i) => ` \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
562
- logger.debug(`Component "${slug}" validation errors:
563
- ${issues}`);
564
- throw new Error(
565
- `Component "${slug}" failed validation. This may indicate an incompatible registry version. Try updating the CLI.`
566
- );
567
- }
568
- return result.data;
569
- }
570
-
571
- // src/commands/list.ts
572
145
  async function listCommand() {
573
146
  const spinner = ora({
574
147
  text: "Fetching components list...",
@@ -576,55 +149,55 @@ async function listCommand() {
576
149
  }).start();
577
150
  try {
578
151
  const registry = await fetchRegistryIndex();
579
- spinner.succeed(pc3.green("Fetched components list successfully!\n"));
152
+ spinner.succeed(pc2.green("Fetched components list successfully!\n"));
580
153
  if (registry.components.length === 0) {
581
- console.log(pc3.dim(" No components available in the registry yet."));
582
- console.log(pc3.dim(" Check back soon or visit https://vectorvesper.dev\n"));
154
+ console.log(pc2.dim(" No components available in the registry yet."));
155
+ console.log(pc2.dim(" Check back soon or visit https://vectorvesper.dev\n"));
583
156
  return;
584
157
  }
585
158
  const hasAuth = !!getAuthToken();
586
- console.log(pc3.bold(pc3.white("Vector Vesper Available Components:")));
587
- console.log(pc3.dim("--------------------------------------------------------------------------------"));
159
+ console.log(pc2.bold(pc2.white("Vector Vesper Available Components:")));
160
+ console.log(pc2.dim("--------------------------------------------------------------------------------"));
588
161
  for (const c of registry.components) {
589
- const slugCol = pc3.cyan(c.slug.padEnd(25));
590
- const categoryCol = pc3.yellow(c.category.padEnd(15));
162
+ const slugCol = pc2.cyan(c.slug.padEnd(25));
163
+ const categoryCol = pc2.yellow(c.category.padEnd(15));
591
164
  let tierBadge;
592
165
  if (c.tier === "pro") {
593
- tierBadge = hasAuth ? pc3.magenta("pro ") : pc3.dim("\u{1F512} ");
166
+ tierBadge = hasAuth ? pc2.magenta("pro ") : pc2.dim("\u{1F512} ");
594
167
  } else {
595
- tierBadge = pc3.green("free");
168
+ tierBadge = pc2.green("free");
596
169
  }
597
- console.log(`${slugCol} [${tierBadge}] ${categoryCol} ${pc3.gray(c.description)}`);
170
+ console.log(`${slugCol} [${tierBadge}] ${categoryCol} ${pc2.gray(c.description)}`);
598
171
  }
599
- console.log(pc3.dim("--------------------------------------------------------------------------------"));
172
+ console.log(pc2.dim("--------------------------------------------------------------------------------"));
600
173
  const freeCount = registry.components.filter((c) => c.tier === "free").length;
601
174
  const proCount = registry.components.filter((c) => c.tier === "pro").length;
602
175
  console.log(`
603
- ${pc3.green(String(freeCount))} free components${proCount > 0 ? ` \xB7 ${pc3.magenta(String(proCount))} pro components` : ""}`);
176
+ ${pc2.green(String(freeCount))} free components${proCount > 0 ? ` \xB7 ${pc2.magenta(String(proCount))} pro components` : ""}`);
604
177
  if (proCount > 0 && !hasAuth) {
605
- console.log(` \u{1F511} ${pc3.dim("Unlock pro components:")} ${pc3.cyan("npx vectorvesper login <key>")} ${pc3.dim("\xB7")} ${pc3.cyan("https://vectorvesper.dev/pricing")}`);
178
+ console.log(` \u{1F511} ${pc2.dim("Unlock pro components:")} ${pc2.cyan("npx vectorvesper login <key>")} ${pc2.dim("\xB7")} ${pc2.cyan("https://vectorvesper.dev/pricing")}`);
606
179
  }
607
180
  console.log(`
608
- \u{1F449} Run ${pc3.bold(pc3.cyan("npx vectorvesper add <slug>"))} to add a component to your project.
181
+ \u{1F449} Run ${pc2.bold(pc2.cyan("npx vectorvesper add <slug>"))} to add a component to your project.
609
182
  `);
610
183
  } catch (error) {
611
184
  const message = error instanceof Error ? error.message : String(error);
612
- spinner.fail(pc3.red(`Failed to fetch components list: ${message}`));
185
+ spinner.fail(pc2.red(`Failed to fetch components list: ${message}`));
613
186
  process.exit(1);
614
187
  }
615
188
  }
616
189
 
617
190
  // src/commands/add.ts
618
- import fs7 from "fs";
619
- import path7 from "path";
191
+ import fs4 from "fs";
192
+ import path4 from "path";
620
193
  import ora2 from "ora";
621
- import pc6 from "picocolors";
194
+ import pc5 from "picocolors";
622
195
  import { confirm as confirm2, isCancel as isCancel2 } from "@clack/prompts";
623
196
 
624
197
  // src/utils/installer.ts
625
- import fs5 from "fs";
626
- import path5 from "path";
627
- import pc4 from "picocolors";
198
+ import fs2 from "fs";
199
+ import path2 from "path";
200
+ import pc3 from "picocolors";
628
201
  var MAX_DEPTH = 20;
629
202
  function toForwardSlash(p) {
630
203
  return p.replace(/\\/g, "/");
@@ -644,8 +217,8 @@ async function resolveComponentTree(slug) {
644
217
  if (component.tier === "pro" && !getAuthToken()) {
645
218
  throw new Error(
646
219
  `"${componentSlug}" is a Pro component and requires a license.
647
- \u{1F449} Run ${pc4.cyan("npx vectorvesper login <your-license-key>")} to unlock pro components.
648
- \u{1F511} Get a license at ${pc4.cyan("https://vectorvesper.dev/pricing")}`
220
+ \u{1F449} Run ${pc3.cyan("npx vectorvesper login <your-license-key>")} to unlock pro components.
221
+ \u{1F511} Get a license at ${pc3.cyan("https://vectorvesper.dev/pricing")}`
649
222
  );
650
223
  }
651
224
  for (const depSlug of component.registryDependencies ?? []) {
@@ -658,12 +231,12 @@ async function resolveComponentTree(slug) {
658
231
  }
659
232
  function planFiles(components, installDir, projectRoot) {
660
233
  const planned = [];
661
- const compDir = path5.join(projectRoot, installDir);
234
+ const compDir = path2.join(projectRoot, installDir);
662
235
  for (const component of components) {
663
236
  for (const file of component.files) {
664
- const absolutePath = path5.resolve(compDir, file.target);
665
- const relativeFromRoot = path5.relative(projectRoot, absolutePath);
666
- if (relativeFromRoot.startsWith("..") || path5.isAbsolute(relativeFromRoot)) {
237
+ const absolutePath = path2.resolve(compDir, file.target);
238
+ const relativeFromRoot = path2.relative(projectRoot, absolutePath);
239
+ if (relativeFromRoot.startsWith("..") || path2.isAbsolute(relativeFromRoot)) {
667
240
  throw new Error(
668
241
  `Security Error: component target tries to escape project root: ${file.target}`
669
242
  );
@@ -673,7 +246,7 @@ function planFiles(components, installDir, projectRoot) {
673
246
  relativePath: relativeFromRoot,
674
247
  target: file.target,
675
248
  content: file.content,
676
- exists: fs5.existsSync(absolutePath)
249
+ exists: fs2.existsSync(absolutePath)
677
250
  });
678
251
  }
679
252
  }
@@ -681,28 +254,28 @@ function planFiles(components, installDir, projectRoot) {
681
254
  }
682
255
  function writeFiles(files) {
683
256
  for (const file of files) {
684
- const folder = path5.dirname(file.absolutePath);
685
- if (!fs5.existsSync(folder)) {
686
- fs5.mkdirSync(folder, { recursive: true });
257
+ const folder = path2.dirname(file.absolutePath);
258
+ if (!fs2.existsSync(folder)) {
259
+ fs2.mkdirSync(folder, { recursive: true });
687
260
  }
688
- fs5.writeFileSync(file.absolutePath, file.content, "utf-8");
261
+ fs2.writeFileSync(file.absolutePath, file.content, "utf-8");
689
262
  }
690
263
  }
691
264
  var MANIFEST_NAME = "vv-manifest.json";
692
265
  function getManifestPath(projectRoot) {
693
- return path5.join(projectRoot, MANIFEST_NAME);
266
+ return path2.join(projectRoot, MANIFEST_NAME);
694
267
  }
695
268
  function readManifest(projectRoot) {
696
269
  const manifestPath = getManifestPath(projectRoot);
697
- if (!fs5.existsSync(manifestPath)) {
270
+ if (!fs2.existsSync(manifestPath)) {
698
271
  return { components: {} };
699
272
  }
700
- const parsed = JSON.parse(fs5.readFileSync(manifestPath, "utf-8"));
273
+ const parsed = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
701
274
  if (!parsed.components) parsed.components = {};
702
275
  return parsed;
703
276
  }
704
277
  function writeManifest(projectRoot, manifest) {
705
- fs5.writeFileSync(getManifestPath(projectRoot), JSON.stringify(manifest, null, 2), "utf-8");
278
+ fs2.writeFileSync(getManifestPath(projectRoot), JSON.stringify(manifest, null, 2), "utf-8");
706
279
  }
707
280
  function recordInstall(components, installDir, projectRoot) {
708
281
  const manifest = readManifest(projectRoot);
@@ -710,7 +283,7 @@ function recordInstall(components, installDir, projectRoot) {
710
283
  for (const component of components) {
711
284
  manifest.components[component.slug] = {
712
285
  version: component.version,
713
- installedAt: toForwardSlash(path5.join(installDir, component.slug)),
286
+ installedAt: toForwardSlash(path2.join(installDir, component.slug)),
714
287
  installedOn: today,
715
288
  files: component.files.map((f) => f.target)
716
289
  };
@@ -718,7 +291,7 @@ function recordInstall(components, installDir, projectRoot) {
718
291
  writeManifest(projectRoot, manifest);
719
292
  }
720
293
  function findOrphanedFiles(components, installDir, projectRoot, previousManifest) {
721
- const compDir = path5.join(projectRoot, installDir);
294
+ const compDir = path2.join(projectRoot, installDir);
722
295
  const currentTargets = /* @__PURE__ */ new Set();
723
296
  for (const component of components) {
724
297
  for (const file of component.files) currentTargets.add(file.target);
@@ -732,10 +305,10 @@ function findOrphanedFiles(components, installDir, projectRoot, previousManifest
732
305
  if (currentTargets.has(target)) continue;
733
306
  if (seen.has(target)) continue;
734
307
  seen.add(target);
735
- const absolutePath = path5.resolve(compDir, target);
736
- const relativeFromRoot = path5.relative(projectRoot, absolutePath);
737
- if (relativeFromRoot.startsWith("..") || path5.isAbsolute(relativeFromRoot)) continue;
738
- if (!fs5.existsSync(absolutePath)) continue;
308
+ const absolutePath = path2.resolve(compDir, target);
309
+ const relativeFromRoot = path2.relative(projectRoot, absolutePath);
310
+ if (relativeFromRoot.startsWith("..") || path2.isAbsolute(relativeFromRoot)) continue;
311
+ if (!fs2.existsSync(absolutePath)) continue;
739
312
  orphans.push({ absolutePath, relativePath: relativeFromRoot, target });
740
313
  }
741
314
  }
@@ -743,26 +316,26 @@ function findOrphanedFiles(components, installDir, projectRoot, previousManifest
743
316
  }
744
317
  function removeFiles(files) {
745
318
  for (const file of files) {
746
- if (fs5.existsSync(file.absolutePath)) {
747
- fs5.rmSync(file.absolutePath, { force: true });
319
+ if (fs2.existsSync(file.absolutePath)) {
320
+ fs2.rmSync(file.absolutePath, { force: true });
748
321
  }
749
322
  }
750
323
  }
751
324
 
752
325
  // src/utils/install.ts
753
- import fs6 from "fs";
754
- import path6 from "path";
326
+ import fs3 from "fs";
327
+ import path3 from "path";
755
328
  import { spawnSync } from "child_process";
756
329
  var NPM_NAME_REGEX = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/i;
757
330
  function isValidPackageName(name) {
758
331
  return NPM_NAME_REGEX.test(name);
759
332
  }
760
333
  function getMissingDependencies(components, projectRoot) {
761
- const pkgPath = path6.join(projectRoot, "package.json");
762
- if (!fs6.existsSync(pkgPath)) return [];
334
+ const pkgPath = path3.join(projectRoot, "package.json");
335
+ if (!fs3.existsSync(pkgPath)) return [];
763
336
  let installed = {};
764
337
  try {
765
- const pkg = JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
338
+ const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
766
339
  installed = {
767
340
  ...pkg.dependencies,
768
341
  ...pkg.devDependencies,
@@ -807,7 +380,7 @@ function installDependencies(deps, pm, projectRoot) {
807
380
  }
808
381
 
809
382
  // src/utils/guidance.ts
810
- import pc5 from "picocolors";
383
+ import pc4 from "picocolors";
811
384
  function toPascalCase(input) {
812
385
  return input.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
813
386
  }
@@ -858,24 +431,24 @@ const ${varName} = dynamic(
858
431
  }
859
432
  function printGuidance(component, ctx) {
860
433
  const g = buildGuidance(component, ctx);
861
- console.log(pc5.bold(pc5.white(`
434
+ console.log(pc4.bold(pc4.white(`
862
435
  Using ${component.title || component.name}:`)));
863
436
  if (g.ssrSnippet) {
864
- console.log(pc5.dim(" // SSR-safe (Next.js) \u2014 disables server rendering for WebGL:"));
437
+ console.log(pc4.dim(" // SSR-safe (Next.js) \u2014 disables server rendering for WebGL:"));
865
438
  for (const line of g.ssrSnippet.split("\n")) {
866
- console.log(line ? ` ${pc5.cyan(line)}` : "");
439
+ console.log(line ? ` ${pc4.cyan(line)}` : "");
867
440
  }
868
441
  } else {
869
- console.log(` ${pc5.cyan(g.importSnippet)}`);
442
+ console.log(` ${pc4.cyan(g.importSnippet)}`);
870
443
  }
871
444
  for (const note of g.notes) {
872
- console.log(` ${pc5.green("\u2022")} ${pc5.dim(note)}`);
445
+ console.log(` ${pc4.green("\u2022")} ${pc4.dim(note)}`);
873
446
  }
874
447
  for (const warning of g.warnings) {
875
- console.log(` ${pc5.yellow("\u26A0")} ${pc5.yellow(warning)}`);
448
+ console.log(` ${pc4.yellow("\u26A0")} ${pc4.yellow(warning)}`);
876
449
  }
877
450
  if (g.docsUrl) {
878
- console.log(` ${pc5.dim("Docs:")} ${pc5.cyan(g.docsUrl)}`);
451
+ console.log(` ${pc4.dim("Docs:")} ${pc4.cyan(g.docsUrl)}`);
879
452
  }
880
453
  }
881
454
 
@@ -943,11 +516,11 @@ async function handleDependencies(components, projectRoot, projectInfo, options)
943
516
  const missing = getMissingDependencies(components, projectRoot);
944
517
  if (missing.length === 0) return;
945
518
  const installCmd = getInstallCommand(projectInfo.packageManager, missing);
946
- const depsLabel = missing.map((d) => pc6.cyan(d)).join(", ");
519
+ const depsLabel = missing.map((d) => pc5.cyan(d)).join(", ");
947
520
  if (options.install === false) {
948
- console.log(pc6.yellow(`
521
+ console.log(pc5.yellow(`
949
522
  \u26A0\uFE0F Missing dependencies: ${depsLabel}`));
950
- console.log(` Run: ${pc6.bold(pc6.cyan(installCmd))}`);
523
+ console.log(` Run: ${pc5.bold(pc5.cyan(installCmd))}`);
951
524
  return;
952
525
  }
953
526
  let shouldInstall = options.yes === true;
@@ -958,44 +531,44 @@ async function handleDependencies(components, projectRoot, projectInfo, options)
958
531
  initialValue: true
959
532
  });
960
533
  if (isCancel2(answer)) {
961
- console.log(pc6.dim(` Skipped. Run: ${pc6.cyan(installCmd)}`));
534
+ console.log(pc5.dim(` Skipped. Run: ${pc5.cyan(installCmd)}`));
962
535
  return;
963
536
  }
964
537
  shouldInstall = answer;
965
538
  }
966
539
  if (!shouldInstall) {
967
- console.log(pc6.dim(` Skipped. Run: ${pc6.cyan(installCmd)} when ready.`));
540
+ console.log(pc5.dim(` Skipped. Run: ${pc5.cyan(installCmd)} when ready.`));
968
541
  return;
969
542
  }
970
- console.log(pc6.dim(`
543
+ console.log(pc5.dim(`
971
544
  Installing dependencies with ${projectInfo.packageManager}...`));
972
545
  try {
973
546
  const ok = installDependencies(missing, projectInfo.packageManager, projectRoot);
974
547
  if (ok) {
975
- console.log(pc6.green(`\u2714 Dependencies installed.`));
548
+ console.log(pc5.green(`\u2714 Dependencies installed.`));
976
549
  } else {
977
- console.log(pc6.yellow(`\u26A0\uFE0F Dependency install did not complete. Run manually: ${pc6.cyan(installCmd)}`));
550
+ console.log(pc5.yellow(`\u26A0\uFE0F Dependency install did not complete. Run manually: ${pc5.cyan(installCmd)}`));
978
551
  }
979
552
  } catch (error) {
980
553
  const message = error instanceof Error ? error.message : String(error);
981
- console.log(pc6.yellow(`\u26A0\uFE0F ${message}`));
982
- console.log(` Run manually: ${pc6.bold(pc6.cyan(installCmd))}`);
554
+ console.log(pc5.yellow(`\u26A0\uFE0F ${message}`));
555
+ console.log(` Run manually: ${pc5.bold(pc5.cyan(installCmd))}`);
983
556
  }
984
557
  }
985
558
  async function handlePrune(orphans, slug, options) {
986
559
  if (orphans.length === 0) return;
987
- const list = orphans.map((o) => ` ${pc6.dim("\u2022")} ${pc6.cyan(o.relativePath)}`).join("\n");
560
+ const list = orphans.map((o) => ` ${pc5.dim("\u2022")} ${pc5.cyan(o.relativePath)}`).join("\n");
988
561
  let shouldPrune = options.prune === true;
989
562
  if (!shouldPrune) {
990
563
  console.log(
991
- pc6.yellow(
564
+ pc5.yellow(
992
565
  `
993
- \u{1F9F9} ${orphans.length} file(s) from a previous version of ${pc6.cyan(slug)} are no longer part of it:`
566
+ \u{1F9F9} ${orphans.length} file(s) from a previous version of ${pc5.cyan(slug)} are no longer part of it:`
994
567
  )
995
568
  );
996
569
  console.log(list);
997
570
  if (options.yes) {
998
- console.log(pc6.dim(` Re-run with ${pc6.cyan("--prune")} to remove them.`));
571
+ console.log(pc5.dim(` Re-run with ${pc5.cyan("--prune")} to remove them.`));
999
572
  return;
1000
573
  }
1001
574
  const answer = await confirm2({
@@ -1003,16 +576,16 @@ async function handlePrune(orphans, slug, options) {
1003
576
  initialValue: true
1004
577
  });
1005
578
  if (isCancel2(answer) || !answer) {
1006
- console.log(pc6.dim(` Left in place. Run with ${pc6.cyan("--prune")} later to remove them.`));
579
+ console.log(pc5.dim(` Left in place. Run with ${pc5.cyan("--prune")} later to remove them.`));
1007
580
  return;
1008
581
  }
1009
582
  shouldPrune = true;
1010
583
  }
1011
584
  removeFiles(orphans);
1012
- console.log(pc6.green(`
585
+ console.log(pc5.green(`
1013
586
  \u{1F9F9} Removed ${orphans.length} orphaned file(s):`));
1014
587
  for (const o of orphans) {
1015
- console.log(` ${pc6.red("\u2212")} ${pc6.cyan(o.relativePath)}`);
588
+ console.log(` ${pc5.red("\u2212")} ${pc5.cyan(o.relativePath)}`);
1016
589
  }
1017
590
  }
1018
591
  async function addCommand(slug, options = {}) {
@@ -1020,7 +593,7 @@ async function addCommand(slug, options = {}) {
1020
593
  validateSlug(slug);
1021
594
  } catch (error) {
1022
595
  const message = error instanceof Error ? error.message : String(error);
1023
- console.error(`${pc6.red(pc6.bold("Error:"))} ${message}`);
596
+ console.error(`${pc5.red(pc5.bold("Error:"))} ${message}`);
1024
597
  process.exit(1);
1025
598
  }
1026
599
  let config;
@@ -1028,13 +601,13 @@ async function addCommand(slug, options = {}) {
1028
601
  config = loadConfig();
1029
602
  } catch (error) {
1030
603
  const message = error instanceof Error ? error.message : String(error);
1031
- console.error(`${pc6.red(pc6.bold("Error:"))} ${message}`);
604
+ console.error(`${pc5.red(pc5.bold("Error:"))} ${message}`);
1032
605
  process.exit(1);
1033
606
  }
1034
607
  if (!config) {
1035
608
  console.error(
1036
- `${pc6.red(pc6.bold("Error:"))} No ${pc6.cyan("vv.config.json")} found in this directory.
1037
- \u{1F449} Run ${pc6.bold(pc6.cyan("npx vectorvesper init"))} first to set up your project.`
609
+ `${pc5.red(pc5.bold("Error:"))} No ${pc5.cyan("vv.config.json")} found in this directory.
610
+ \u{1F449} Run ${pc5.bold(pc5.cyan("npx vectorvesper init"))} first to set up your project.`
1038
611
  );
1039
612
  process.exit(1);
1040
613
  return;
@@ -1042,13 +615,13 @@ async function addCommand(slug, options = {}) {
1042
615
  const projectInfo = detectProject();
1043
616
  const componentInstallDir = resolveAlias(config.aliases.vv, projectInfo.hasSrcDir);
1044
617
  const projectRoot = process.cwd();
1045
- const spinner = ora2({ text: `Resolving component ${pc6.cyan(slug)}...`, color: "cyan" }).start();
618
+ const spinner = ora2({ text: `Resolving component ${pc5.cyan(slug)}...`, color: "cyan" }).start();
1046
619
  let resolvedComponents;
1047
620
  try {
1048
621
  resolvedComponents = await resolveComponentTree(slug);
1049
622
  } catch (error) {
1050
623
  const message = error instanceof Error ? error.message : String(error);
1051
- spinner.fail(pc6.red(`Failed to resolve component "${slug}": ${message}`));
624
+ spinner.fail(pc5.red(`Failed to resolve component "${slug}": ${message}`));
1052
625
  process.exit(1);
1053
626
  return;
1054
627
  }
@@ -1070,7 +643,7 @@ async function addCommand(slug, options = {}) {
1070
643
  planned = planFiles(resolvedComponents, componentInstallDir, projectRoot);
1071
644
  } catch (error) {
1072
645
  const message = error instanceof Error ? error.message : String(error);
1073
- spinner.fail(pc6.red(message));
646
+ spinner.fail(pc5.red(message));
1074
647
  process.exit(1);
1075
648
  return;
1076
649
  }
@@ -1079,11 +652,11 @@ async function addCommand(slug, options = {}) {
1079
652
  if (file.exists && !options.dryRun && !options.overwrite && !options.yes) {
1080
653
  spinner.stop();
1081
654
  const answer = await confirm2({
1082
- message: pc6.yellow(`File already exists: "${file.relativePath}". Overwrite?`),
655
+ message: pc5.yellow(`File already exists: "${file.relativePath}". Overwrite?`),
1083
656
  initialValue: false
1084
657
  });
1085
658
  if (isCancel2(answer) || !answer) {
1086
- console.log(pc6.dim(` Skipping existing file: ${file.relativePath}`));
659
+ console.log(pc5.dim(` Skipping existing file: ${file.relativePath}`));
1087
660
  spinner.start("Continuing installation...");
1088
661
  continue;
1089
662
  }
@@ -1096,7 +669,7 @@ async function addCommand(slug, options = {}) {
1096
669
  });
1097
670
  }
1098
671
  const targetComponent = resolvedComponents[resolvedComponents.length - 1];
1099
- const installPath = toForwardSlash(path7.join(componentInstallDir, targetComponent.slug));
672
+ const installPath = toForwardSlash(path4.join(componentInstallDir, targetComponent.slug));
1100
673
  let orphans = [];
1101
674
  try {
1102
675
  const previousManifest = readManifest(projectRoot);
@@ -1105,32 +678,32 @@ async function addCommand(slug, options = {}) {
1105
678
  orphans = [];
1106
679
  }
1107
680
  if (options.dryRun) {
1108
- spinner.succeed(pc6.yellow("Dry-run: simulation completed. No files were written."));
1109
- console.log(pc6.bold(pc6.yellow("\n[Dry Run] Files that would be created/modified:")));
681
+ spinner.succeed(pc5.yellow("Dry-run: simulation completed. No files were written."));
682
+ console.log(pc5.bold(pc5.yellow("\n[Dry Run] Files that would be created/modified:")));
1110
683
  for (const file of filesToWrite) {
1111
- const status = fs7.existsSync(file.absolutePath) ? pc6.yellow("(exists, would overwrite)") : pc6.green("(new)");
1112
- console.log(` ${pc6.cyan(file.relativePath)} ${status}`);
684
+ const status = fs4.existsSync(file.absolutePath) ? pc5.yellow("(exists, would overwrite)") : pc5.green("(new)");
685
+ console.log(` ${pc5.cyan(file.relativePath)} ${status}`);
1113
686
  }
1114
687
  if (orphans.length > 0) {
1115
- console.log(pc6.bold(pc6.yellow("\n[Dry Run] Orphaned files from a previous version:")));
688
+ console.log(pc5.bold(pc5.yellow("\n[Dry Run] Orphaned files from a previous version:")));
1116
689
  for (const o of orphans) {
1117
- const note = options.prune ? pc6.red("(would remove)") : pc6.dim("(use --prune to remove)");
1118
- console.log(` ${pc6.cyan(o.relativePath)} ${note}`);
690
+ const note = options.prune ? pc5.red("(would remove)") : pc5.dim("(use --prune to remove)");
691
+ console.log(` ${pc5.cyan(o.relativePath)} ${note}`);
1119
692
  }
1120
693
  }
1121
694
  const missing = getMissingDependencies(resolvedComponents, projectRoot);
1122
695
  if (missing.length > 0) {
1123
- console.log(pc6.yellow(`
1124
- \u26A0\uFE0F Would need dependencies: ${missing.map((d) => pc6.cyan(d)).join(", ")}`));
1125
- console.log(` ${pc6.dim(getInstallCommand(projectInfo.packageManager, missing))}`);
696
+ console.log(pc5.yellow(`
697
+ \u26A0\uFE0F Would need dependencies: ${missing.map((d) => pc5.cyan(d)).join(", ")}`));
698
+ console.log(` ${pc5.dim(getInstallCommand(projectInfo.packageManager, missing))}`);
1126
699
  }
1127
700
  console.log("");
1128
- console.log(pc6.bold(pc6.yellow(`\u2714 [Dry Run] Would add ${pc6.cyan(targetComponent.slug)} to ${installPath}`)));
701
+ console.log(pc5.bold(pc5.yellow(`\u2714 [Dry Run] Would add ${pc5.cyan(targetComponent.slug)} to ${installPath}`)));
1129
702
  console.log("");
1130
703
  return;
1131
704
  }
1132
705
  if (filesToWrite.length === 0) {
1133
- spinner.succeed(pc6.green("All files skipped (already up to date)."));
706
+ spinner.succeed(pc5.green("All files skipped (already up to date)."));
1134
707
  await handlePrune(orphans, targetComponent.slug, options);
1135
708
  return;
1136
709
  }
@@ -1139,7 +712,7 @@ async function addCommand(slug, options = {}) {
1139
712
  writeFiles(filesToWrite);
1140
713
  } catch (error) {
1141
714
  const message = error instanceof Error ? error.message : String(error);
1142
- spinner.fail(pc6.red(`Failed to write files: ${message}`));
715
+ spinner.fail(pc5.red(`Failed to write files: ${message}`));
1143
716
  process.exit(1);
1144
717
  return;
1145
718
  }
@@ -1150,10 +723,10 @@ async function addCommand(slug, options = {}) {
1150
723
  logger.warn(`Failed to update vv-manifest.json: ${message}`);
1151
724
  logger.warn("Component was installed but may not appear in 'npx vectorvesper info' or 'npx vectorvesper diff'.");
1152
725
  }
1153
- spinner.succeed(pc6.green("Files written successfully!"));
1154
- console.log(pc6.dim("\nCreated files:"));
726
+ spinner.succeed(pc5.green("Files written successfully!"));
727
+ console.log(pc5.dim("\nCreated files:"));
1155
728
  for (const file of filesToWrite) {
1156
- console.log(` ${pc6.green("\u2714")} ${pc6.cyan(file.relativePath)}`);
729
+ console.log(` ${pc5.green("\u2714")} ${pc5.cyan(file.relativePath)}`);
1157
730
  }
1158
731
  await handlePrune(orphans, targetComponent.slug, options);
1159
732
  await handleDependencies(resolvedComponents, projectRoot, projectInfo, options);
@@ -1163,20 +736,20 @@ async function addCommand(slug, options = {}) {
1163
736
  hasTailwind: projectInfo.hasTailwind
1164
737
  });
1165
738
  if (transpileWarnings.length > 0) {
1166
- console.log(pc6.yellow(`
739
+ console.log(pc5.yellow(`
1167
740
  \u26A0\uFE0F Some files were kept as TypeScript:`));
1168
- for (const w of transpileWarnings) console.log(` ${pc6.dim(w)}`);
741
+ for (const w of transpileWarnings) console.log(` ${pc5.dim(w)}`);
1169
742
  }
1170
743
  console.log("");
1171
- console.log(pc6.bold(pc6.green(`\u2714 Added ${pc6.cyan(targetComponent.slug)} to ${installPath}`)));
744
+ console.log(pc5.bold(pc5.green(`\u2714 Added ${pc5.cyan(targetComponent.slug)} to ${installPath}`)));
1172
745
  console.log("");
1173
- console.log(pc6.gray("\u{1F449} Loving Vector Vesper? Star the repo: https://github.com/vectorvesper/vv-components"));
1174
- console.log(pc6.gray("\u{1F680} Premium shader & pixel systems: https://vectorvesper.dev/pricing"));
746
+ console.log(pc5.gray("\u{1F449} Loving Vector Vesper? Star the repo: https://github.com/vectorvesper/vv-components"));
747
+ console.log(pc5.gray("\u{1F680} Premium shader & pixel systems: https://vectorvesper.dev/pricing"));
1175
748
  console.log("");
1176
749
  }
1177
750
 
1178
751
  // src/commands/update.ts
1179
- import pc7 from "picocolors";
752
+ import pc6 from "picocolors";
1180
753
  import ora3 from "ora";
1181
754
  async function updateCommand(slug, options = {}) {
1182
755
  const projectRoot = process.cwd();
@@ -1185,14 +758,14 @@ async function updateCommand(slug, options = {}) {
1185
758
  config = loadConfig();
1186
759
  } catch (error) {
1187
760
  const message = error instanceof Error ? error.message : String(error);
1188
- console.error(`${pc7.red(pc7.bold("Error:"))} ${message}`);
761
+ console.error(`${pc6.red(pc6.bold("Error:"))} ${message}`);
1189
762
  process.exit(1);
1190
763
  return;
1191
764
  }
1192
765
  if (!config) {
1193
766
  console.error(
1194
- `${pc7.red(pc7.bold("Error:"))} No ${pc7.cyan("vv.config.json")} found.
1195
- \u{1F449} Run ${pc7.bold(pc7.cyan("npx vectorvesper init"))} first.`
767
+ `${pc6.red(pc6.bold("Error:"))} No ${pc6.cyan("vv.config.json")} found.
768
+ \u{1F449} Run ${pc6.bold(pc6.cyan("npx vectorvesper init"))} first.`
1196
769
  );
1197
770
  process.exit(1);
1198
771
  return;
@@ -1202,9 +775,9 @@ async function updateCommand(slug, options = {}) {
1202
775
  const manifest = readManifest(projectRoot);
1203
776
  const installedSlugs = Object.keys(manifest.components);
1204
777
  if (installedSlugs.length === 0) {
1205
- console.log(pc7.yellow(`
778
+ console.log(pc6.yellow(`
1206
779
  \u26A0\uFE0F No components are installed in this project.`));
1207
- console.log(`\u{1F449} Add one with ${pc7.bold(pc7.cyan("npx vectorvesper add <slug>"))}
780
+ console.log(`\u{1F449} Add one with ${pc6.bold(pc6.cyan("npx vectorvesper add <slug>"))}
1208
781
  `);
1209
782
  return;
1210
783
  }
@@ -1214,16 +787,16 @@ async function updateCommand(slug, options = {}) {
1214
787
  validateSlug(slug);
1215
788
  } catch (error) {
1216
789
  const message = error instanceof Error ? error.message : String(error);
1217
- console.error(pc7.red(`
790
+ console.error(pc6.red(`
1218
791
  \u274C ${message}
1219
792
  `));
1220
793
  process.exit(1);
1221
794
  return;
1222
795
  }
1223
796
  if (!manifest.components[slug]) {
1224
- console.log(pc7.red(`
797
+ console.log(pc6.red(`
1225
798
  \u274C Component "${slug}" is not installed in this project.`));
1226
- console.log(`\u{1F449} Run ${pc7.cyan(`npx vectorvesper add ${slug}`)} to install it.
799
+ console.log(`\u{1F449} Run ${pc6.cyan(`npx vectorvesper add ${slug}`)} to install it.
1227
800
  `);
1228
801
  return;
1229
802
  }
@@ -1238,7 +811,7 @@ async function updateCommand(slug, options = {}) {
1238
811
  const updatedComponents = [];
1239
812
  const transpileWarnings = [];
1240
813
  for (const target of targets) {
1241
- spinner.text = `Updating ${pc7.cyan(target)}...`;
814
+ spinner.text = `Updating ${pc6.cyan(target)}...`;
1242
815
  try {
1243
816
  let components = await resolveComponentTree(target);
1244
817
  const remote = components[components.length - 1];
@@ -1268,26 +841,26 @@ async function updateCommand(slug, options = {}) {
1268
841
  }
1269
842
  }
1270
843
  spinner.stop();
1271
- console.log(pc7.bold(pc7.cyan("\nVector Vesper Update\n")));
844
+ console.log(pc6.bold(pc6.cyan("\nVector Vesper Update\n")));
1272
845
  if (updated.length > 0) {
1273
- console.log(pc7.bold(pc7.green(` Updated (${updated.length}):`)));
1274
- for (const u of updated) console.log(` ${pc7.green("\u2714")} ${u}`);
1275
- console.log(pc7.dim(" Note: updating overwrites local edits to these files."));
846
+ console.log(pc6.bold(pc6.green(` Updated (${updated.length}):`)));
847
+ for (const u of updated) console.log(` ${pc6.green("\u2714")} ${u}`);
848
+ console.log(pc6.dim(" Note: updating overwrites local edits to these files."));
1276
849
  }
1277
850
  if (upToDate.length > 0) {
1278
- console.log(pc7.bold(pc7.gray(`
851
+ console.log(pc6.bold(pc6.gray(`
1279
852
  Already up to date (${upToDate.length}):`)));
1280
- console.log(` ${pc7.dim(upToDate.join(", "))}`);
853
+ console.log(` ${pc6.dim(upToDate.join(", "))}`);
1281
854
  }
1282
855
  if (failed.length > 0) {
1283
- console.log(pc7.bold(pc7.red(`
856
+ console.log(pc6.bold(pc6.red(`
1284
857
  Failed (${failed.length}):`)));
1285
- for (const f of failed) console.log(` ${pc7.red("\u2716")} ${f.slug}: ${pc7.dim(f.reason)}`);
858
+ for (const f of failed) console.log(` ${pc6.red("\u2716")} ${f.slug}: ${pc6.dim(f.reason)}`);
1286
859
  }
1287
860
  if (transpileWarnings.length > 0) {
1288
- console.log(pc7.yellow(`
861
+ console.log(pc6.yellow(`
1289
862
  \u26A0\uFE0F Some files were kept as TypeScript:`));
1290
- for (const w of transpileWarnings) console.log(` ${pc7.dim(w)}`);
863
+ for (const w of transpileWarnings) console.log(` ${pc6.dim(w)}`);
1291
864
  }
1292
865
  console.log("");
1293
866
  if (updatedComponents.length > 0) {
@@ -1297,16 +870,16 @@ async function updateCommand(slug, options = {}) {
1297
870
  }
1298
871
 
1299
872
  // src/commands/remove.ts
1300
- import fs8 from "fs";
1301
- import path8 from "path";
1302
- import pc8 from "picocolors";
873
+ import fs5 from "fs";
874
+ import path5 from "path";
875
+ import pc7 from "picocolors";
1303
876
  import { confirm as confirm3, isCancel as isCancel3 } from "@clack/prompts";
1304
877
  async function removeCommand(slug, options = {}) {
1305
878
  try {
1306
879
  validateSlug(slug);
1307
880
  } catch (error) {
1308
881
  const message = error instanceof Error ? error.message : String(error);
1309
- console.error(`${pc8.red(pc8.bold("Error:"))} ${message}`);
882
+ console.error(`${pc7.red(pc7.bold("Error:"))} ${message}`);
1310
883
  process.exit(1);
1311
884
  return;
1312
885
  }
@@ -1316,14 +889,14 @@ async function removeCommand(slug, options = {}) {
1316
889
  config = loadConfig();
1317
890
  } catch (error) {
1318
891
  const message = error instanceof Error ? error.message : String(error);
1319
- console.error(`${pc8.red(pc8.bold("Error:"))} ${message}`);
892
+ console.error(`${pc7.red(pc7.bold("Error:"))} ${message}`);
1320
893
  process.exit(1);
1321
894
  return;
1322
895
  }
1323
896
  if (!config) {
1324
897
  console.error(
1325
- `${pc8.red(pc8.bold("Error:"))} No ${pc8.cyan("vv.config.json")} found.
1326
- \u{1F449} Run ${pc8.bold(pc8.cyan("npx vectorvesper init"))} first.`
898
+ `${pc7.red(pc7.bold("Error:"))} No ${pc7.cyan("vv.config.json")} found.
899
+ \u{1F449} Run ${pc7.bold(pc7.cyan("npx vectorvesper init"))} first.`
1327
900
  );
1328
901
  process.exit(1);
1329
902
  return;
@@ -1331,50 +904,50 @@ async function removeCommand(slug, options = {}) {
1331
904
  const manifest = readManifest(projectRoot);
1332
905
  const entry = manifest.components[slug];
1333
906
  if (!entry) {
1334
- console.log(pc8.yellow(`
907
+ console.log(pc7.yellow(`
1335
908
  \u26A0\uFE0F Component "${slug}" is not installed (not in vv-manifest.json).`));
1336
- console.log(`\u{1F449} See installed components with ${pc8.bold(pc8.cyan("npx vectorvesper info"))}
909
+ console.log(`\u{1F449} See installed components with ${pc7.bold(pc7.cyan("npx vectorvesper info"))}
1337
910
  `);
1338
911
  return;
1339
912
  }
1340
913
  const projectInfo = detectProject();
1341
914
  const installDir = resolveAlias(config.aliases.vv, projectInfo.hasSrcDir);
1342
- const baseDir = path8.join(projectRoot, installDir);
915
+ const baseDir = path5.join(projectRoot, installDir);
1343
916
  const targets = entry.files ?? [];
1344
- const absoluteFiles = targets.map((t) => path8.resolve(baseDir, t));
1345
- console.log(pc8.bold(pc8.cyan(`
917
+ const absoluteFiles = targets.map((t) => path5.resolve(baseDir, t));
918
+ console.log(pc7.bold(pc7.cyan(`
1346
919
  Remove ${slug}
1347
920
  `)));
1348
- console.log(pc8.dim(" The following files will be deleted:"));
921
+ console.log(pc7.dim(" The following files will be deleted:"));
1349
922
  for (const f of absoluteFiles) {
1350
- console.log(` ${fs8.existsSync(f) ? pc8.red("\u2212") : pc8.dim("\xB7")} ${pc8.cyan(path8.relative(projectRoot, f))}`);
923
+ console.log(` ${fs5.existsSync(f) ? pc7.red("\u2212") : pc7.dim("\xB7")} ${pc7.cyan(path5.relative(projectRoot, f))}`);
1351
924
  }
1352
925
  if (!options.yes) {
1353
926
  const answer = await confirm3({
1354
- message: pc8.yellow(`Delete ${absoluteFiles.length} file(s) for "${slug}"?`),
927
+ message: pc7.yellow(`Delete ${absoluteFiles.length} file(s) for "${slug}"?`),
1355
928
  initialValue: false
1356
929
  });
1357
930
  if (isCancel3(answer) || !answer) {
1358
- console.log(pc8.dim("\n Cancelled. Nothing was removed.\n"));
931
+ console.log(pc7.dim("\n Cancelled. Nothing was removed.\n"));
1359
932
  return;
1360
933
  }
1361
934
  }
1362
935
  let deleted = 0;
1363
936
  for (const f of absoluteFiles) {
1364
937
  try {
1365
- if (fs8.existsSync(f)) {
1366
- fs8.rmSync(f);
938
+ if (fs5.existsSync(f)) {
939
+ fs5.rmSync(f);
1367
940
  deleted++;
1368
941
  }
1369
942
  } catch (error) {
1370
943
  const message = error instanceof Error ? error.message : String(error);
1371
- console.log(pc8.yellow(` \u26A0\uFE0F Could not delete ${path8.relative(projectRoot, f)}: ${message}`));
944
+ console.log(pc7.yellow(` \u26A0\uFE0F Could not delete ${path5.relative(projectRoot, f)}: ${message}`));
1372
945
  }
1373
946
  }
1374
- const componentDir = path8.resolve(baseDir, slug);
947
+ const componentDir = path5.resolve(baseDir, slug);
1375
948
  try {
1376
- if (fs8.existsSync(componentDir) && fs8.readdirSync(componentDir).length === 0) {
1377
- fs8.rmdirSync(componentDir);
949
+ if (fs5.existsSync(componentDir) && fs5.readdirSync(componentDir).length === 0) {
950
+ fs5.rmdirSync(componentDir);
1378
951
  }
1379
952
  } catch {
1380
953
  }
@@ -1383,23 +956,23 @@ Remove ${slug}
1383
956
  writeManifest(projectRoot, manifest);
1384
957
  } catch (error) {
1385
958
  const message = error instanceof Error ? error.message : String(error);
1386
- console.log(pc8.yellow(` \u26A0\uFE0F Removed files but failed to update vv-manifest.json: ${message}`));
959
+ console.log(pc7.yellow(` \u26A0\uFE0F Removed files but failed to update vv-manifest.json: ${message}`));
1387
960
  }
1388
961
  console.log("");
1389
- console.log(pc8.bold(pc8.green(`\u2714 Removed ${pc8.cyan(slug)} (${deleted} file(s) deleted).`)));
962
+ console.log(pc7.bold(pc7.green(`\u2714 Removed ${pc7.cyan(slug)} (${deleted} file(s) deleted).`)));
1390
963
  if ((entry.files ?? []).length === 0) {
1391
- console.log(pc8.dim(" No files were tracked for this component; manifest entry cleared."));
964
+ console.log(pc7.dim(" No files were tracked for this component; manifest entry cleared."));
1392
965
  }
1393
966
  console.log("");
1394
967
  }
1395
968
 
1396
969
  // src/commands/info.ts
1397
- import fs9 from "fs";
1398
- import path9 from "path";
1399
- import pc9 from "picocolors";
1400
- var CLI_VERSION = true ? "1.2.0" : "0.0.0-dev";
970
+ import fs6 from "fs";
971
+ import path6 from "path";
972
+ import pc8 from "picocolors";
973
+ var CLI_VERSION = true ? "2.0.1" : "0.0.0-dev";
1401
974
  async function infoCommand() {
1402
- console.log(pc9.bold(pc9.cyan("\nVector Vesper Diagnostics\n")));
975
+ console.log(pc8.bold(pc8.cyan("\nVector Vesper Diagnostics\n")));
1403
976
  const projectInfo = detectProject();
1404
977
  let config;
1405
978
  try {
@@ -1407,84 +980,84 @@ async function infoCommand() {
1407
980
  } catch {
1408
981
  config = null;
1409
982
  }
1410
- console.log(pc9.bold(pc9.white("Environment:")));
1411
- console.log(` \u2022 CLI Version: ${pc9.cyan(CLI_VERSION)}`);
1412
- console.log(` \u2022 Node Version: ${pc9.cyan(process.version)}`);
1413
- console.log(` \u2022 OS: ${pc9.cyan(`${process.platform} ${process.arch}`)}`);
1414
- console.log(` \u2022 Package Manager: ${pc9.cyan(projectInfo.packageManager)}`);
1415
- console.log(` \u2022 Framework: ${pc9.cyan(projectInfo.framework)}`);
1416
- console.log(` \u2022 TypeScript: ${pc9.cyan(projectInfo.isTypeScript ? "Yes" : "No")}`);
1417
- console.log(` \u2022 Has src/ folder: ${pc9.cyan(projectInfo.hasSrcDir ? "Yes" : "No")}`);
1418
- console.log(` \u2022 Tailwind CSS: ${pc9.cyan(projectInfo.hasTailwind ? "Yes" : "No")}`);
983
+ console.log(pc8.bold(pc8.white("Environment:")));
984
+ console.log(` \u2022 CLI Version: ${pc8.cyan(CLI_VERSION)}`);
985
+ console.log(` \u2022 Node Version: ${pc8.cyan(process.version)}`);
986
+ console.log(` \u2022 OS: ${pc8.cyan(`${process.platform} ${process.arch}`)}`);
987
+ console.log(` \u2022 Package Manager: ${pc8.cyan(projectInfo.packageManager)}`);
988
+ console.log(` \u2022 Framework: ${pc8.cyan(projectInfo.framework)}`);
989
+ console.log(` \u2022 TypeScript: ${pc8.cyan(projectInfo.isTypeScript ? "Yes" : "No")}`);
990
+ console.log(` \u2022 Has src/ folder: ${pc8.cyan(projectInfo.hasSrcDir ? "Yes" : "No")}`);
991
+ console.log(` \u2022 Tailwind CSS: ${pc8.cyan(projectInfo.hasTailwind ? "Yes" : "No")}`);
1419
992
  console.log("");
1420
- console.log(pc9.bold(pc9.white("Configuration (vv.config.json):")));
993
+ console.log(pc8.bold(pc8.white("Configuration (vv.config.json):")));
1421
994
  if (config) {
1422
- console.log(` \u2022 Framework Set: ${pc9.cyan(config.framework)}`);
1423
- console.log(` \u2022 TypeScript Set: ${pc9.cyan(config.tsx ? "Yes" : "No")}`);
1424
- console.log(` \u2022 Component Alias: ${pc9.cyan(config.aliases.vv)}`);
995
+ console.log(` \u2022 Framework Set: ${pc8.cyan(config.framework)}`);
996
+ console.log(` \u2022 TypeScript Set: ${pc8.cyan(config.tsx ? "Yes" : "No")}`);
997
+ console.log(` \u2022 Component Alias: ${pc8.cyan(config.aliases.vv)}`);
1425
998
  } else {
1426
- console.log(` ${pc9.yellow("\u26A0\uFE0F No vv.config.json found in this directory.")}`);
999
+ console.log(` ${pc8.yellow("\u26A0\uFE0F No vv.config.json found in this directory.")}`);
1427
1000
  }
1428
1001
  console.log("");
1429
- console.log(pc9.bold(pc9.white("Installed Components (vv-manifest.json):")));
1430
- const manifestPath = path9.join(process.cwd(), "vv-manifest.json");
1431
- if (fs9.existsSync(manifestPath)) {
1002
+ console.log(pc8.bold(pc8.white("Installed Components (vv-manifest.json):")));
1003
+ const manifestPath = path6.join(process.cwd(), "vv-manifest.json");
1004
+ if (fs6.existsSync(manifestPath)) {
1432
1005
  try {
1433
- const manifest = JSON.parse(fs9.readFileSync(manifestPath, "utf-8"));
1006
+ const manifest = JSON.parse(fs6.readFileSync(manifestPath, "utf-8"));
1434
1007
  const components = manifest.components || {};
1435
1008
  const slugs = Object.keys(components);
1436
1009
  if (slugs.length === 0) {
1437
- console.log(` ${pc9.dim("No components installed yet.")}`);
1010
+ console.log(` ${pc8.dim("No components installed yet.")}`);
1438
1011
  } else {
1439
- console.log(pc9.dim(" ------------------------------------------------------------"));
1440
- console.log(` ${pc9.bold(pc9.white("Component".padEnd(25)))} ${pc9.bold(pc9.white("Version".padEnd(10)))} ${pc9.bold(pc9.white("Installed At"))}`);
1441
- console.log(pc9.dim(" ------------------------------------------------------------"));
1012
+ console.log(pc8.dim(" ------------------------------------------------------------"));
1013
+ console.log(` ${pc8.bold(pc8.white("Component".padEnd(25)))} ${pc8.bold(pc8.white("Version".padEnd(10)))} ${pc8.bold(pc8.white("Installed At"))}`);
1014
+ console.log(pc8.dim(" ------------------------------------------------------------"));
1442
1015
  for (const slug of slugs) {
1443
1016
  const info = components[slug];
1444
1017
  const version2 = info?.version ?? "unknown";
1445
1018
  const installedAt = info?.installedAt ?? "unknown";
1446
- console.log(` ${pc9.cyan(slug.padEnd(25))} ${pc9.green(version2.padEnd(10))} ${pc9.gray(installedAt)}`);
1019
+ console.log(` ${pc8.cyan(slug.padEnd(25))} ${pc8.green(version2.padEnd(10))} ${pc8.gray(installedAt)}`);
1447
1020
  }
1448
- console.log(pc9.dim(" ------------------------------------------------------------"));
1021
+ console.log(pc8.dim(" ------------------------------------------------------------"));
1449
1022
  }
1450
1023
  } catch {
1451
- console.log(` ${pc9.red("\u274C Error reading vv-manifest.json: Invalid JSON format.")}`);
1024
+ console.log(` ${pc8.red("\u274C Error reading vv-manifest.json: Invalid JSON format.")}`);
1452
1025
  }
1453
1026
  } else {
1454
- console.log(` ${pc9.dim("No components installed yet (vv-manifest.json not found).")}`);
1027
+ console.log(` ${pc8.dim("No components installed yet (vv-manifest.json not found).")}`);
1455
1028
  }
1456
1029
  console.log("");
1457
1030
  }
1458
1031
 
1459
1032
  // src/commands/diff.ts
1460
- import fs10 from "fs";
1461
- import path10 from "path";
1462
- import pc10 from "picocolors";
1033
+ import fs7 from "fs";
1034
+ import path7 from "path";
1035
+ import pc9 from "picocolors";
1463
1036
  import ora4 from "ora";
1464
1037
  async function diffCommand(slug) {
1465
1038
  const projectRoot = process.cwd();
1466
- const manifestPath = path10.join(projectRoot, "vv-manifest.json");
1467
- if (!fs10.existsSync(manifestPath)) {
1468
- console.log(pc10.yellow(`
1039
+ const manifestPath = path7.join(projectRoot, "vv-manifest.json");
1040
+ if (!fs7.existsSync(manifestPath)) {
1041
+ console.log(pc9.yellow(`
1469
1042
  \u26A0\uFE0F No vv-manifest.json found in this directory.`));
1470
- console.log(`\u{1F449} Add components first using ${pc10.bold(pc10.cyan("npx vectorvesper add <slug>"))}
1043
+ console.log(`\u{1F449} Add components first using ${pc9.bold(pc9.cyan("npx vectorvesper add <slug>"))}
1471
1044
  `);
1472
1045
  return;
1473
1046
  }
1474
1047
  let manifest;
1475
1048
  try {
1476
- manifest = JSON.parse(fs10.readFileSync(manifestPath, "utf-8"));
1049
+ manifest = JSON.parse(fs7.readFileSync(manifestPath, "utf-8"));
1477
1050
  } catch {
1478
- console.error(pc10.red(`\u274C Error reading vv-manifest.json: Invalid JSON format.`));
1051
+ console.error(pc9.red(`\u274C Error reading vv-manifest.json: Invalid JSON format.`));
1479
1052
  process.exit(1);
1480
1053
  return;
1481
1054
  }
1482
1055
  const installedComponents = manifest.components || {};
1483
1056
  const installedSlugs = Object.keys(installedComponents);
1484
1057
  if (installedSlugs.length === 0) {
1485
- console.log(pc10.yellow(`
1058
+ console.log(pc9.yellow(`
1486
1059
  \u26A0\uFE0F No components are registered as installed in vv-manifest.json.`));
1487
- console.log(`\u{1F449} Add components using ${pc10.bold(pc10.cyan("npx vectorvesper add <slug>"))}
1060
+ console.log(`\u{1F449} Add components using ${pc9.bold(pc9.cyan("npx vectorvesper add <slug>"))}
1488
1061
  `);
1489
1062
  return;
1490
1063
  }
@@ -1493,21 +1066,21 @@ async function diffCommand(slug) {
1493
1066
  validateSlug(slug);
1494
1067
  } catch (error) {
1495
1068
  const message = error instanceof Error ? error.message : String(error);
1496
- console.error(pc10.red(`
1069
+ console.error(pc9.red(`
1497
1070
  \u274C ${message}
1498
1071
  `));
1499
1072
  process.exit(1);
1500
1073
  }
1501
1074
  if (!installedComponents[slug]) {
1502
- console.log(pc10.red(`
1075
+ console.log(pc9.red(`
1503
1076
  \u274C Component "${slug}" is not installed in this project.`));
1504
- console.log(`\u{1F449} Run ${pc10.cyan(`npx vectorvesper add ${slug}`)} to install it.
1077
+ console.log(`\u{1F449} Run ${pc9.cyan(`npx vectorvesper add ${slug}`)} to install it.
1505
1078
  `);
1506
1079
  return;
1507
1080
  }
1508
1081
  const localInfo = installedComponents[slug];
1509
1082
  const spinner = ora4({
1510
- text: `Checking updates for ${pc10.cyan(slug)}...`,
1083
+ text: `Checking updates for ${pc9.cyan(slug)}...`,
1511
1084
  color: "cyan"
1512
1085
  }).start();
1513
1086
  try {
@@ -1515,21 +1088,21 @@ async function diffCommand(slug) {
1515
1088
  spinner.stop();
1516
1089
  const localVersion = localInfo.version ?? "unknown";
1517
1090
  const remoteVersion = remoteComponent.version;
1518
- console.log(pc10.bold(pc10.cyan(`
1091
+ console.log(pc9.bold(pc9.cyan(`
1519
1092
  Component Diff: ${slug}`)));
1520
- console.log(` \u2022 Local version: ${pc10.yellow(localVersion)}`);
1521
- console.log(` \u2022 Latest version: ${pc10.green(remoteVersion)}`);
1093
+ console.log(` \u2022 Local version: ${pc9.yellow(localVersion)}`);
1094
+ console.log(` \u2022 Latest version: ${pc9.green(remoteVersion)}`);
1522
1095
  if (localVersion === remoteVersion) {
1523
- console.log(` \u2022 Status: ${pc10.green("\u2714 Up to date")}
1096
+ console.log(` \u2022 Status: ${pc9.green("\u2714 Up to date")}
1524
1097
  `);
1525
1098
  } else {
1526
- console.log(` \u2022 Status: ${pc10.bold(pc10.yellow("\u26A0\uFE0F Update available!"))}`);
1527
- console.log(` \u2022 Run ${pc10.bold(pc10.cyan(`npx vectorvesper add ${slug} --overwrite`))} to update.
1099
+ console.log(` \u2022 Status: ${pc9.bold(pc9.yellow("\u26A0\uFE0F Update available!"))}`);
1100
+ console.log(` \u2022 Run ${pc9.bold(pc9.cyan(`npx vectorvesper add ${slug} --overwrite`))} to update.
1528
1101
  `);
1529
1102
  }
1530
1103
  } catch (error) {
1531
1104
  const message = error instanceof Error ? error.message : String(error);
1532
- spinner.fail(pc10.red(`Failed to fetch remote component details: ${message}`));
1105
+ spinner.fail(pc9.red(`Failed to fetch remote component details: ${message}`));
1533
1106
  process.exit(1);
1534
1107
  }
1535
1108
  } else {
@@ -1540,14 +1113,14 @@ Component Diff: ${slug}`)));
1540
1113
  try {
1541
1114
  const registryIndex = await fetchRegistryIndex();
1542
1115
  spinner.stop();
1543
- console.log(pc10.bold(pc10.cyan("\nVector Vesper Component Version Comparison\n")));
1544
- console.log(pc10.dim(" ----------------------------------------------------------------------"));
1116
+ console.log(pc9.bold(pc9.cyan("\nVector Vesper Component Version Comparison\n")));
1117
+ console.log(pc9.dim(" ----------------------------------------------------------------------"));
1545
1118
  console.log(
1546
- ` ${pc10.bold(pc10.white("Component".padEnd(25)))} ${pc10.bold(
1547
- pc10.white("Local".padEnd(10))
1548
- )} ${pc10.bold(pc10.white("Latest".padEnd(10)))} ${pc10.bold(pc10.white("Status"))}`
1119
+ ` ${pc9.bold(pc9.white("Component".padEnd(25)))} ${pc9.bold(
1120
+ pc9.white("Local".padEnd(10))
1121
+ )} ${pc9.bold(pc9.white("Latest".padEnd(10)))} ${pc9.bold(pc9.white("Status"))}`
1549
1122
  );
1550
- console.log(pc10.dim(" ----------------------------------------------------------------------"));
1123
+ console.log(pc9.dim(" ----------------------------------------------------------------------"));
1551
1124
  let updatesAvailableCount = 0;
1552
1125
  for (const instSlug of installedSlugs) {
1553
1126
  const localInfo = installedComponents[instSlug];
@@ -1555,67 +1128,67 @@ Component Diff: ${slug}`)));
1555
1128
  const remoteInfo = registryIndex.components.find((c) => c.slug === instSlug);
1556
1129
  if (!remoteInfo) {
1557
1130
  console.log(
1558
- ` ${pc10.cyan(instSlug.padEnd(25))} ${pc10.yellow(
1131
+ ` ${pc9.cyan(instSlug.padEnd(25))} ${pc9.yellow(
1559
1132
  localVersion.padEnd(10)
1560
- )} ${pc10.red("unknown".padEnd(10))} ${pc10.red("Not found in registry")}`
1133
+ )} ${pc9.red("unknown".padEnd(10))} ${pc9.red("Not found in registry")}`
1561
1134
  );
1562
1135
  } else {
1563
1136
  const remoteVersion = remoteInfo.version;
1564
1137
  if (localVersion === remoteVersion) {
1565
1138
  console.log(
1566
- ` ${pc10.cyan(instSlug.padEnd(25))} ${pc10.gray(
1139
+ ` ${pc9.cyan(instSlug.padEnd(25))} ${pc9.gray(
1567
1140
  localVersion.padEnd(10)
1568
- )} ${pc10.gray(remoteVersion.padEnd(10))} ${pc10.green("\u2714 Up to date")}`
1141
+ )} ${pc9.gray(remoteVersion.padEnd(10))} ${pc9.green("\u2714 Up to date")}`
1569
1142
  );
1570
1143
  } else {
1571
1144
  updatesAvailableCount++;
1572
1145
  console.log(
1573
- ` ${pc10.cyan(instSlug.padEnd(25))} ${pc10.yellow(
1146
+ ` ${pc9.cyan(instSlug.padEnd(25))} ${pc9.yellow(
1574
1147
  localVersion.padEnd(10)
1575
- )} ${pc10.green(remoteVersion.padEnd(10))} ${pc10.bold(
1576
- pc10.yellow("\u26A0\uFE0F Update available")
1148
+ )} ${pc9.green(remoteVersion.padEnd(10))} ${pc9.bold(
1149
+ pc9.yellow("\u26A0\uFE0F Update available")
1577
1150
  )}`
1578
1151
  );
1579
1152
  }
1580
1153
  }
1581
1154
  }
1582
- console.log(pc10.dim(" ----------------------------------------------------------------------"));
1155
+ console.log(pc9.dim(" ----------------------------------------------------------------------"));
1583
1156
  if (updatesAvailableCount > 0) {
1584
1157
  console.log(
1585
1158
  `
1586
- \u{1F4E2} ${pc10.bold(pc10.yellow(String(updatesAvailableCount)))} component(s) have updates available.`
1159
+ \u{1F4E2} ${pc9.bold(pc9.yellow(String(updatesAvailableCount)))} component(s) have updates available.`
1587
1160
  );
1588
- console.log(`\u{1F449} Run ${pc10.bold(pc10.cyan("npx vectorvesper add <slug> --overwrite"))} to update a component.
1161
+ console.log(`\u{1F449} Run ${pc9.bold(pc9.cyan("npx vectorvesper add <slug> --overwrite"))} to update a component.
1589
1162
  `);
1590
1163
  } else {
1591
1164
  console.log(`
1592
- ${pc10.green("\u2714")} All components are up to date!
1165
+ ${pc9.green("\u2714")} All components are up to date!
1593
1166
  `);
1594
1167
  }
1595
1168
  } catch (error) {
1596
1169
  const message = error instanceof Error ? error.message : String(error);
1597
- spinner.fail(pc10.red(`Failed to check updates: ${message}`));
1170
+ spinner.fail(pc9.red(`Failed to check updates: ${message}`));
1598
1171
  process.exit(1);
1599
1172
  }
1600
1173
  }
1601
1174
  }
1602
1175
 
1603
1176
  // src/commands/auth.ts
1604
- import pc11 from "picocolors";
1177
+ import pc10 from "picocolors";
1605
1178
  async function loginCommand(key) {
1606
1179
  if (!key || key.trim().length === 0) {
1607
- logger.error("Please provide a license key.");
1180
+ logger.error("Please provide your access token.");
1608
1181
  console.log(`
1609
- Usage: ${pc11.cyan("npx vectorvesper login <your-license-key>")}`);
1610
- console.log(` \u{1F511} Get a key at ${pc11.cyan("https://vectorvesper.dev/pricing")}
1182
+ Usage: ${pc10.cyan("npx vectorvesper login <token>")}`);
1183
+ console.log(` \u{1F511} Generate a token at ${pc10.cyan("https://vectorvesper.dev/account")}
1611
1184
  `);
1612
1185
  process.exit(1);
1613
1186
  }
1614
1187
  const trimmedKey = key.trim();
1615
1188
  if (trimmedKey.length < 8) {
1616
- logger.error("That doesn't look like a valid license key.");
1189
+ logger.error("That doesn't look like a valid token.");
1617
1190
  console.log(`
1618
- \u{1F511} License keys are available at ${pc11.cyan("https://vectorvesper.dev/pricing")}
1191
+ \u{1F511} Generate a token at ${pc10.cyan("https://vectorvesper.dev/account")}
1619
1192
  `);
1620
1193
  process.exit(1);
1621
1194
  }
@@ -1632,18 +1205,18 @@ async function loginCommand(key) {
1632
1205
  process.exit(1);
1633
1206
  }
1634
1207
  console.log("");
1635
- console.log(` ${pc11.green(pc11.bold("\u2714"))} License key saved successfully!`);
1636
- console.log(` ${pc11.dim("Stored at:")} ${pc11.cyan(getGlobalConfigPath())}`);
1208
+ console.log(` ${pc10.green(pc10.bold("\u2714"))} Token saved \u2014 you're logged in.`);
1209
+ console.log(` ${pc10.dim("Stored at:")} ${pc10.cyan(getGlobalConfigPath())}`);
1637
1210
  console.log("");
1638
- console.log(` ${pc11.dim("Pro components are now available when you run")} ${pc11.cyan("npx vectorvesper add <slug>")}`);
1639
- console.log(` ${pc11.dim("To verify your account:")} ${pc11.cyan("npx vectorvesper whoami")}`);
1211
+ console.log(` ${pc10.dim("Pro components are now available when you run")} ${pc10.cyan("npx vectorvesper add <slug>")}`);
1212
+ console.log(` ${pc10.dim("To verify your account:")} ${pc10.cyan("npx vectorvesper whoami")}`);
1640
1213
  console.log("");
1641
1214
  }
1642
1215
  async function logoutCommand() {
1643
1216
  const config = loadGlobalConfig();
1644
1217
  if (!config.auth?.token) {
1645
1218
  console.log(`
1646
- ${pc11.dim("You're not logged in. Nothing to do.")}
1219
+ ${pc10.dim("You're not logged in. Nothing to do.")}
1647
1220
  `);
1648
1221
  return;
1649
1222
  }
@@ -1656,46 +1229,46 @@ async function logoutCommand() {
1656
1229
  process.exit(1);
1657
1230
  }
1658
1231
  console.log("");
1659
- console.log(` ${pc11.green(pc11.bold("\u2714"))} Logged out successfully.`);
1660
- console.log(` ${pc11.dim("Your license key has been removed from")} ${pc11.cyan(getGlobalConfigPath())}`);
1661
- console.log(` ${pc11.dim("Free components remain available.")}`);
1232
+ console.log(` ${pc10.green(pc10.bold("\u2714"))} Logged out successfully.`);
1233
+ console.log(` ${pc10.dim("Your token has been removed from")} ${pc10.cyan(getGlobalConfigPath())}`);
1234
+ console.log(` ${pc10.dim("Free components remain available.")}`);
1662
1235
  console.log("");
1663
1236
  }
1664
1237
  async function whoamiCommand() {
1665
1238
  const config = loadGlobalConfig();
1666
1239
  console.log("");
1667
- console.log(pc11.bold(pc11.cyan(" Vector Vesper Account Status\n")));
1240
+ console.log(pc10.bold(pc10.cyan(" Vector Vesper Account Status\n")));
1668
1241
  if (config.auth?.token) {
1669
1242
  const maskedKey = config.auth.token.slice(0, 6) + "\u2026" + config.auth.token.slice(-4);
1670
1243
  const tier = config.auth.tier || "pro";
1671
- console.log(` ${pc11.bold("Status:")} ${pc11.green("Authenticated")}`);
1672
- console.log(` ${pc11.bold("Key:")} ${pc11.cyan(maskedKey)}`);
1673
- console.log(` ${pc11.bold("Tier:")} ${pc11.magenta(tier)}`);
1244
+ console.log(` ${pc10.bold("Status:")} ${pc10.green("Authenticated")}`);
1245
+ console.log(` ${pc10.bold("Token:")} ${pc10.cyan(maskedKey)}`);
1246
+ console.log(` ${pc10.bold("Tier:")} ${pc10.magenta(tier)}`);
1674
1247
  if (config.auth.email) {
1675
- console.log(` ${pc11.bold("Email:")} ${pc11.cyan(config.auth.email)}`);
1248
+ console.log(` ${pc10.bold("Email:")} ${pc10.cyan(config.auth.email)}`);
1676
1249
  }
1677
1250
  if (config.auth.expiresAt) {
1678
1251
  const expiry = new Date(config.auth.expiresAt);
1679
1252
  const now = /* @__PURE__ */ new Date();
1680
1253
  const isExpired = expiry < now;
1681
- console.log(` ${pc11.bold("Expires:")} ${isExpired ? pc11.red("EXPIRED") : pc11.green(expiry.toLocaleDateString())}`);
1254
+ console.log(` ${pc10.bold("Expires:")} ${isExpired ? pc10.red("EXPIRED") : pc10.green(expiry.toLocaleDateString())}`);
1682
1255
  }
1683
1256
  console.log("");
1684
- console.log(` ${pc11.dim("Config:")} ${pc11.cyan(getGlobalConfigPath())}`);
1685
- console.log(` ${pc11.dim("Manage your account at")} ${pc11.cyan("https://vectorvesper.dev/account")}`);
1257
+ console.log(` ${pc10.dim("Config:")} ${pc10.cyan(getGlobalConfigPath())}`);
1258
+ console.log(` ${pc10.dim("Manage your account at")} ${pc10.cyan("https://vectorvesper.dev/account")}`);
1686
1259
  } else {
1687
- console.log(` ${pc11.bold("Status:")} ${pc11.yellow("Anonymous (free tier)")}`);
1688
- console.log(` ${pc11.bold("Access:")} ${pc11.dim("Free components only")}`);
1260
+ console.log(` ${pc10.bold("Status:")} ${pc10.yellow("Anonymous (free tier)")}`);
1261
+ console.log(` ${pc10.bold("Access:")} ${pc10.dim("Free components only")}`);
1689
1262
  console.log("");
1690
- console.log(` ${pc11.dim("To unlock pro components:")}`);
1691
- console.log(` ${pc11.cyan("npx vectorvesper login <your-license-key>")}`);
1692
- console.log(` \u{1F511} ${pc11.dim("Get a key at")} ${pc11.cyan("https://vectorvesper.dev/pricing")}`);
1263
+ console.log(` ${pc10.dim("To unlock pro components:")}`);
1264
+ console.log(` ${pc10.cyan("npx vectorvesper login <token>")}`);
1265
+ console.log(` \u{1F511} ${pc10.dim("Generate a token at")} ${pc10.cyan("https://vectorvesper.dev/account")}`);
1693
1266
  }
1694
1267
  console.log("");
1695
1268
  }
1696
1269
 
1697
1270
  // src/index.ts
1698
- var version = true ? "1.2.0" : "0.0.0-dev";
1271
+ var version = true ? "2.0.1" : "0.0.0-dev";
1699
1272
  var program = new Command();
1700
1273
  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) => {
1701
1274
  const opts = thisCommand.opts();
@@ -1733,6 +1306,10 @@ program.command("logout", { hidden: true }).description("Clear stored license cr
1733
1306
  program.command("whoami", { hidden: true }).description("Show current authentication status").action(async () => {
1734
1307
  await whoamiCommand();
1735
1308
  });
1309
+ program.command("mcp [action]").description("Run as an MCP server (stdio) for AI coding agents. `vv mcp status` checks the setup.").option("--stdio", "Force server mode even from an interactive terminal").action(async (action, options) => {
1310
+ const { mcpCommand } = await import("./mcp-ZGA5K5VW.js");
1311
+ await mcpCommand(action, options);
1312
+ });
1736
1313
  process.on("unhandledRejection", (error) => {
1737
1314
  console.error("An unexpected error occurred:", error instanceof Error ? error.message : error);
1738
1315
  process.exit(1);