vectorvesper 2.0.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/{chunk-32GDEAJM.js → chunk-HOJ3DQSV.js} +11 -242
- package/dist/chunk-SFP5K3ZO.js +243 -0
- package/dist/chunk-XN3PPCIM.js +41 -0
- package/dist/index.js +9 -7
- package/dist/mcp-ZGA5K5VW.js +107 -0
- package/dist/{server-7WN7N3ZG.js → server-5CFZ6BS7.js} +9 -42
- package/package.json +3 -2
- package/dist/mcp-DOUIUZGA.js +0 -24
|
@@ -1,37 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/** Standard info message */
|
|
9
|
-
info(message) {
|
|
10
|
-
console.log(message);
|
|
11
|
-
},
|
|
12
|
-
/** Success message with green checkmark */
|
|
13
|
-
success(message) {
|
|
14
|
-
console.log(`${pc.green("\u2714")} ${message}`);
|
|
15
|
-
},
|
|
16
|
-
/** Warning message */
|
|
17
|
-
warn(message) {
|
|
18
|
-
console.log(pc.yellow(`\u26A0\uFE0F ${message}`));
|
|
19
|
-
},
|
|
20
|
-
/** Error message */
|
|
21
|
-
error(message) {
|
|
22
|
-
console.error(pc.red(`\u274C ${message}`));
|
|
23
|
-
},
|
|
24
|
-
/** Debug message — only shown when --verbose is active */
|
|
25
|
-
debug(message) {
|
|
26
|
-
if (verboseMode) {
|
|
27
|
-
console.log(pc.dim(` [debug] ${message}`));
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
/** Blank line */
|
|
31
|
-
break() {
|
|
32
|
-
console.log("");
|
|
33
|
-
}
|
|
34
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
RegistryComponentSchema,
|
|
3
|
+
RegistryIndexSchema,
|
|
4
|
+
getAuthToken,
|
|
5
|
+
logger,
|
|
6
|
+
validateSlug
|
|
7
|
+
} from "./chunk-SFP5K3ZO.js";
|
|
35
8
|
|
|
36
9
|
// src/utils/project.ts
|
|
37
10
|
import fs from "fs";
|
|
@@ -97,203 +70,9 @@ function detectProject(cwd = process.cwd()) {
|
|
|
97
70
|
};
|
|
98
71
|
}
|
|
99
72
|
|
|
100
|
-
// src/utils/
|
|
73
|
+
// src/utils/registry.ts
|
|
101
74
|
import fs2 from "fs";
|
|
102
75
|
import path2 from "path";
|
|
103
|
-
import os from "os";
|
|
104
|
-
|
|
105
|
-
// src/utils/types.ts
|
|
106
|
-
import { z } from "zod";
|
|
107
|
-
var SLUG_REGEX = /^[a-z0-9][a-z0-9-]*$/;
|
|
108
|
-
function validateSlug(slug) {
|
|
109
|
-
if (!SLUG_REGEX.test(slug)) {
|
|
110
|
-
throw new Error(
|
|
111
|
-
`Invalid component slug "${slug}". Slugs must contain only lowercase letters, numbers, and hyphens, and cannot start with a hyphen.`
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
var ComponentFileSchema = z.object({
|
|
116
|
-
path: z.string(),
|
|
117
|
-
target: z.string(),
|
|
118
|
-
type: z.enum(["component", "types", "shader", "lib", "docs"]),
|
|
119
|
-
content: z.string()
|
|
120
|
-
});
|
|
121
|
-
var RegistryComponentSchema = z.object({
|
|
122
|
-
slug: z.string(),
|
|
123
|
-
name: z.string(),
|
|
124
|
-
title: z.string(),
|
|
125
|
-
description: z.string(),
|
|
126
|
-
version: z.string(),
|
|
127
|
-
tier: z.enum(["free", "pro"]),
|
|
128
|
-
category: z.string(),
|
|
129
|
-
type: z.string(),
|
|
130
|
-
frameworks: z.array(z.string()),
|
|
131
|
-
files: z.array(ComponentFileSchema),
|
|
132
|
-
dependencies: z.array(z.string()),
|
|
133
|
-
devDependencies: z.array(z.string()),
|
|
134
|
-
registryDependencies: z.array(z.string()),
|
|
135
|
-
requiresClient: z.boolean(),
|
|
136
|
-
supportsReducedMotion: z.boolean(),
|
|
137
|
-
usesWebGL: z.boolean(),
|
|
138
|
-
usesPointer: z.boolean(),
|
|
139
|
-
usesScroll: z.boolean(),
|
|
140
|
-
// Optional metadata — kept in sync with the registry builder schema.
|
|
141
|
-
// Declared here (rather than relying on .passthrough()) so the CLI can
|
|
142
|
-
// read them with full type-safety for post-install guidance.
|
|
143
|
-
entry: z.string().optional(),
|
|
144
|
-
exportName: z.string().optional(),
|
|
145
|
-
usesTailwind: z.boolean().optional(),
|
|
146
|
-
fallbacks: z.array(z.string()).optional(),
|
|
147
|
-
recipes: z.array(z.string()).optional(),
|
|
148
|
-
docsUrl: z.string().optional(),
|
|
149
|
-
previewUrl: z.string().optional()
|
|
150
|
-
}).passthrough();
|
|
151
|
-
var IndexComponentSchema = z.object({
|
|
152
|
-
slug: z.string(),
|
|
153
|
-
name: z.string(),
|
|
154
|
-
title: z.string(),
|
|
155
|
-
description: z.string(),
|
|
156
|
-
version: z.string(),
|
|
157
|
-
tier: z.enum(["free", "pro"]),
|
|
158
|
-
category: z.string(),
|
|
159
|
-
type: z.string(),
|
|
160
|
-
frameworks: z.array(z.string()),
|
|
161
|
-
files: z.array(z.object({
|
|
162
|
-
path: z.string(),
|
|
163
|
-
target: z.string(),
|
|
164
|
-
type: z.enum(["component", "types", "shader", "lib", "docs"])
|
|
165
|
-
})),
|
|
166
|
-
dependencies: z.array(z.string()),
|
|
167
|
-
devDependencies: z.array(z.string()),
|
|
168
|
-
registryDependencies: z.array(z.string()),
|
|
169
|
-
requiresClient: z.boolean(),
|
|
170
|
-
supportsReducedMotion: z.boolean(),
|
|
171
|
-
usesWebGL: z.boolean(),
|
|
172
|
-
usesPointer: z.boolean(),
|
|
173
|
-
usesScroll: z.boolean(),
|
|
174
|
-
entry: z.string().optional(),
|
|
175
|
-
exportName: z.string().optional(),
|
|
176
|
-
usesTailwind: z.boolean().optional(),
|
|
177
|
-
// These are emitted by the registry build and were reaching consumers only
|
|
178
|
-
// through .passthrough(), i.e. typed as unknown. Declared optional rather
|
|
179
|
-
// than required so an older published registry still validates.
|
|
180
|
-
fallbacks: z.array(z.string()).optional(),
|
|
181
|
-
recipes: z.array(z.string()).optional(),
|
|
182
|
-
docsUrl: z.string().optional(),
|
|
183
|
-
previewUrl: z.string().optional()
|
|
184
|
-
}).passthrough();
|
|
185
|
-
var RegistryIndexSchema = z.object({
|
|
186
|
-
version: z.string(),
|
|
187
|
-
components: z.array(IndexComponentSchema)
|
|
188
|
-
});
|
|
189
|
-
var VVConfigSchema = z.object({
|
|
190
|
-
tsx: z.boolean(),
|
|
191
|
-
framework: z.enum(["next", "vite", "unknown"]),
|
|
192
|
-
aliases: z.object({
|
|
193
|
-
vv: z.string()
|
|
194
|
-
})
|
|
195
|
-
});
|
|
196
|
-
var VVGlobalConfigSchema = z.object({
|
|
197
|
-
// Auth — license key for paid components
|
|
198
|
-
auth: z.object({
|
|
199
|
-
token: z.string().optional(),
|
|
200
|
-
email: z.string().optional(),
|
|
201
|
-
tier: z.enum(["free", "pro", "team"]).optional(),
|
|
202
|
-
expiresAt: z.string().optional()
|
|
203
|
-
}).optional(),
|
|
204
|
-
// Preferences
|
|
205
|
-
telemetry: z.boolean().optional()
|
|
206
|
-
}).passthrough();
|
|
207
|
-
var ManifestEntrySchema = z.object({
|
|
208
|
-
version: z.string(),
|
|
209
|
-
installedAt: z.string(),
|
|
210
|
-
installedOn: z.string(),
|
|
211
|
-
files: z.array(z.string())
|
|
212
|
-
});
|
|
213
|
-
var ManifestSchema = z.object({
|
|
214
|
-
components: z.record(z.string(), ManifestEntrySchema)
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
// src/utils/config.ts
|
|
218
|
-
var CONFIG_FILE_NAME = "vv.config.json";
|
|
219
|
-
function getConfigPath(cwd = process.cwd()) {
|
|
220
|
-
return path2.join(cwd, CONFIG_FILE_NAME);
|
|
221
|
-
}
|
|
222
|
-
function loadConfig(cwd = process.cwd()) {
|
|
223
|
-
const configPath = getConfigPath(cwd);
|
|
224
|
-
if (!fs2.existsSync(configPath)) {
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
let raw;
|
|
228
|
-
try {
|
|
229
|
-
const content = fs2.readFileSync(configPath, "utf-8");
|
|
230
|
-
raw = JSON.parse(content);
|
|
231
|
-
} catch {
|
|
232
|
-
throw new Error(
|
|
233
|
-
`Failed to parse vv.config.json \u2014 the file contains invalid JSON. Delete it and run "npx vectorvesper init" to regenerate.`
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
const result = VVConfigSchema.safeParse(raw);
|
|
237
|
-
if (!result.success) {
|
|
238
|
-
const issues = result.error.issues.map((i) => ` \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
239
|
-
throw new Error(
|
|
240
|
-
`Invalid vv.config.json \u2014 schema validation failed:
|
|
241
|
-
${issues}
|
|
242
|
-
Delete the file and run "npx vectorvesper init" to regenerate.`
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
return result.data;
|
|
246
|
-
}
|
|
247
|
-
function writeConfig(config, cwd = process.cwd()) {
|
|
248
|
-
const configPath = getConfigPath(cwd);
|
|
249
|
-
fs2.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
250
|
-
}
|
|
251
|
-
var GLOBAL_CONFIG_DIR = path2.join(os.homedir(), ".vv");
|
|
252
|
-
var GLOBAL_CONFIG_PATH = path2.join(GLOBAL_CONFIG_DIR, "config.json");
|
|
253
|
-
function getGlobalConfigPath() {
|
|
254
|
-
return GLOBAL_CONFIG_PATH;
|
|
255
|
-
}
|
|
256
|
-
function loadGlobalConfig() {
|
|
257
|
-
if (!fs2.existsSync(GLOBAL_CONFIG_PATH)) {
|
|
258
|
-
return {};
|
|
259
|
-
}
|
|
260
|
-
try {
|
|
261
|
-
const content = fs2.readFileSync(GLOBAL_CONFIG_PATH, "utf-8");
|
|
262
|
-
const raw = JSON.parse(content);
|
|
263
|
-
const result = VVGlobalConfigSchema.safeParse(raw);
|
|
264
|
-
if (!result.success) {
|
|
265
|
-
logger.debug(`Global config validation failed: ${result.error.message}`);
|
|
266
|
-
return {};
|
|
267
|
-
}
|
|
268
|
-
return result.data;
|
|
269
|
-
} catch {
|
|
270
|
-
logger.debug("Failed to parse global config, using defaults.");
|
|
271
|
-
return {};
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
function saveGlobalConfig(config) {
|
|
275
|
-
if (!fs2.existsSync(GLOBAL_CONFIG_DIR)) {
|
|
276
|
-
fs2.mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true });
|
|
277
|
-
}
|
|
278
|
-
fs2.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
|
|
279
|
-
}
|
|
280
|
-
function getAuthToken() {
|
|
281
|
-
const config = loadGlobalConfig();
|
|
282
|
-
return config.auth?.token;
|
|
283
|
-
}
|
|
284
|
-
function resolveAlias(alias, hasSrcDir) {
|
|
285
|
-
if (alias.startsWith("@/")) {
|
|
286
|
-
return alias.replace("@/", hasSrcDir ? "src/" : "");
|
|
287
|
-
}
|
|
288
|
-
if (alias.startsWith("~/")) {
|
|
289
|
-
return alias.replace("~/", hasSrcDir ? "src/" : "");
|
|
290
|
-
}
|
|
291
|
-
return alias;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// src/utils/registry.ts
|
|
295
|
-
import fs3 from "fs";
|
|
296
|
-
import path3 from "path";
|
|
297
76
|
import { fileURLToPath } from "url";
|
|
298
77
|
var DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/vectorvesper/vv-components/main/r";
|
|
299
78
|
var DEFAULT_PRO_API_URL = "https://vectorvesper.dev/api/cli/registry";
|
|
@@ -402,12 +181,12 @@ async function fetchRegistryData(urlOrPath) {
|
|
|
402
181
|
if (urlOrPath.startsWith("file://")) {
|
|
403
182
|
cleanPath = fileURLToPath(urlOrPath);
|
|
404
183
|
}
|
|
405
|
-
cleanPath =
|
|
406
|
-
if (!
|
|
184
|
+
cleanPath = path2.resolve(cleanPath);
|
|
185
|
+
if (!fs2.existsSync(cleanPath)) {
|
|
407
186
|
throw new Error(`Registry path not found: ${cleanPath}`);
|
|
408
187
|
}
|
|
409
188
|
logger.debug(`Reading local registry: ${cleanPath}`);
|
|
410
|
-
return
|
|
189
|
+
return fs2.readFileSync(cleanPath, "utf-8");
|
|
411
190
|
}
|
|
412
191
|
async function fetchRegistryIndex() {
|
|
413
192
|
const baseUrl = getRegistryBaseUrl();
|
|
@@ -482,17 +261,7 @@ ${issues}`);
|
|
|
482
261
|
}
|
|
483
262
|
|
|
484
263
|
export {
|
|
485
|
-
setVerbose,
|
|
486
|
-
logger,
|
|
487
264
|
detectProject,
|
|
488
|
-
validateSlug,
|
|
489
|
-
loadConfig,
|
|
490
|
-
writeConfig,
|
|
491
|
-
getGlobalConfigPath,
|
|
492
|
-
loadGlobalConfig,
|
|
493
|
-
saveGlobalConfig,
|
|
494
|
-
getAuthToken,
|
|
495
|
-
resolveAlias,
|
|
496
265
|
fetchRegistryIndex,
|
|
497
266
|
fetchComponent
|
|
498
267
|
};
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
// src/utils/logger.ts
|
|
2
|
+
import pc from "picocolors";
|
|
3
|
+
var verboseMode = false;
|
|
4
|
+
function setVerbose(enabled) {
|
|
5
|
+
verboseMode = enabled;
|
|
6
|
+
}
|
|
7
|
+
var logger = {
|
|
8
|
+
/** Standard info message */
|
|
9
|
+
info(message) {
|
|
10
|
+
console.log(message);
|
|
11
|
+
},
|
|
12
|
+
/** Success message with green checkmark */
|
|
13
|
+
success(message) {
|
|
14
|
+
console.log(`${pc.green("\u2714")} ${message}`);
|
|
15
|
+
},
|
|
16
|
+
/** Warning message */
|
|
17
|
+
warn(message) {
|
|
18
|
+
console.log(pc.yellow(`\u26A0\uFE0F ${message}`));
|
|
19
|
+
},
|
|
20
|
+
/** Error message */
|
|
21
|
+
error(message) {
|
|
22
|
+
console.error(pc.red(`\u274C ${message}`));
|
|
23
|
+
},
|
|
24
|
+
/** Debug message — only shown when --verbose is active */
|
|
25
|
+
debug(message) {
|
|
26
|
+
if (verboseMode) {
|
|
27
|
+
console.log(pc.dim(` [debug] ${message}`));
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
/** Blank line */
|
|
31
|
+
break() {
|
|
32
|
+
console.log("");
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// src/utils/config.ts
|
|
37
|
+
import fs from "fs";
|
|
38
|
+
import path from "path";
|
|
39
|
+
import os from "os";
|
|
40
|
+
|
|
41
|
+
// src/utils/types.ts
|
|
42
|
+
import { z } from "zod";
|
|
43
|
+
var SLUG_REGEX = /^[a-z0-9][a-z0-9-]*$/;
|
|
44
|
+
function validateSlug(slug) {
|
|
45
|
+
if (!SLUG_REGEX.test(slug)) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Invalid component slug "${slug}". Slugs must contain only lowercase letters, numbers, and hyphens, and cannot start with a hyphen.`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
var ComponentFileSchema = z.object({
|
|
52
|
+
path: z.string(),
|
|
53
|
+
target: z.string(),
|
|
54
|
+
type: z.enum(["component", "types", "shader", "lib", "docs"]),
|
|
55
|
+
content: z.string()
|
|
56
|
+
});
|
|
57
|
+
var RegistryComponentSchema = z.object({
|
|
58
|
+
slug: z.string(),
|
|
59
|
+
name: z.string(),
|
|
60
|
+
title: z.string(),
|
|
61
|
+
description: z.string(),
|
|
62
|
+
version: z.string(),
|
|
63
|
+
tier: z.enum(["free", "pro"]),
|
|
64
|
+
category: z.string(),
|
|
65
|
+
type: z.string(),
|
|
66
|
+
frameworks: z.array(z.string()),
|
|
67
|
+
files: z.array(ComponentFileSchema),
|
|
68
|
+
dependencies: z.array(z.string()),
|
|
69
|
+
devDependencies: z.array(z.string()),
|
|
70
|
+
registryDependencies: z.array(z.string()),
|
|
71
|
+
requiresClient: z.boolean(),
|
|
72
|
+
supportsReducedMotion: z.boolean(),
|
|
73
|
+
usesWebGL: z.boolean(),
|
|
74
|
+
usesPointer: z.boolean(),
|
|
75
|
+
usesScroll: z.boolean(),
|
|
76
|
+
// Optional metadata — kept in sync with the registry builder schema.
|
|
77
|
+
// Declared here (rather than relying on .passthrough()) so the CLI can
|
|
78
|
+
// read them with full type-safety for post-install guidance.
|
|
79
|
+
entry: z.string().optional(),
|
|
80
|
+
exportName: z.string().optional(),
|
|
81
|
+
usesTailwind: z.boolean().optional(),
|
|
82
|
+
fallbacks: z.array(z.string()).optional(),
|
|
83
|
+
recipes: z.array(z.string()).optional(),
|
|
84
|
+
docsUrl: z.string().optional(),
|
|
85
|
+
previewUrl: z.string().optional()
|
|
86
|
+
}).passthrough();
|
|
87
|
+
var IndexComponentSchema = z.object({
|
|
88
|
+
slug: z.string(),
|
|
89
|
+
name: z.string(),
|
|
90
|
+
title: z.string(),
|
|
91
|
+
description: z.string(),
|
|
92
|
+
version: z.string(),
|
|
93
|
+
tier: z.enum(["free", "pro"]),
|
|
94
|
+
category: z.string(),
|
|
95
|
+
type: z.string(),
|
|
96
|
+
frameworks: z.array(z.string()),
|
|
97
|
+
files: z.array(z.object({
|
|
98
|
+
path: z.string(),
|
|
99
|
+
target: z.string(),
|
|
100
|
+
type: z.enum(["component", "types", "shader", "lib", "docs"])
|
|
101
|
+
})),
|
|
102
|
+
dependencies: z.array(z.string()),
|
|
103
|
+
devDependencies: z.array(z.string()),
|
|
104
|
+
registryDependencies: z.array(z.string()),
|
|
105
|
+
requiresClient: z.boolean(),
|
|
106
|
+
supportsReducedMotion: z.boolean(),
|
|
107
|
+
usesWebGL: z.boolean(),
|
|
108
|
+
usesPointer: z.boolean(),
|
|
109
|
+
usesScroll: z.boolean(),
|
|
110
|
+
entry: z.string().optional(),
|
|
111
|
+
exportName: z.string().optional(),
|
|
112
|
+
usesTailwind: z.boolean().optional(),
|
|
113
|
+
// These are emitted by the registry build and were reaching consumers only
|
|
114
|
+
// through .passthrough(), i.e. typed as unknown. Declared optional rather
|
|
115
|
+
// than required so an older published registry still validates.
|
|
116
|
+
fallbacks: z.array(z.string()).optional(),
|
|
117
|
+
recipes: z.array(z.string()).optional(),
|
|
118
|
+
docsUrl: z.string().optional(),
|
|
119
|
+
previewUrl: z.string().optional()
|
|
120
|
+
}).passthrough();
|
|
121
|
+
var RegistryIndexSchema = z.object({
|
|
122
|
+
version: z.string(),
|
|
123
|
+
components: z.array(IndexComponentSchema)
|
|
124
|
+
});
|
|
125
|
+
var VVConfigSchema = z.object({
|
|
126
|
+
tsx: z.boolean(),
|
|
127
|
+
framework: z.enum(["next", "vite", "unknown"]),
|
|
128
|
+
aliases: z.object({
|
|
129
|
+
vv: z.string()
|
|
130
|
+
})
|
|
131
|
+
});
|
|
132
|
+
var VVGlobalConfigSchema = z.object({
|
|
133
|
+
// Auth — license key for paid components
|
|
134
|
+
auth: z.object({
|
|
135
|
+
token: z.string().optional(),
|
|
136
|
+
email: z.string().optional(),
|
|
137
|
+
tier: z.enum(["free", "pro", "team"]).optional(),
|
|
138
|
+
expiresAt: z.string().optional()
|
|
139
|
+
}).optional(),
|
|
140
|
+
// Preferences
|
|
141
|
+
telemetry: z.boolean().optional()
|
|
142
|
+
}).passthrough();
|
|
143
|
+
var ManifestEntrySchema = z.object({
|
|
144
|
+
version: z.string(),
|
|
145
|
+
installedAt: z.string(),
|
|
146
|
+
installedOn: z.string(),
|
|
147
|
+
files: z.array(z.string())
|
|
148
|
+
});
|
|
149
|
+
var ManifestSchema = z.object({
|
|
150
|
+
components: z.record(z.string(), ManifestEntrySchema)
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// src/utils/config.ts
|
|
154
|
+
var CONFIG_FILE_NAME = "vv.config.json";
|
|
155
|
+
function getConfigPath(cwd = process.cwd()) {
|
|
156
|
+
return path.join(cwd, CONFIG_FILE_NAME);
|
|
157
|
+
}
|
|
158
|
+
function loadConfig(cwd = process.cwd()) {
|
|
159
|
+
const configPath = getConfigPath(cwd);
|
|
160
|
+
if (!fs.existsSync(configPath)) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
let raw;
|
|
164
|
+
try {
|
|
165
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
166
|
+
raw = JSON.parse(content);
|
|
167
|
+
} catch {
|
|
168
|
+
throw new Error(
|
|
169
|
+
`Failed to parse vv.config.json \u2014 the file contains invalid JSON. Delete it and run "npx vectorvesper init" to regenerate.`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
const result = VVConfigSchema.safeParse(raw);
|
|
173
|
+
if (!result.success) {
|
|
174
|
+
const issues = result.error.issues.map((i) => ` \u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
175
|
+
throw new Error(
|
|
176
|
+
`Invalid vv.config.json \u2014 schema validation failed:
|
|
177
|
+
${issues}
|
|
178
|
+
Delete the file and run "npx vectorvesper init" to regenerate.`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
return result.data;
|
|
182
|
+
}
|
|
183
|
+
function writeConfig(config, cwd = process.cwd()) {
|
|
184
|
+
const configPath = getConfigPath(cwd);
|
|
185
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
186
|
+
}
|
|
187
|
+
var GLOBAL_CONFIG_DIR = path.join(os.homedir(), ".vv");
|
|
188
|
+
var GLOBAL_CONFIG_PATH = path.join(GLOBAL_CONFIG_DIR, "config.json");
|
|
189
|
+
function getGlobalConfigPath() {
|
|
190
|
+
return GLOBAL_CONFIG_PATH;
|
|
191
|
+
}
|
|
192
|
+
function loadGlobalConfig() {
|
|
193
|
+
if (!fs.existsSync(GLOBAL_CONFIG_PATH)) {
|
|
194
|
+
return {};
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
const content = fs.readFileSync(GLOBAL_CONFIG_PATH, "utf-8");
|
|
198
|
+
const raw = JSON.parse(content);
|
|
199
|
+
const result = VVGlobalConfigSchema.safeParse(raw);
|
|
200
|
+
if (!result.success) {
|
|
201
|
+
logger.debug(`Global config validation failed: ${result.error.message}`);
|
|
202
|
+
return {};
|
|
203
|
+
}
|
|
204
|
+
return result.data;
|
|
205
|
+
} catch {
|
|
206
|
+
logger.debug("Failed to parse global config, using defaults.");
|
|
207
|
+
return {};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function saveGlobalConfig(config) {
|
|
211
|
+
if (!fs.existsSync(GLOBAL_CONFIG_DIR)) {
|
|
212
|
+
fs.mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true });
|
|
213
|
+
}
|
|
214
|
+
fs.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
|
|
215
|
+
}
|
|
216
|
+
function getAuthToken() {
|
|
217
|
+
const config = loadGlobalConfig();
|
|
218
|
+
return config.auth?.token;
|
|
219
|
+
}
|
|
220
|
+
function resolveAlias(alias, hasSrcDir) {
|
|
221
|
+
if (alias.startsWith("@/")) {
|
|
222
|
+
return alias.replace("@/", hasSrcDir ? "src/" : "");
|
|
223
|
+
}
|
|
224
|
+
if (alias.startsWith("~/")) {
|
|
225
|
+
return alias.replace("~/", hasSrcDir ? "src/" : "");
|
|
226
|
+
}
|
|
227
|
+
return alias;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export {
|
|
231
|
+
setVerbose,
|
|
232
|
+
logger,
|
|
233
|
+
validateSlug,
|
|
234
|
+
RegistryComponentSchema,
|
|
235
|
+
RegistryIndexSchema,
|
|
236
|
+
loadConfig,
|
|
237
|
+
writeConfig,
|
|
238
|
+
getGlobalConfigPath,
|
|
239
|
+
loadGlobalConfig,
|
|
240
|
+
saveGlobalConfig,
|
|
241
|
+
getAuthToken,
|
|
242
|
+
resolveAlias
|
|
243
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// src/mcp/manifest.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
var CANDIDATES = [
|
|
7
|
+
path.join(__dirname, "hooks.json"),
|
|
8
|
+
path.join(__dirname, "../hooks.json"),
|
|
9
|
+
path.resolve(__dirname, "../../../registry/generated/hooks.lean.json"),
|
|
10
|
+
path.resolve(__dirname, "../../registry/generated/hooks.lean.json")
|
|
11
|
+
];
|
|
12
|
+
var cached = null;
|
|
13
|
+
function loadHookManifest() {
|
|
14
|
+
if (cached) return cached;
|
|
15
|
+
for (const candidate of CANDIDATES) {
|
|
16
|
+
if (!fs.existsSync(candidate)) continue;
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(fs.readFileSync(candidate, "utf-8"));
|
|
19
|
+
if (Array.isArray(parsed?.hooks)) {
|
|
20
|
+
cached = parsed;
|
|
21
|
+
return cached;
|
|
22
|
+
}
|
|
23
|
+
} catch {
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
function findHook(name) {
|
|
29
|
+
const manifest = loadHookManifest();
|
|
30
|
+
if (!manifest) return null;
|
|
31
|
+
const wanted = name.toLowerCase();
|
|
32
|
+
return manifest.hooks.find((h) => h.name.toLowerCase() === wanted) ?? // Tolerate "sensor-bus" / "sensorbus" / "SensorBus" for "useSensorBus".
|
|
33
|
+
manifest.hooks.find(
|
|
34
|
+
(h) => h.name.toLowerCase().replace(/^use/, "") === wanted.replace(/^use/, "").replace(/-/g, "")
|
|
35
|
+
) ?? null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
loadHookManifest,
|
|
40
|
+
findHook
|
|
41
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
detectProject,
|
|
4
4
|
fetchComponent,
|
|
5
|
-
fetchRegistryIndex
|
|
5
|
+
fetchRegistryIndex
|
|
6
|
+
} from "./chunk-HOJ3DQSV.js";
|
|
7
|
+
import {
|
|
6
8
|
getAuthToken,
|
|
7
9
|
getGlobalConfigPath,
|
|
8
10
|
loadConfig,
|
|
@@ -13,7 +15,7 @@ import {
|
|
|
13
15
|
setVerbose,
|
|
14
16
|
validateSlug,
|
|
15
17
|
writeConfig
|
|
16
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-SFP5K3ZO.js";
|
|
17
19
|
|
|
18
20
|
// src/index.ts
|
|
19
21
|
import { Command } from "commander";
|
|
@@ -968,7 +970,7 @@ Remove ${slug}
|
|
|
968
970
|
import fs6 from "fs";
|
|
969
971
|
import path6 from "path";
|
|
970
972
|
import pc8 from "picocolors";
|
|
971
|
-
var CLI_VERSION = true ? "
|
|
973
|
+
var CLI_VERSION = true ? "2.0.1" : "0.0.0-dev";
|
|
972
974
|
async function infoCommand() {
|
|
973
975
|
console.log(pc8.bold(pc8.cyan("\nVector Vesper Diagnostics\n")));
|
|
974
976
|
const projectInfo = detectProject();
|
|
@@ -1266,7 +1268,7 @@ async function whoamiCommand() {
|
|
|
1266
1268
|
}
|
|
1267
1269
|
|
|
1268
1270
|
// src/index.ts
|
|
1269
|
-
var version = true ? "
|
|
1271
|
+
var version = true ? "2.0.1" : "0.0.0-dev";
|
|
1270
1272
|
var program = new Command();
|
|
1271
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) => {
|
|
1272
1274
|
const opts = thisCommand.opts();
|
|
@@ -1304,9 +1306,9 @@ program.command("logout", { hidden: true }).description("Clear stored license cr
|
|
|
1304
1306
|
program.command("whoami", { hidden: true }).description("Show current authentication status").action(async () => {
|
|
1305
1307
|
await whoamiCommand();
|
|
1306
1308
|
});
|
|
1307
|
-
program.command("mcp").description("Run as an MCP server (stdio) for AI coding agents").action(async () => {
|
|
1308
|
-
const { mcpCommand } = await import("./mcp-
|
|
1309
|
-
await mcpCommand();
|
|
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);
|
|
1310
1312
|
});
|
|
1311
1313
|
process.on("unhandledRejection", (error) => {
|
|
1312
1314
|
console.error("An unexpected error occurred:", error instanceof Error ? error.message : error);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadHookManifest
|
|
3
|
+
} from "./chunk-XN3PPCIM.js";
|
|
4
|
+
import {
|
|
5
|
+
getAuthToken
|
|
6
|
+
} from "./chunk-SFP5K3ZO.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/mcp.ts
|
|
9
|
+
import pc from "picocolors";
|
|
10
|
+
var VERSION = true ? "2.0.1" : "0.0.0-dev";
|
|
11
|
+
var CONFIG_SNIPPET = `{
|
|
12
|
+
"mcpServers": {
|
|
13
|
+
"vectorvesper": {
|
|
14
|
+
"command": "npx",
|
|
15
|
+
"args": ["-y", "vectorvesper", "mcp"]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}`;
|
|
19
|
+
function protectStdout() {
|
|
20
|
+
const toStderr = (...args) => {
|
|
21
|
+
console.error(...args);
|
|
22
|
+
};
|
|
23
|
+
console.log = toStderr;
|
|
24
|
+
console.info = toStderr;
|
|
25
|
+
console.debug = toStderr;
|
|
26
|
+
}
|
|
27
|
+
function printStatus() {
|
|
28
|
+
const manifest = loadHookManifest();
|
|
29
|
+
const authed = Boolean(getAuthToken());
|
|
30
|
+
const ok = (s) => `${pc.green("\u2714")} ${s}`;
|
|
31
|
+
const bad = (s) => `${pc.red("\u2717")} ${s}`;
|
|
32
|
+
console.log("");
|
|
33
|
+
console.log(pc.bold(pc.cyan(" Vector Vesper MCP\n")));
|
|
34
|
+
console.log(` ${pc.bold("CLI version:")} ${VERSION}`);
|
|
35
|
+
if (manifest) {
|
|
36
|
+
console.log(` ${ok(`Hook manifest: ${manifest.hooks.length} hooks, engine v${manifest.engineVersion}`)}`);
|
|
37
|
+
console.log(` ${pc.dim(`Contract level: ${manifest.contractLevel}`)}`);
|
|
38
|
+
} else {
|
|
39
|
+
console.log(` ${bad("Hook manifest: MISSING")}`);
|
|
40
|
+
console.log(` ${pc.dim("Reinstall with: npm i -g vectorvesper@latest")}`);
|
|
41
|
+
}
|
|
42
|
+
console.log(
|
|
43
|
+
` ${authed ? ok("Authenticated \u2014 Pro components available") : pc.dim("\u25CB Not authenticated \u2014 free components only")}`
|
|
44
|
+
);
|
|
45
|
+
console.log("");
|
|
46
|
+
console.log(pc.bold(" Register with an agent"));
|
|
47
|
+
console.log(pc.dim(" Claude Code:"));
|
|
48
|
+
console.log(` ${pc.cyan("claude mcp add vectorvesper -- npx -y vectorvesper mcp")}`);
|
|
49
|
+
console.log(pc.dim(" Cursor / Claude Desktop / other \u2014 add to the client's MCP config:"));
|
|
50
|
+
console.log(
|
|
51
|
+
CONFIG_SNIPPET.split("\n").map((l) => ` ${pc.dim(l)}`).join("\n")
|
|
52
|
+
);
|
|
53
|
+
console.log("");
|
|
54
|
+
console.log(
|
|
55
|
+
pc.dim(" Tools: list_hooks \xB7 get_hook \xB7 list_components \xB7 get_component \xB7 get_setup_guidance \xB7 search")
|
|
56
|
+
);
|
|
57
|
+
console.log("");
|
|
58
|
+
}
|
|
59
|
+
function printInteractiveHelp() {
|
|
60
|
+
console.log("");
|
|
61
|
+
console.log(pc.bold(pc.cyan(" Vector Vesper MCP server")));
|
|
62
|
+
console.log("");
|
|
63
|
+
console.log(" This command speaks the Model Context Protocol over stdin/stdout.");
|
|
64
|
+
console.log(" It is meant to be launched by an AI coding agent, not run by hand \u2014");
|
|
65
|
+
console.log(" started from a terminal it would just wait for a client that never connects.");
|
|
66
|
+
console.log("");
|
|
67
|
+
console.log(` ${pc.bold("Check your setup:")} ${pc.cyan("vv mcp status")}`);
|
|
68
|
+
console.log(` ${pc.bold("Add to Claude Code:")} ${pc.cyan("claude mcp add vectorvesper -- npx -y vectorvesper mcp")}`);
|
|
69
|
+
console.log("");
|
|
70
|
+
console.log(pc.dim(" To run the server here anyway (for debugging): vv mcp --stdio"));
|
|
71
|
+
console.log("");
|
|
72
|
+
}
|
|
73
|
+
async function mcpCommand(action, options = {}) {
|
|
74
|
+
if (action === "status" || action === "info") {
|
|
75
|
+
printStatus();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (action !== void 0) {
|
|
79
|
+
console.error(
|
|
80
|
+
`
|
|
81
|
+
${pc.red("\u2717")} Unknown argument "${action}" for \`vv mcp\`.
|
|
82
|
+
|
|
83
|
+
${pc.cyan("vv mcp")} start the MCP server (for agents)
|
|
84
|
+
${pc.cyan("vv mcp status")} check the setup and print client config
|
|
85
|
+
`
|
|
86
|
+
);
|
|
87
|
+
process.exitCode = 1;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (process.stdin.isTTY && !options.stdio) {
|
|
91
|
+
printInteractiveHelp();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
protectStdout();
|
|
95
|
+
const { startMcpServer } = await import("./server-5CFZ6BS7.js");
|
|
96
|
+
try {
|
|
97
|
+
await startMcpServer();
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.error(
|
|
100
|
+
`vectorvesper mcp: failed to start \u2014 ${error instanceof Error ? error.message : String(error)}`
|
|
101
|
+
);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export {
|
|
106
|
+
mcpCommand
|
|
107
|
+
};
|
|
@@ -1,51 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectProject,
|
|
3
|
-
fetchRegistryIndex
|
|
3
|
+
fetchRegistryIndex
|
|
4
|
+
} from "./chunk-HOJ3DQSV.js";
|
|
5
|
+
import {
|
|
6
|
+
findHook,
|
|
7
|
+
loadHookManifest
|
|
8
|
+
} from "./chunk-XN3PPCIM.js";
|
|
9
|
+
import {
|
|
4
10
|
getAuthToken
|
|
5
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-SFP5K3ZO.js";
|
|
6
12
|
|
|
7
13
|
// src/mcp/server.ts
|
|
8
14
|
import { z } from "zod";
|
|
9
|
-
|
|
10
|
-
// src/mcp/manifest.ts
|
|
11
|
-
import fs from "fs";
|
|
12
|
-
import path from "path";
|
|
13
|
-
import { fileURLToPath } from "url";
|
|
14
|
-
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
-
var CANDIDATES = [
|
|
16
|
-
path.join(__dirname, "hooks.json"),
|
|
17
|
-
path.join(__dirname, "../hooks.json"),
|
|
18
|
-
path.resolve(__dirname, "../../../registry/generated/hooks.lean.json"),
|
|
19
|
-
path.resolve(__dirname, "../../registry/generated/hooks.lean.json")
|
|
20
|
-
];
|
|
21
|
-
var cached = null;
|
|
22
|
-
function loadHookManifest() {
|
|
23
|
-
if (cached) return cached;
|
|
24
|
-
for (const candidate of CANDIDATES) {
|
|
25
|
-
if (!fs.existsSync(candidate)) continue;
|
|
26
|
-
try {
|
|
27
|
-
const parsed = JSON.parse(fs.readFileSync(candidate, "utf-8"));
|
|
28
|
-
if (Array.isArray(parsed?.hooks)) {
|
|
29
|
-
cached = parsed;
|
|
30
|
-
return cached;
|
|
31
|
-
}
|
|
32
|
-
} catch {
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
function findHook(name) {
|
|
38
|
-
const manifest = loadHookManifest();
|
|
39
|
-
if (!manifest) return null;
|
|
40
|
-
const wanted = name.toLowerCase();
|
|
41
|
-
return manifest.hooks.find((h) => h.name.toLowerCase() === wanted) ?? // Tolerate "sensor-bus" / "sensorbus" / "SensorBus" for "useSensorBus".
|
|
42
|
-
manifest.hooks.find(
|
|
43
|
-
(h) => h.name.toLowerCase().replace(/^use/, "") === wanted.replace(/^use/, "").replace(/-/g, "")
|
|
44
|
-
) ?? null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// src/mcp/server.ts
|
|
48
|
-
var VERSION = true ? "1.2.0" : "0.0.0-dev";
|
|
15
|
+
var VERSION = true ? "2.0.1" : "0.0.0-dev";
|
|
49
16
|
function text(body) {
|
|
50
17
|
return { content: [{ type: "text", text: body }] };
|
|
51
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vectorvesper",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Add WebGL, React Three Fiber & advanced motion components to your project via CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
"typecheck": "tsc --noEmit",
|
|
45
45
|
"test": "vitest run",
|
|
46
46
|
"test:watch": "vitest",
|
|
47
|
-
"postbuild": "node scripts/bundle-manifest.mjs"
|
|
47
|
+
"postbuild": "node scripts/bundle-manifest.mjs",
|
|
48
|
+
"prepublishOnly": "npm run build"
|
|
48
49
|
},
|
|
49
50
|
"dependencies": {
|
|
50
51
|
"@babel/core": "^7.24.0",
|
package/dist/mcp-DOUIUZGA.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// src/commands/mcp.ts
|
|
2
|
-
function protectStdout() {
|
|
3
|
-
const toStderr = (...args) => {
|
|
4
|
-
console.error(...args);
|
|
5
|
-
};
|
|
6
|
-
console.log = toStderr;
|
|
7
|
-
console.info = toStderr;
|
|
8
|
-
console.debug = toStderr;
|
|
9
|
-
}
|
|
10
|
-
async function mcpCommand() {
|
|
11
|
-
protectStdout();
|
|
12
|
-
const { startMcpServer } = await import("./server-7WN7N3ZG.js");
|
|
13
|
-
try {
|
|
14
|
-
await startMcpServer();
|
|
15
|
-
} catch (error) {
|
|
16
|
-
console.error(
|
|
17
|
-
`vectorvesper mcp: failed to start \u2014 ${error instanceof Error ? error.message : String(error)}`
|
|
18
|
-
);
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
export {
|
|
23
|
-
mcpCommand
|
|
24
|
-
};
|