@nikkory/vibe-cli 1.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2 -2
- package/dist/index.js +26 -1329
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -24,13 +24,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/index.ts
|
|
27
|
-
var
|
|
27
|
+
var import_commander4 = require("commander");
|
|
28
28
|
|
|
29
|
-
// src/commands/
|
|
29
|
+
// src/commands/init.ts
|
|
30
30
|
var fs = __toESM(require("fs/promises"));
|
|
31
31
|
var path = __toESM(require("path"));
|
|
32
32
|
var import_commander = require("commander");
|
|
33
|
-
var import_inquirer = __toESM(require("inquirer"));
|
|
34
33
|
|
|
35
34
|
// src/utils/logger.ts
|
|
36
35
|
var import_boxen = __toESM(require("boxen"));
|
|
@@ -176,766 +175,10 @@ var Logger = class {
|
|
|
176
175
|
};
|
|
177
176
|
var logger = new Logger();
|
|
178
177
|
|
|
179
|
-
// src/commands/add.ts
|
|
180
|
-
var AVAILABLE_COMPONENTS = [
|
|
181
|
-
"button",
|
|
182
|
-
"input",
|
|
183
|
-
"card",
|
|
184
|
-
"badge",
|
|
185
|
-
"toast",
|
|
186
|
-
"modal",
|
|
187
|
-
"dropdown",
|
|
188
|
-
"tabs",
|
|
189
|
-
"accordion",
|
|
190
|
-
"avatar"
|
|
191
|
-
];
|
|
192
|
-
var COLORS = [
|
|
193
|
-
"primary",
|
|
194
|
-
"secondary",
|
|
195
|
-
"success",
|
|
196
|
-
"warning",
|
|
197
|
-
"error",
|
|
198
|
-
"info",
|
|
199
|
-
"blue",
|
|
200
|
-
"red",
|
|
201
|
-
"green",
|
|
202
|
-
"yellow",
|
|
203
|
-
"purple",
|
|
204
|
-
"gray",
|
|
205
|
-
"orange",
|
|
206
|
-
"amber",
|
|
207
|
-
"lime",
|
|
208
|
-
"emerald",
|
|
209
|
-
"teal",
|
|
210
|
-
"cyan",
|
|
211
|
-
"sky",
|
|
212
|
-
"indigo",
|
|
213
|
-
"violet",
|
|
214
|
-
"fuchsia",
|
|
215
|
-
"pink",
|
|
216
|
-
"rose",
|
|
217
|
-
"slate",
|
|
218
|
-
"zinc",
|
|
219
|
-
"neutral",
|
|
220
|
-
"stone"
|
|
221
|
-
];
|
|
222
|
-
var SIZES = ["xs", "sm", "md", "lg", "xl", "2xl"];
|
|
223
|
-
var VARIANTS = {
|
|
224
|
-
button: ["solid", "outline", "ghost", "soft", "link"],
|
|
225
|
-
input: ["outlined", "filled", "underlined", "ghost"],
|
|
226
|
-
card: ["elevated", "outlined", "filled", "ghost"],
|
|
227
|
-
badge: ["solid", "soft", "outline", "dot"],
|
|
228
|
-
toast: ["solid", "soft", "outlined", "minimal"]
|
|
229
|
-
};
|
|
230
|
-
var SHAPES = ["square", "rounded", "pill", "circle"];
|
|
231
|
-
var POSITIONS = [
|
|
232
|
-
"top-left",
|
|
233
|
-
"top-center",
|
|
234
|
-
"top-right",
|
|
235
|
-
"bottom-left",
|
|
236
|
-
"bottom-center",
|
|
237
|
-
"bottom-right",
|
|
238
|
-
"left",
|
|
239
|
-
"center",
|
|
240
|
-
"right"
|
|
241
|
-
];
|
|
242
|
-
var ANIMATIONS = ["none", "subtle", "standard", "smooth", "bounce", "pulse"];
|
|
243
|
-
var ELEVATIONS = ["none", "xs", "sm", "md", "lg", "xl", "2xl", "glow"];
|
|
244
|
-
var A11Y_LEVELS = ["standard", "enhanced", "maximum"];
|
|
245
|
-
var PRESETS = {
|
|
246
|
-
primary: { color: "blue", variant: "solid", size: "md" },
|
|
247
|
-
secondary: { color: "gray", variant: "outline", size: "md" },
|
|
248
|
-
danger: { color: "red", variant: "solid", size: "md" },
|
|
249
|
-
success: { color: "green", variant: "solid", size: "md" },
|
|
250
|
-
warning: { color: "yellow", variant: "solid", size: "md" },
|
|
251
|
-
ghost: { color: "gray", variant: "ghost", size: "md" },
|
|
252
|
-
pill: { color: "blue", variant: "solid", shape: "pill", size: "md" },
|
|
253
|
-
large: { color: "blue", variant: "solid", size: "lg" },
|
|
254
|
-
small: { color: "blue", variant: "solid", size: "sm" }
|
|
255
|
-
};
|
|
256
|
-
var addCommand = new import_commander.Command("add").description("Add a component with variant configuration").argument("[component]", "Component to add (button, input, card, etc.)").option("-c, --color <color>", "Color theme", "blue").option("-s, --size <size>", "Component size", "md").option("-v, --variant <variant>", "Visual style").option("--shape <shape>", "Border radius style", "rounded").option("-p, --position <position>", "Position (for toast, modal)").option("-a, --animation <animation>", "Animation style", "standard").option("-e, --elevation <elevation>", "Shadow depth", "md").option("--a11y <level>", "Accessibility level", "standard").option("--preset <preset>", "Use a preset configuration").option("-i, --interactive", "Interactive mode").option("-o, --output <path>", "Output directory", "./components").option("--dry-run", "Preview without writing files").action(async (component, options) => {
|
|
257
|
-
try {
|
|
258
|
-
logger.header("\u{1F3A8} Nikkory Vibe - Add Component");
|
|
259
|
-
if (options.interactive || !component) {
|
|
260
|
-
const config = await promptVariantConfig();
|
|
261
|
-
component = config.component;
|
|
262
|
-
Object.assign(options, config);
|
|
263
|
-
}
|
|
264
|
-
if (!component || !AVAILABLE_COMPONENTS.includes(component)) {
|
|
265
|
-
logger.error(`Unknown component: ${component ?? "none"}`);
|
|
266
|
-
logger.info(`Available: ${AVAILABLE_COMPONENTS.join(", ")}`);
|
|
267
|
-
process.exit(1);
|
|
268
|
-
}
|
|
269
|
-
const validatedComponent = component;
|
|
270
|
-
if (options.preset) {
|
|
271
|
-
const preset = PRESETS[options.preset];
|
|
272
|
-
if (!preset) {
|
|
273
|
-
logger.error(`Unknown preset: ${options.preset}`);
|
|
274
|
-
logger.info(`Available: ${Object.keys(PRESETS).join(", ")}`);
|
|
275
|
-
process.exit(1);
|
|
276
|
-
}
|
|
277
|
-
Object.assign(options, preset);
|
|
278
|
-
}
|
|
279
|
-
if (options.color && !COLORS.includes(options.color)) {
|
|
280
|
-
logger.warn(`Unknown color: ${options.color}. Using default.`);
|
|
281
|
-
}
|
|
282
|
-
if (options.size && !SIZES.includes(options.size)) {
|
|
283
|
-
logger.warn(`Unknown size: ${options.size}. Using default.`);
|
|
284
|
-
}
|
|
285
|
-
if (options.position && !POSITIONS.includes(options.position)) {
|
|
286
|
-
logger.warn(`Unknown position: ${options.position}. Using default.`);
|
|
287
|
-
}
|
|
288
|
-
if (options.a11y && !A11Y_LEVELS.includes(options.a11y)) {
|
|
289
|
-
logger.warn(`Unknown accessibility level: ${options.a11y}. Using default.`);
|
|
290
|
-
}
|
|
291
|
-
logger.newline();
|
|
292
|
-
logger.info(`Component: ${validatedComponent}`);
|
|
293
|
-
logger.info(`Color: ${options.color ?? "default"}`);
|
|
294
|
-
logger.info(`Size: ${options.size ?? "default"}`);
|
|
295
|
-
logger.info(`Variant: ${options.variant ?? "default"}`);
|
|
296
|
-
logger.info(`Shape: ${options.shape ?? "default"}`);
|
|
297
|
-
if (options.position) {
|
|
298
|
-
logger.info(`Position: ${options.position}`);
|
|
299
|
-
}
|
|
300
|
-
logger.info(`Animation: ${options.animation ?? "default"}`);
|
|
301
|
-
logger.info(`Elevation: ${options.elevation ?? "default"}`);
|
|
302
|
-
logger.info(`Accessibility: ${options.a11y ?? "default"}`);
|
|
303
|
-
logger.newline();
|
|
304
|
-
logger.startSpinner("Generating component...");
|
|
305
|
-
const variantConfig = {
|
|
306
|
-
color: options.color,
|
|
307
|
-
size: options.size,
|
|
308
|
-
variant: options.variant,
|
|
309
|
-
shape: options.shape,
|
|
310
|
-
position: options.position,
|
|
311
|
-
animation: options.animation,
|
|
312
|
-
elevation: options.elevation,
|
|
313
|
-
a11y: options.a11y
|
|
314
|
-
};
|
|
315
|
-
const code = generateComponentCode(validatedComponent, variantConfig);
|
|
316
|
-
logger.stopSpinnerSuccess("Component generated");
|
|
317
|
-
if (options.dryRun) {
|
|
318
|
-
logger.newline();
|
|
319
|
-
logger.header("Generated Code (Preview)");
|
|
320
|
-
logger.code(code);
|
|
321
|
-
logger.newline();
|
|
322
|
-
logger.info("Dry run mode - No files written");
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
const componentName = capitalize(validatedComponent);
|
|
326
|
-
const outputPath = path.join(process.cwd(), options.output, `${componentName}.tsx`);
|
|
327
|
-
logger.startSpinner(`Writing to ${outputPath}...`);
|
|
328
|
-
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
|
329
|
-
await fs.writeFile(outputPath, code, "utf-8");
|
|
330
|
-
logger.stopSpinnerSuccess(`Created: ${outputPath}`);
|
|
331
|
-
logger.newline();
|
|
332
|
-
logger.box(
|
|
333
|
-
`\u2728 ${componentName} component added!
|
|
334
|
-
|
|
335
|
-
File: ${outputPath}
|
|
336
|
-
Color: ${options.color ?? "default"}
|
|
337
|
-
Size: ${options.size ?? "default"}`,
|
|
338
|
-
{ title: "Success", borderColor: "green" }
|
|
339
|
-
);
|
|
340
|
-
logger.newline();
|
|
341
|
-
logger.info("Usage:");
|
|
342
|
-
logger.code(` import { ${componentName} } from './components/${componentName}';`);
|
|
343
|
-
logger.code(
|
|
344
|
-
` <${componentName} color="${options.color ?? "primary"}" size="${options.size ?? "md"}" />`
|
|
345
|
-
);
|
|
346
|
-
logger.newline();
|
|
347
|
-
} catch (error) {
|
|
348
|
-
logger.stopSpinner();
|
|
349
|
-
logger.error("Failed to add component");
|
|
350
|
-
if (error instanceof Error) {
|
|
351
|
-
logger.debug(error.stack || error.message);
|
|
352
|
-
}
|
|
353
|
-
process.exit(1);
|
|
354
|
-
}
|
|
355
|
-
});
|
|
356
|
-
async function promptVariantConfig() {
|
|
357
|
-
const answers = await import_inquirer.default.prompt([
|
|
358
|
-
{
|
|
359
|
-
type: "list",
|
|
360
|
-
name: "component",
|
|
361
|
-
message: "Select component:",
|
|
362
|
-
choices: AVAILABLE_COMPONENTS.map((c) => ({ name: capitalize(c), value: c }))
|
|
363
|
-
},
|
|
364
|
-
{
|
|
365
|
-
type: "list",
|
|
366
|
-
name: "color",
|
|
367
|
-
message: "Color:",
|
|
368
|
-
choices: [
|
|
369
|
-
new import_inquirer.default.Separator("--- Semantic ---"),
|
|
370
|
-
{ name: "Primary (Blue)", value: "primary" },
|
|
371
|
-
{ name: "Secondary (Purple)", value: "secondary" },
|
|
372
|
-
{ name: "Success (Green)", value: "success" },
|
|
373
|
-
{ name: "Warning (Yellow)", value: "warning" },
|
|
374
|
-
{ name: "Error (Red)", value: "error" },
|
|
375
|
-
{ name: "Info (Cyan)", value: "info" },
|
|
376
|
-
new import_inquirer.default.Separator("--- Palette ---"),
|
|
377
|
-
{ name: "Blue", value: "blue" },
|
|
378
|
-
{ name: "Red", value: "red" },
|
|
379
|
-
{ name: "Green", value: "green" },
|
|
380
|
-
{ name: "Yellow", value: "yellow" },
|
|
381
|
-
{ name: "Purple", value: "purple" },
|
|
382
|
-
{ name: "Gray", value: "gray" },
|
|
383
|
-
{ name: "Orange", value: "orange" },
|
|
384
|
-
{ name: "Pink", value: "pink" }
|
|
385
|
-
],
|
|
386
|
-
default: "blue"
|
|
387
|
-
},
|
|
388
|
-
{
|
|
389
|
-
type: "list",
|
|
390
|
-
name: "size",
|
|
391
|
-
message: "Size:",
|
|
392
|
-
choices: [
|
|
393
|
-
{ name: "Extra Small (xs)", value: "xs" },
|
|
394
|
-
{ name: "Small (sm)", value: "sm" },
|
|
395
|
-
{ name: "Medium (md)", value: "md" },
|
|
396
|
-
{ name: "Large (lg)", value: "lg" },
|
|
397
|
-
{ name: "Extra Large (xl)", value: "xl" },
|
|
398
|
-
{ name: "2X Large (2xl)", value: "2xl" }
|
|
399
|
-
],
|
|
400
|
-
default: "md"
|
|
401
|
-
},
|
|
402
|
-
{
|
|
403
|
-
type: "list",
|
|
404
|
-
name: "variant",
|
|
405
|
-
message: "Variant:",
|
|
406
|
-
choices: (answers2) => {
|
|
407
|
-
const comp = answers2.component;
|
|
408
|
-
return (VARIANTS[comp] || ["solid", "outline", "ghost"]).map((v) => ({
|
|
409
|
-
name: capitalize(v),
|
|
410
|
-
value: v
|
|
411
|
-
}));
|
|
412
|
-
}
|
|
413
|
-
},
|
|
414
|
-
{
|
|
415
|
-
type: "list",
|
|
416
|
-
name: "shape",
|
|
417
|
-
message: "Shape:",
|
|
418
|
-
choices: SHAPES.map((s) => ({ name: capitalize(s), value: s })),
|
|
419
|
-
default: "rounded"
|
|
420
|
-
},
|
|
421
|
-
{
|
|
422
|
-
type: "list",
|
|
423
|
-
name: "animation",
|
|
424
|
-
message: "Animation:",
|
|
425
|
-
choices: ANIMATIONS.map((a) => ({ name: capitalize(a), value: a })),
|
|
426
|
-
default: "standard"
|
|
427
|
-
},
|
|
428
|
-
{
|
|
429
|
-
type: "list",
|
|
430
|
-
name: "elevation",
|
|
431
|
-
message: "Elevation/Shadow:",
|
|
432
|
-
choices: ELEVATIONS.map((e) => ({ name: e === "none" ? "None" : e.toUpperCase(), value: e })),
|
|
433
|
-
default: "md"
|
|
434
|
-
}
|
|
435
|
-
]);
|
|
436
|
-
return answers;
|
|
437
|
-
}
|
|
438
|
-
function capitalize(str) {
|
|
439
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
440
|
-
}
|
|
441
|
-
function generateComponentCode(component, config) {
|
|
442
|
-
const name = capitalize(component);
|
|
443
|
-
const propsInterface = `${name}Props`;
|
|
444
|
-
return `/**
|
|
445
|
-
* ${name} Component
|
|
446
|
-
*
|
|
447
|
-
* Generated with Nikkory Vibe CLI
|
|
448
|
-
* Configuration: color=${config.color}, size=${config.size}, variant=${config.variant || "default"}
|
|
449
|
-
*/
|
|
450
|
-
|
|
451
|
-
'use client';
|
|
452
|
-
|
|
453
|
-
import React, { forwardRef } from 'react';
|
|
454
|
-
import { ${name} as Vibe${name} } from '@nikkory/vibe-library/core';
|
|
455
|
-
|
|
456
|
-
export interface ${propsInterface} {
|
|
457
|
-
children?: React.ReactNode;
|
|
458
|
-
className?: string;
|
|
459
|
-
// Override default config
|
|
460
|
-
color?: string;
|
|
461
|
-
size?: string;
|
|
462
|
-
variant?: string;
|
|
463
|
-
shape?: string;
|
|
464
|
-
animation?: string;
|
|
465
|
-
elevation?: string;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* Pre-configured ${name} with:
|
|
470
|
-
* - Color: ${config.color}
|
|
471
|
-
* - Size: ${config.size}
|
|
472
|
-
* - Variant: ${config.variant || "default"}
|
|
473
|
-
* - Shape: ${config.shape}
|
|
474
|
-
* - Animation: ${config.animation}
|
|
475
|
-
* - Elevation: ${config.elevation}
|
|
476
|
-
*/
|
|
477
|
-
export const ${name} = forwardRef<HTMLElement, ${propsInterface}>(
|
|
478
|
-
(
|
|
479
|
-
{
|
|
480
|
-
children,
|
|
481
|
-
className = '',
|
|
482
|
-
color = '${config.color}',
|
|
483
|
-
size = '${config.size}',
|
|
484
|
-
variant = '${config.variant || "solid"}',
|
|
485
|
-
shape = '${config.shape}',
|
|
486
|
-
animation = '${config.animation}',
|
|
487
|
-
elevation = '${config.elevation}',
|
|
488
|
-
...props
|
|
489
|
-
},
|
|
490
|
-
ref
|
|
491
|
-
) => {
|
|
492
|
-
return (
|
|
493
|
-
<Vibe${name}
|
|
494
|
-
ref={ref}
|
|
495
|
-
color={color}
|
|
496
|
-
size={size}
|
|
497
|
-
variant={variant}
|
|
498
|
-
shape={shape}
|
|
499
|
-
animation={animation}
|
|
500
|
-
elevation={elevation}
|
|
501
|
-
className={className}
|
|
502
|
-
{...props}
|
|
503
|
-
>
|
|
504
|
-
{children}
|
|
505
|
-
</Vibe${name}>
|
|
506
|
-
);
|
|
507
|
-
}
|
|
508
|
-
);
|
|
509
|
-
|
|
510
|
-
${name}.displayName = '${name}';
|
|
511
|
-
|
|
512
|
-
export default ${name};
|
|
513
|
-
`;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// src/commands/copy.ts
|
|
517
|
-
var fsSync = __toESM(require("fs"));
|
|
518
|
-
var fs2 = __toESM(require("fs/promises"));
|
|
519
|
-
var path2 = __toESM(require("path"));
|
|
520
|
-
var import_commander2 = require("commander");
|
|
521
|
-
var DESIGN_SYSTEMS = [
|
|
522
|
-
"material-design",
|
|
523
|
-
"ios-hig",
|
|
524
|
-
"glassmorphism",
|
|
525
|
-
"neumorphism",
|
|
526
|
-
"minimalism",
|
|
527
|
-
"brutalism"
|
|
528
|
-
];
|
|
529
|
-
var TIERS = ["basic", "standard", "enterprise"];
|
|
530
|
-
var COMPONENTS = [
|
|
531
|
-
// Core
|
|
532
|
-
"button",
|
|
533
|
-
"input",
|
|
534
|
-
"textarea",
|
|
535
|
-
"select",
|
|
536
|
-
"checkbox",
|
|
537
|
-
"radio",
|
|
538
|
-
"switch",
|
|
539
|
-
"slider",
|
|
540
|
-
// Display
|
|
541
|
-
"badge",
|
|
542
|
-
"avatar",
|
|
543
|
-
"card",
|
|
544
|
-
"tooltip",
|
|
545
|
-
"popover",
|
|
546
|
-
// Feedback
|
|
547
|
-
"alert",
|
|
548
|
-
"toast",
|
|
549
|
-
"progress",
|
|
550
|
-
"spinner",
|
|
551
|
-
"skeleton",
|
|
552
|
-
// Navigation
|
|
553
|
-
"tabs",
|
|
554
|
-
"breadcrumb",
|
|
555
|
-
"pagination",
|
|
556
|
-
"stepper",
|
|
557
|
-
"menu",
|
|
558
|
-
// Overlay
|
|
559
|
-
"modal",
|
|
560
|
-
"drawer",
|
|
561
|
-
"dropdown",
|
|
562
|
-
"dialog",
|
|
563
|
-
// Data
|
|
564
|
-
"table",
|
|
565
|
-
"list",
|
|
566
|
-
"tree",
|
|
567
|
-
"timeline",
|
|
568
|
-
// Media
|
|
569
|
-
"image",
|
|
570
|
-
"video",
|
|
571
|
-
"audio",
|
|
572
|
-
"carousel",
|
|
573
|
-
"gallery",
|
|
574
|
-
// Form
|
|
575
|
-
"form",
|
|
576
|
-
"field",
|
|
577
|
-
"label",
|
|
578
|
-
"error-message",
|
|
579
|
-
// Layout
|
|
580
|
-
"container",
|
|
581
|
-
"grid",
|
|
582
|
-
"flex",
|
|
583
|
-
"divider",
|
|
584
|
-
"spacer",
|
|
585
|
-
// Typography
|
|
586
|
-
"heading",
|
|
587
|
-
"text",
|
|
588
|
-
"link",
|
|
589
|
-
"code",
|
|
590
|
-
// Charts
|
|
591
|
-
"chart",
|
|
592
|
-
"sparkline",
|
|
593
|
-
"gauge",
|
|
594
|
-
// Special
|
|
595
|
-
"rating",
|
|
596
|
-
"transfer",
|
|
597
|
-
"color-picker",
|
|
598
|
-
"date-picker",
|
|
599
|
-
"file-upload"
|
|
600
|
-
];
|
|
601
|
-
var DESIGN_ALIASES = {
|
|
602
|
-
material: "material-design",
|
|
603
|
-
md: "material-design",
|
|
604
|
-
ios: "ios-hig",
|
|
605
|
-
hig: "ios-hig",
|
|
606
|
-
glass: "glassmorphism",
|
|
607
|
-
neu: "neumorphism",
|
|
608
|
-
neomorphism: "neumorphism",
|
|
609
|
-
minimal: "minimalism",
|
|
610
|
-
min: "minimalism",
|
|
611
|
-
brutal: "brutalism"
|
|
612
|
-
};
|
|
613
|
-
var copyCommand = new import_commander2.Command("copy").alias("cp").description("Copy pre-built components from the library (zero-token)").argument(
|
|
614
|
-
"[component]",
|
|
615
|
-
"Component to copy (button, card, etc. or path like button/glassmorphism/enterprise)"
|
|
616
|
-
).option("-d, --design <design>", "Design system", "material-design").option("-t, --tier <tier>", "Quality tier", "standard").option("-o, --output <path>", "Output directory", "./components").option("--overwrite", "Overwrite existing files").option("--dry-run", "Preview without copying").option("--all", "Copy all components for the design/tier").action(async (component, options) => {
|
|
617
|
-
try {
|
|
618
|
-
logger.header("\u{1F4CB} Nikkory Vibe - Zero-Token Copy");
|
|
619
|
-
if (options.all) {
|
|
620
|
-
await copyAllComponents(options);
|
|
621
|
-
return;
|
|
622
|
-
}
|
|
623
|
-
if (!component) {
|
|
624
|
-
logger.error("Please specify a component to copy");
|
|
625
|
-
logger.newline();
|
|
626
|
-
logger.info("Usage:");
|
|
627
|
-
logger.code(" vibe copy button");
|
|
628
|
-
logger.code(" vibe copy button/glassmorphism");
|
|
629
|
-
logger.code(" vibe copy button/glassmorphism/enterprise");
|
|
630
|
-
logger.code(" vibe copy --all --design=brutalism");
|
|
631
|
-
logger.newline();
|
|
632
|
-
logger.info("Available components:");
|
|
633
|
-
logger.code(` ${COMPONENTS.slice(0, 10).join(", ")}...`);
|
|
634
|
-
logger.info(` Run 'vibe list templates' for full list`);
|
|
635
|
-
process.exit(1);
|
|
636
|
-
}
|
|
637
|
-
const parsed = parseComponentPath(component, options);
|
|
638
|
-
if (!validateComponentPath(parsed)) {
|
|
639
|
-
process.exit(1);
|
|
640
|
-
}
|
|
641
|
-
logger.newline();
|
|
642
|
-
logger.info(`Component: ${capitalize2(parsed.component)}`);
|
|
643
|
-
logger.info(`Design System: ${formatDesignSystem(parsed.designSystem)}`);
|
|
644
|
-
logger.info(`Tier: ${capitalize2(parsed.tier)}`);
|
|
645
|
-
logger.newline();
|
|
646
|
-
await copyComponent(parsed, options);
|
|
647
|
-
} catch (error) {
|
|
648
|
-
logger.stopSpinner();
|
|
649
|
-
logger.error("Copy failed");
|
|
650
|
-
if (error instanceof Error) {
|
|
651
|
-
logger.debug(error.stack || error.message);
|
|
652
|
-
}
|
|
653
|
-
process.exit(1);
|
|
654
|
-
}
|
|
655
|
-
});
|
|
656
|
-
function parseComponentPath(input, options) {
|
|
657
|
-
const parts = input.split("/").filter(Boolean);
|
|
658
|
-
const component = parts[0] ?? "";
|
|
659
|
-
let designSystem = options.design ?? "material-design";
|
|
660
|
-
let tier = options.tier ?? "standard";
|
|
661
|
-
if (parts.length === 2 && parts[1]) {
|
|
662
|
-
designSystem = normalizeDesignSystem(parts[1]);
|
|
663
|
-
} else if (parts.length >= 3 && parts[1] && parts[2]) {
|
|
664
|
-
designSystem = normalizeDesignSystem(parts[1]);
|
|
665
|
-
tier = parts[2];
|
|
666
|
-
}
|
|
667
|
-
designSystem = normalizeDesignSystem(designSystem);
|
|
668
|
-
return { component, designSystem, tier };
|
|
669
|
-
}
|
|
670
|
-
function normalizeDesignSystem(design) {
|
|
671
|
-
const lower = design.toLowerCase();
|
|
672
|
-
return DESIGN_ALIASES[lower] || lower;
|
|
673
|
-
}
|
|
674
|
-
function validateComponentPath(parsed) {
|
|
675
|
-
if (!COMPONENTS.includes(parsed.component)) {
|
|
676
|
-
logger.error(`Unknown component: ${parsed.component}`);
|
|
677
|
-
logger.info(`Available: ${COMPONENTS.slice(0, 8).join(", ")}...`);
|
|
678
|
-
return false;
|
|
679
|
-
}
|
|
680
|
-
if (!DESIGN_SYSTEMS.includes(parsed.designSystem)) {
|
|
681
|
-
logger.error(`Unknown design system: ${parsed.designSystem}`);
|
|
682
|
-
logger.info(`Available: ${DESIGN_SYSTEMS.join(", ")}`);
|
|
683
|
-
return false;
|
|
684
|
-
}
|
|
685
|
-
if (!TIERS.includes(parsed.tier)) {
|
|
686
|
-
logger.error(`Unknown tier: ${parsed.tier}`);
|
|
687
|
-
logger.info(`Available: ${TIERS.join(", ")}`);
|
|
688
|
-
return false;
|
|
689
|
-
}
|
|
690
|
-
return true;
|
|
691
|
-
}
|
|
692
|
-
async function copyComponent(parsed, options) {
|
|
693
|
-
const { component, designSystem, tier } = parsed;
|
|
694
|
-
const libraryRoot = findLibraryRoot();
|
|
695
|
-
const sourcePath = path2.join(
|
|
696
|
-
libraryRoot,
|
|
697
|
-
"src",
|
|
698
|
-
"components",
|
|
699
|
-
component,
|
|
700
|
-
designSystem,
|
|
701
|
-
`${tier}.tsx`
|
|
702
|
-
);
|
|
703
|
-
const sourceExists = await fileExists(sourcePath);
|
|
704
|
-
if (!sourceExists) {
|
|
705
|
-
logger.error(`Component not found: ${sourcePath}`);
|
|
706
|
-
logger.info("This component may not be available yet.");
|
|
707
|
-
logger.info("Run `vibe list templates` to see available components.");
|
|
708
|
-
process.exit(1);
|
|
709
|
-
}
|
|
710
|
-
const outputDir = path2.join(process.cwd(), options.output || "./components");
|
|
711
|
-
const fileName = `${capitalize2(component)}.tsx`;
|
|
712
|
-
const outputPath = path2.join(outputDir, fileName);
|
|
713
|
-
const outputExists = await fileExists(outputPath);
|
|
714
|
-
if (outputExists && !options.overwrite) {
|
|
715
|
-
logger.error(`File already exists: ${outputPath}`);
|
|
716
|
-
logger.info("Use --overwrite to replace it");
|
|
717
|
-
process.exit(1);
|
|
718
|
-
}
|
|
719
|
-
logger.startSpinner(`Reading ${component}...`);
|
|
720
|
-
const sourceCode = await fs2.readFile(sourcePath, "utf-8");
|
|
721
|
-
logger.stopSpinnerSuccess("Source loaded");
|
|
722
|
-
const transformedCode = transformComponent(sourceCode, parsed);
|
|
723
|
-
if (options.dryRun) {
|
|
724
|
-
logger.newline();
|
|
725
|
-
logger.header("Preview (Dry Run)");
|
|
726
|
-
logger.code(`${transformedCode.slice(0, 1e3)}
|
|
727
|
-
...`);
|
|
728
|
-
logger.newline();
|
|
729
|
-
logger.info(`Would write to: ${outputPath}`);
|
|
730
|
-
logger.info(`Lines: ${transformedCode.split("\n").length}`);
|
|
731
|
-
return;
|
|
732
|
-
}
|
|
733
|
-
logger.startSpinner(`Writing to ${outputPath}...`);
|
|
734
|
-
await fs2.mkdir(outputDir, { recursive: true });
|
|
735
|
-
await fs2.writeFile(outputPath, transformedCode, "utf-8");
|
|
736
|
-
logger.stopSpinnerSuccess("Component copied");
|
|
737
|
-
logger.newline();
|
|
738
|
-
logger.box(
|
|
739
|
-
`\u2728 ${capitalize2(component)} copied successfully!
|
|
740
|
-
|
|
741
|
-
File: ${outputPath}
|
|
742
|
-
Design: ${formatDesignSystem(designSystem)}
|
|
743
|
-
Tier: ${capitalize2(tier)}
|
|
744
|
-
Lines: ${transformedCode.split("\n").length}`,
|
|
745
|
-
{ title: "Success", borderColor: "green" }
|
|
746
|
-
);
|
|
747
|
-
logger.newline();
|
|
748
|
-
logger.info("Usage:");
|
|
749
|
-
logger.code(
|
|
750
|
-
` import { ${capitalize2(component)} } from './components/${capitalize2(component)}';`
|
|
751
|
-
);
|
|
752
|
-
logger.newline();
|
|
753
|
-
}
|
|
754
|
-
async function copyAllComponents(options) {
|
|
755
|
-
const designSystem = normalizeDesignSystem(options.design || "material-design");
|
|
756
|
-
const tier = options.tier || "standard";
|
|
757
|
-
logger.newline();
|
|
758
|
-
logger.info(`Copying all components...`);
|
|
759
|
-
logger.info(`Design System: ${formatDesignSystem(designSystem)}`);
|
|
760
|
-
logger.info(`Tier: ${capitalize2(tier)}`);
|
|
761
|
-
logger.newline();
|
|
762
|
-
const libraryRoot = findLibraryRoot();
|
|
763
|
-
let copied = 0;
|
|
764
|
-
let skipped = 0;
|
|
765
|
-
const errors = [];
|
|
766
|
-
for (const component of COMPONENTS) {
|
|
767
|
-
const sourcePath = path2.join(
|
|
768
|
-
libraryRoot,
|
|
769
|
-
"src",
|
|
770
|
-
"components",
|
|
771
|
-
component,
|
|
772
|
-
designSystem,
|
|
773
|
-
`${tier}.tsx`
|
|
774
|
-
);
|
|
775
|
-
const exists = await fileExists(sourcePath);
|
|
776
|
-
if (!exists) {
|
|
777
|
-
skipped++;
|
|
778
|
-
continue;
|
|
779
|
-
}
|
|
780
|
-
try {
|
|
781
|
-
await copyComponent({ component, designSystem, tier }, { ...options, all: false });
|
|
782
|
-
copied++;
|
|
783
|
-
} catch (error) {
|
|
784
|
-
errors.push(component);
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
logger.newline();
|
|
788
|
-
logger.box(
|
|
789
|
-
`\u{1F4E6} Bulk Copy Complete
|
|
790
|
-
|
|
791
|
-
Copied: ${copied} components
|
|
792
|
-
Skipped: ${skipped} (not available)
|
|
793
|
-
Errors: ${errors.length}`,
|
|
794
|
-
{ title: "Summary", borderColor: copied > 0 ? "green" : "yellow" }
|
|
795
|
-
);
|
|
796
|
-
if (errors.length > 0) {
|
|
797
|
-
logger.warn(`Failed: ${errors.join(", ")}`);
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
function transformComponent(code, parsed) {
|
|
801
|
-
const { component, designSystem, tier } = parsed;
|
|
802
|
-
const header = `/**
|
|
803
|
-
* ${capitalize2(component)} Component
|
|
804
|
-
*
|
|
805
|
-
* Copied from @nikkory/vibe-library
|
|
806
|
-
* Design System: ${formatDesignSystem(designSystem)}
|
|
807
|
-
* Tier: ${capitalize2(tier)}
|
|
808
|
-
*
|
|
809
|
-
* Zero-token generation - No AI needed
|
|
810
|
-
* Just copy, paste, and customize!
|
|
811
|
-
*/
|
|
812
|
-
|
|
813
|
-
`;
|
|
814
|
-
let transformed = code;
|
|
815
|
-
transformed = transformed.replace(/from ['"]@nikkory\/vibe-library\/core['"]/g, "from './core'");
|
|
816
|
-
transformed = transformed.replace(/from ['"]@nikkory\/vibe-library['"]/g, "from './index'");
|
|
817
|
-
if (!transformed.includes("'use client'")) {
|
|
818
|
-
transformed = `'use client';
|
|
819
|
-
|
|
820
|
-
${transformed}`;
|
|
821
|
-
}
|
|
822
|
-
return `${header}${transformed}`;
|
|
823
|
-
}
|
|
824
|
-
function findLibraryRoot() {
|
|
825
|
-
const possiblePaths = [
|
|
826
|
-
path2.join(process.cwd(), "node_modules", "@nikkory", "vibe-library"),
|
|
827
|
-
path2.join(process.cwd(), "..", "..", "packages", "library"),
|
|
828
|
-
path2.join(__dirname, "..", "..", "..", "library"),
|
|
829
|
-
// Development path
|
|
830
|
-
"m:/AI Workspace/nikkory-vibe/packages/library"
|
|
831
|
-
];
|
|
832
|
-
for (const p of possiblePaths) {
|
|
833
|
-
try {
|
|
834
|
-
fsSync.accessSync(p);
|
|
835
|
-
return p;
|
|
836
|
-
} catch {
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
return possiblePaths[possiblePaths.length - 1] ?? "m:/AI Workspace/nikkory-vibe/packages/library";
|
|
840
|
-
}
|
|
841
|
-
async function fileExists(filePath) {
|
|
842
|
-
try {
|
|
843
|
-
await fs2.access(filePath);
|
|
844
|
-
return true;
|
|
845
|
-
} catch {
|
|
846
|
-
return false;
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
function capitalize2(str) {
|
|
850
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
851
|
-
}
|
|
852
|
-
function formatDesignSystem(design) {
|
|
853
|
-
const names = {
|
|
854
|
-
"material-design": "Material Design",
|
|
855
|
-
"ios-hig": "iOS HIG",
|
|
856
|
-
glassmorphism: "Glassmorphism",
|
|
857
|
-
neumorphism: "Neumorphism",
|
|
858
|
-
minimalism: "Minimalism",
|
|
859
|
-
brutalism: "Brutalism"
|
|
860
|
-
};
|
|
861
|
-
return names[design] || capitalize2(design);
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
// src/commands/generate.ts
|
|
865
|
-
var fs3 = __toESM(require("fs/promises"));
|
|
866
|
-
var path3 = __toESM(require("path"));
|
|
867
|
-
var import_vibe_core = require("@nikkory/vibe-core");
|
|
868
|
-
var import_commander3 = require("commander");
|
|
869
|
-
|
|
870
178
|
// src/utils/prompts.ts
|
|
871
|
-
var
|
|
872
|
-
async function promptComponentConfig() {
|
|
873
|
-
const answers = await import_inquirer2.default.prompt([
|
|
874
|
-
{
|
|
875
|
-
type: "input",
|
|
876
|
-
name: "name",
|
|
877
|
-
message: "Component name (PascalCase):",
|
|
878
|
-
validate: (input) => {
|
|
879
|
-
if (!input) return "Component name is required";
|
|
880
|
-
if (!/^[A-Z][a-zA-Z0-9]*$/.test(input)) {
|
|
881
|
-
return "Component name must be PascalCase (e.g., MyButton)";
|
|
882
|
-
}
|
|
883
|
-
return true;
|
|
884
|
-
}
|
|
885
|
-
},
|
|
886
|
-
{
|
|
887
|
-
type: "list",
|
|
888
|
-
name: "template",
|
|
889
|
-
message: "Template type:",
|
|
890
|
-
choices: [
|
|
891
|
-
{ name: "Button", value: "button" },
|
|
892
|
-
{ name: "Card", value: "card" },
|
|
893
|
-
{ name: "Input", value: "input" },
|
|
894
|
-
{ name: "Modal", value: "modal" },
|
|
895
|
-
{ name: "Table", value: "table" }
|
|
896
|
-
]
|
|
897
|
-
},
|
|
898
|
-
{
|
|
899
|
-
type: "list",
|
|
900
|
-
name: "designSystem",
|
|
901
|
-
message: "Design system:",
|
|
902
|
-
choices: [
|
|
903
|
-
{ name: "Material Design 3", value: "material-design" },
|
|
904
|
-
{ name: "iOS Human Interface Guidelines", value: "ios-hig" },
|
|
905
|
-
{ name: "Glassmorphism", value: "glassmorphism" },
|
|
906
|
-
{ name: "Neumorphism", value: "neumorphism" },
|
|
907
|
-
{ name: "Minimalism", value: "minimalism" }
|
|
908
|
-
]
|
|
909
|
-
},
|
|
910
|
-
{
|
|
911
|
-
type: "list",
|
|
912
|
-
name: "tier",
|
|
913
|
-
message: "Quality tier:",
|
|
914
|
-
choices: [
|
|
915
|
-
{ name: "Basic (Prototype)", value: "basic" },
|
|
916
|
-
{ name: "Standard (Production)", value: "standard" },
|
|
917
|
-
{ name: "Enterprise (Mission-critical)", value: "enterprise" }
|
|
918
|
-
],
|
|
919
|
-
default: "standard"
|
|
920
|
-
},
|
|
921
|
-
{
|
|
922
|
-
type: "list",
|
|
923
|
-
name: "framework",
|
|
924
|
-
message: "Framework:",
|
|
925
|
-
choices: [
|
|
926
|
-
{ name: "React", value: "react" },
|
|
927
|
-
{ name: "Vue", value: "vue" },
|
|
928
|
-
{ name: "Angular", value: "angular" },
|
|
929
|
-
{ name: "Svelte", value: "svelte" },
|
|
930
|
-
{ name: "Solid", value: "solid" }
|
|
931
|
-
],
|
|
932
|
-
default: "react"
|
|
933
|
-
}
|
|
934
|
-
]);
|
|
935
|
-
return answers;
|
|
936
|
-
}
|
|
179
|
+
var import_inquirer = __toESM(require("inquirer"));
|
|
937
180
|
async function promptProjectInit() {
|
|
938
|
-
const answers = await
|
|
181
|
+
const answers = await import_inquirer.default.prompt([
|
|
939
182
|
{
|
|
940
183
|
type: "input",
|
|
941
184
|
name: "projectName",
|
|
@@ -982,551 +225,8 @@ async function promptProjectInit() {
|
|
|
982
225
|
]);
|
|
983
226
|
return answers;
|
|
984
227
|
}
|
|
985
|
-
async function promptSectionConfig() {
|
|
986
|
-
const answers = await import_inquirer2.default.prompt([
|
|
987
|
-
{
|
|
988
|
-
type: "input",
|
|
989
|
-
name: "name",
|
|
990
|
-
message: "Section name (PascalCase):",
|
|
991
|
-
validate: (input) => {
|
|
992
|
-
if (!input) return "Section name is required";
|
|
993
|
-
if (!/^[A-Z][a-zA-Z0-9]*$/.test(input)) {
|
|
994
|
-
return "Section name must be PascalCase (e.g., HeroSection)";
|
|
995
|
-
}
|
|
996
|
-
return true;
|
|
997
|
-
}
|
|
998
|
-
},
|
|
999
|
-
{
|
|
1000
|
-
type: "list",
|
|
1001
|
-
name: "template",
|
|
1002
|
-
message: "Section template:",
|
|
1003
|
-
choices: [
|
|
1004
|
-
// Hero sections
|
|
1005
|
-
{ name: "Hero - Centered", value: "hero-centered" },
|
|
1006
|
-
{ name: "Hero - Split (Image + Text)", value: "hero-split" },
|
|
1007
|
-
{ name: "Hero - Background Image", value: "hero-background" },
|
|
1008
|
-
{ name: "Hero - Video Background", value: "hero-video" },
|
|
1009
|
-
// Features sections
|
|
1010
|
-
{ name: "Features - Grid", value: "features-grid" },
|
|
1011
|
-
{ name: "Features - List", value: "features-list" },
|
|
1012
|
-
{ name: "Features - Alternating", value: "features-alternating" },
|
|
1013
|
-
// CTA sections
|
|
1014
|
-
{ name: "CTA - Banner", value: "cta-banner" },
|
|
1015
|
-
{ name: "CTA - Centered", value: "cta-centered" },
|
|
1016
|
-
{ name: "CTA - Split", value: "cta-split" },
|
|
1017
|
-
// Pricing sections
|
|
1018
|
-
{ name: "Pricing - Cards", value: "pricing-cards" },
|
|
1019
|
-
{ name: "Pricing - Table", value: "pricing-table" },
|
|
1020
|
-
// Testimonial sections
|
|
1021
|
-
{ name: "Testimonials - Grid", value: "testimonials-grid" },
|
|
1022
|
-
{ name: "Testimonials - Carousel", value: "testimonials-carousel" },
|
|
1023
|
-
// Other sections
|
|
1024
|
-
{ name: "FAQ - Accordion", value: "faq-accordion" },
|
|
1025
|
-
{ name: "Team - Grid", value: "team-grid" },
|
|
1026
|
-
{ name: "Stats - Grid", value: "stats-grid" },
|
|
1027
|
-
{ name: "Logo Cloud", value: "logo-cloud" },
|
|
1028
|
-
{ name: "Newsletter", value: "newsletter" },
|
|
1029
|
-
{ name: "Contact Form", value: "contact-form" }
|
|
1030
|
-
]
|
|
1031
|
-
},
|
|
1032
|
-
{
|
|
1033
|
-
type: "list",
|
|
1034
|
-
name: "designSystem",
|
|
1035
|
-
message: "Design system:",
|
|
1036
|
-
choices: [
|
|
1037
|
-
{ name: "Material Design 3", value: "material-design" },
|
|
1038
|
-
{ name: "iOS Human Interface Guidelines", value: "ios-hig" },
|
|
1039
|
-
{ name: "Glassmorphism", value: "glassmorphism" },
|
|
1040
|
-
{ name: "Neumorphism", value: "neumorphism" },
|
|
1041
|
-
{ name: "Brutalism", value: "brutalism" },
|
|
1042
|
-
{ name: "Minimalism", value: "minimalism" }
|
|
1043
|
-
]
|
|
1044
|
-
},
|
|
1045
|
-
{
|
|
1046
|
-
type: "list",
|
|
1047
|
-
name: "tier",
|
|
1048
|
-
message: "Quality tier:",
|
|
1049
|
-
choices: [
|
|
1050
|
-
{ name: "Basic (Prototype)", value: "basic" },
|
|
1051
|
-
{ name: "Standard (Production)", value: "standard" },
|
|
1052
|
-
{ name: "Enterprise (Mission-critical)", value: "enterprise" }
|
|
1053
|
-
],
|
|
1054
|
-
default: "standard"
|
|
1055
|
-
},
|
|
1056
|
-
{
|
|
1057
|
-
type: "list",
|
|
1058
|
-
name: "framework",
|
|
1059
|
-
message: "Framework:",
|
|
1060
|
-
choices: [
|
|
1061
|
-
{ name: "React", value: "react" },
|
|
1062
|
-
{ name: "Vue", value: "vue" },
|
|
1063
|
-
{ name: "Angular", value: "angular" },
|
|
1064
|
-
{ name: "Svelte", value: "svelte" },
|
|
1065
|
-
{ name: "Solid", value: "solid" }
|
|
1066
|
-
],
|
|
1067
|
-
default: "react"
|
|
1068
|
-
},
|
|
1069
|
-
{
|
|
1070
|
-
type: "input",
|
|
1071
|
-
name: "heading",
|
|
1072
|
-
message: "Section heading:",
|
|
1073
|
-
default: "Welcome to Your App"
|
|
1074
|
-
},
|
|
1075
|
-
{
|
|
1076
|
-
type: "input",
|
|
1077
|
-
name: "subheading",
|
|
1078
|
-
message: "Section subheading (optional):",
|
|
1079
|
-
default: ""
|
|
1080
|
-
},
|
|
1081
|
-
{
|
|
1082
|
-
type: "input",
|
|
1083
|
-
name: "description",
|
|
1084
|
-
message: "Section description (optional):",
|
|
1085
|
-
default: ""
|
|
1086
|
-
},
|
|
1087
|
-
{
|
|
1088
|
-
type: "input",
|
|
1089
|
-
name: "ctaText",
|
|
1090
|
-
message: "Call-to-action button text:",
|
|
1091
|
-
default: "Get Started"
|
|
1092
|
-
},
|
|
1093
|
-
{
|
|
1094
|
-
type: "input",
|
|
1095
|
-
name: "ctaHref",
|
|
1096
|
-
message: "Call-to-action button link:",
|
|
1097
|
-
default: "#"
|
|
1098
|
-
}
|
|
1099
|
-
]);
|
|
1100
|
-
return answers;
|
|
1101
|
-
}
|
|
1102
|
-
async function promptGenerationType() {
|
|
1103
|
-
const answer = await import_inquirer2.default.prompt([
|
|
1104
|
-
{
|
|
1105
|
-
type: "list",
|
|
1106
|
-
name: "type",
|
|
1107
|
-
message: "What do you want to generate?",
|
|
1108
|
-
choices: [
|
|
1109
|
-
{ name: "Component (Button, Card, Input, etc.)", value: "component" },
|
|
1110
|
-
{ name: "Section (Hero, Features, CTA, etc.)", value: "section" },
|
|
1111
|
-
{ name: "Page (Landing, Dashboard, Auth, etc.)", value: "page" }
|
|
1112
|
-
]
|
|
1113
|
-
}
|
|
1114
|
-
]);
|
|
1115
|
-
return answer.type;
|
|
1116
|
-
}
|
|
1117
|
-
async function promptPageConfig() {
|
|
1118
|
-
const answers = await import_inquirer2.default.prompt([
|
|
1119
|
-
{
|
|
1120
|
-
type: "input",
|
|
1121
|
-
name: "name",
|
|
1122
|
-
message: "Page name (PascalCase):",
|
|
1123
|
-
validate: (input) => {
|
|
1124
|
-
if (!input) return "Page name is required";
|
|
1125
|
-
if (!/^[A-Z][a-zA-Z0-9]*$/.test(input)) {
|
|
1126
|
-
return "Page name must be PascalCase (e.g., HomePage)";
|
|
1127
|
-
}
|
|
1128
|
-
return true;
|
|
1129
|
-
}
|
|
1130
|
-
},
|
|
1131
|
-
{
|
|
1132
|
-
type: "list",
|
|
1133
|
-
name: "template",
|
|
1134
|
-
message: "Page template:",
|
|
1135
|
-
choices: [
|
|
1136
|
-
// Landing pages
|
|
1137
|
-
{ name: "Landing - SaaS Product", value: "landing-saas" },
|
|
1138
|
-
{ name: "Landing - Product Showcase", value: "landing-product" },
|
|
1139
|
-
{ name: "Landing - Agency", value: "landing-agency" },
|
|
1140
|
-
{ name: "Landing - Startup", value: "landing-startup" },
|
|
1141
|
-
{ name: "Landing - Mobile App", value: "landing-app" },
|
|
1142
|
-
// Marketing pages
|
|
1143
|
-
{ name: "Marketing - Simple", value: "marketing-simple" },
|
|
1144
|
-
{ name: "Marketing - Feature", value: "marketing-feature" },
|
|
1145
|
-
{ name: "Marketing - Pricing", value: "marketing-pricing" },
|
|
1146
|
-
// Dashboard pages
|
|
1147
|
-
{ name: "Dashboard - Overview", value: "dashboard-overview" },
|
|
1148
|
-
{ name: "Dashboard - Analytics", value: "dashboard-analytics" },
|
|
1149
|
-
{ name: "Dashboard - Settings", value: "dashboard-settings" },
|
|
1150
|
-
// Auth pages
|
|
1151
|
-
{ name: "Auth - Login", value: "auth-login" },
|
|
1152
|
-
{ name: "Auth - Register", value: "auth-register" },
|
|
1153
|
-
{ name: "Auth - Forgot Password", value: "auth-forgot-password" },
|
|
1154
|
-
// E-commerce pages
|
|
1155
|
-
{ name: "E-commerce - Home", value: "ecommerce-home" },
|
|
1156
|
-
{ name: "E-commerce - Product", value: "ecommerce-product" },
|
|
1157
|
-
{ name: "E-commerce - Cart", value: "ecommerce-cart" },
|
|
1158
|
-
// Error pages
|
|
1159
|
-
{ name: "Error - 404 Not Found", value: "error-404" },
|
|
1160
|
-
{ name: "Error - 500 Server Error", value: "error-500" },
|
|
1161
|
-
{ name: "Error - Maintenance", value: "error-maintenance" },
|
|
1162
|
-
// Content pages
|
|
1163
|
-
{ name: "Content - Blog List", value: "content-blog-list" },
|
|
1164
|
-
{ name: "Content - Blog Post", value: "content-blog-post" },
|
|
1165
|
-
{ name: "Content - About", value: "content-about" },
|
|
1166
|
-
{ name: "Content - Contact", value: "content-contact" }
|
|
1167
|
-
]
|
|
1168
|
-
},
|
|
1169
|
-
{
|
|
1170
|
-
type: "list",
|
|
1171
|
-
name: "designSystem",
|
|
1172
|
-
message: "Design system:",
|
|
1173
|
-
choices: [
|
|
1174
|
-
{ name: "Material Design 3", value: "material-design" },
|
|
1175
|
-
{ name: "iOS Human Interface Guidelines", value: "ios-hig" },
|
|
1176
|
-
{ name: "Glassmorphism", value: "glassmorphism" },
|
|
1177
|
-
{ name: "Neumorphism", value: "neumorphism" },
|
|
1178
|
-
{ name: "Brutalism", value: "brutalism" },
|
|
1179
|
-
{ name: "Minimalism", value: "minimalism" }
|
|
1180
|
-
]
|
|
1181
|
-
},
|
|
1182
|
-
{
|
|
1183
|
-
type: "list",
|
|
1184
|
-
name: "tier",
|
|
1185
|
-
message: "Quality tier:",
|
|
1186
|
-
choices: [
|
|
1187
|
-
{ name: "Basic (Prototype)", value: "basic" },
|
|
1188
|
-
{ name: "Standard (Production)", value: "standard" },
|
|
1189
|
-
{ name: "Enterprise (Mission-critical)", value: "enterprise" }
|
|
1190
|
-
],
|
|
1191
|
-
default: "standard"
|
|
1192
|
-
},
|
|
1193
|
-
{
|
|
1194
|
-
type: "list",
|
|
1195
|
-
name: "framework",
|
|
1196
|
-
message: "Framework:",
|
|
1197
|
-
choices: [
|
|
1198
|
-
{ name: "React", value: "react" },
|
|
1199
|
-
{ name: "Next.js", value: "nextjs" },
|
|
1200
|
-
{ name: "Remix", value: "remix" },
|
|
1201
|
-
{ name: "Astro", value: "astro" }
|
|
1202
|
-
],
|
|
1203
|
-
default: "react"
|
|
1204
|
-
},
|
|
1205
|
-
{
|
|
1206
|
-
type: "input",
|
|
1207
|
-
name: "title",
|
|
1208
|
-
message: "Page title (for SEO):",
|
|
1209
|
-
default: "My Page"
|
|
1210
|
-
},
|
|
1211
|
-
{
|
|
1212
|
-
type: "input",
|
|
1213
|
-
name: "description",
|
|
1214
|
-
message: "Page description (for SEO):",
|
|
1215
|
-
default: "A great page built with Nikkory Vibe"
|
|
1216
|
-
}
|
|
1217
|
-
]);
|
|
1218
|
-
return answers;
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
// src/commands/generate.ts
|
|
1222
|
-
var generateCommand = new import_commander3.Command("generate").alias("g").description("Generate components, sections, or pages from templates").argument("[type]", "Type to generate (component, section, page)").option("-n, --name <name>", "Name (PascalCase)").option("-t, --template <template>", "Template type").option("-d, --design <system>", "Design system", "material-design").option("--tier <tier>", "Quality tier (basic, standard, enterprise)", "standard").option("-f, --framework <framework>", "Framework (react, vue, etc.)", "react").option("-o, --output <path>", "Output file path").option("--dry-run", "Preview generated code without writing").option("--interactive", "Interactive mode with prompts").option("--heading <text>", "Section heading (for sections)").option("--subheading <text>", "Section subheading (for sections)").option("--description <text>", "Section description (for sections)").option("--cta-text <text>", "CTA button text (for sections)").option("--cta-href <url>", "CTA button link (for sections)").option("--title <text>", "Page title for SEO (for pages)").action(async (type, options) => {
|
|
1223
|
-
try {
|
|
1224
|
-
logger.header("\u{1F3A8} Nikkory Vibe - Code Generator");
|
|
1225
|
-
let generationType = type;
|
|
1226
|
-
if (!generationType || options.interactive) {
|
|
1227
|
-
generationType = await promptGenerationType();
|
|
1228
|
-
}
|
|
1229
|
-
switch (generationType) {
|
|
1230
|
-
case "component":
|
|
1231
|
-
await generateComponent(options);
|
|
1232
|
-
break;
|
|
1233
|
-
case "section":
|
|
1234
|
-
await generateSection(options);
|
|
1235
|
-
break;
|
|
1236
|
-
case "page":
|
|
1237
|
-
await generatePage(options);
|
|
1238
|
-
break;
|
|
1239
|
-
default:
|
|
1240
|
-
await generateComponent(options);
|
|
1241
|
-
}
|
|
1242
|
-
} catch (error) {
|
|
1243
|
-
logger.stopSpinner();
|
|
1244
|
-
logger.error("Unexpected error occurred");
|
|
1245
|
-
if (error instanceof Error) {
|
|
1246
|
-
logger.debug(error.stack || error.message);
|
|
1247
|
-
}
|
|
1248
|
-
process.exit(1);
|
|
1249
|
-
}
|
|
1250
|
-
});
|
|
1251
|
-
async function generateComponent(options) {
|
|
1252
|
-
let config;
|
|
1253
|
-
if (options.interactive ?? !options.name) {
|
|
1254
|
-
config = await promptComponentConfig();
|
|
1255
|
-
} else {
|
|
1256
|
-
config = {
|
|
1257
|
-
name: options.name ?? "",
|
|
1258
|
-
template: options.template ?? "button",
|
|
1259
|
-
framework: options.framework ?? "react",
|
|
1260
|
-
designSystem: options.design ?? "material-design",
|
|
1261
|
-
tier: options.tier ?? "standard"
|
|
1262
|
-
};
|
|
1263
|
-
}
|
|
1264
|
-
if (!config.name) {
|
|
1265
|
-
logger.error("Component name is required");
|
|
1266
|
-
process.exit(1);
|
|
1267
|
-
}
|
|
1268
|
-
logger.newline();
|
|
1269
|
-
logger.info(`Generating ${config.tier} ${config.template} component...`);
|
|
1270
|
-
logger.info(`Design System: ${config.designSystem}`);
|
|
1271
|
-
logger.info(`Framework: ${config.framework}`);
|
|
1272
|
-
logger.newline();
|
|
1273
|
-
logger.startSpinner("Loading template...");
|
|
1274
|
-
const generator = new import_vibe_core.ComponentGenerator();
|
|
1275
|
-
const result = await generator.generate({
|
|
1276
|
-
name: config.name,
|
|
1277
|
-
template: config.template,
|
|
1278
|
-
designSystem: config.designSystem,
|
|
1279
|
-
tier: config.tier,
|
|
1280
|
-
framework: config.framework,
|
|
1281
|
-
outputPath: options.output
|
|
1282
|
-
});
|
|
1283
|
-
if (result.isFailure()) {
|
|
1284
|
-
logger.stopSpinnerFail("Generation failed");
|
|
1285
|
-
logger.error(result.getError().message);
|
|
1286
|
-
process.exit(1);
|
|
1287
|
-
}
|
|
1288
|
-
logger.stopSpinnerSuccess("Template loaded");
|
|
1289
|
-
const code = result.getValue();
|
|
1290
|
-
if (options.dryRun) {
|
|
1291
|
-
logger.newline();
|
|
1292
|
-
logger.header("Generated Code (Preview)");
|
|
1293
|
-
logger.code(code);
|
|
1294
|
-
logger.newline();
|
|
1295
|
-
logger.info("Dry run mode - No files written");
|
|
1296
|
-
return;
|
|
1297
|
-
}
|
|
1298
|
-
const outputPath = options.output ?? generateComponentPath(config);
|
|
1299
|
-
logger.startSpinner(`Writing to ${outputPath}...`);
|
|
1300
|
-
await fs3.mkdir(path3.dirname(outputPath), { recursive: true });
|
|
1301
|
-
await fs3.writeFile(outputPath, code, "utf-8");
|
|
1302
|
-
logger.stopSpinnerSuccess(`Component created: ${outputPath}`);
|
|
1303
|
-
logger.newline();
|
|
1304
|
-
logger.box(
|
|
1305
|
-
`\u2728 ${config.name} component generated successfully!
|
|
1306
|
-
|
|
1307
|
-
File: ${outputPath}
|
|
1308
|
-
Lines: ${code.split("\n").length}
|
|
1309
|
-
Design: ${config.designSystem}
|
|
1310
|
-
Tier: ${config.tier}`,
|
|
1311
|
-
{ title: "Success", borderColor: "green" }
|
|
1312
|
-
);
|
|
1313
|
-
printNextSteps("component");
|
|
1314
|
-
}
|
|
1315
|
-
async function generateSection(options) {
|
|
1316
|
-
let config;
|
|
1317
|
-
if (options.interactive ?? !options.name) {
|
|
1318
|
-
config = await promptSectionConfig();
|
|
1319
|
-
} else {
|
|
1320
|
-
config = {
|
|
1321
|
-
name: options.name ?? "",
|
|
1322
|
-
template: options.template ?? "hero-centered",
|
|
1323
|
-
framework: options.framework ?? "react",
|
|
1324
|
-
designSystem: options.design ?? "material-design",
|
|
1325
|
-
tier: options.tier ?? "standard",
|
|
1326
|
-
heading: options.heading ?? "Welcome to Your App",
|
|
1327
|
-
subheading: options.subheading ?? "",
|
|
1328
|
-
description: options.description ?? "",
|
|
1329
|
-
ctaText: options.ctaText ?? "Get Started",
|
|
1330
|
-
ctaHref: options.ctaHref ?? "#"
|
|
1331
|
-
};
|
|
1332
|
-
}
|
|
1333
|
-
if (!config.name) {
|
|
1334
|
-
logger.error("Section name is required");
|
|
1335
|
-
process.exit(1);
|
|
1336
|
-
}
|
|
1337
|
-
logger.newline();
|
|
1338
|
-
logger.info(`Generating ${config.tier} ${config.template} section...`);
|
|
1339
|
-
logger.info(`Design System: ${config.designSystem}`);
|
|
1340
|
-
logger.info(`Framework: ${config.framework}`);
|
|
1341
|
-
logger.newline();
|
|
1342
|
-
const sectionConfig = {
|
|
1343
|
-
name: config.name,
|
|
1344
|
-
template: config.template,
|
|
1345
|
-
designSystem: config.designSystem,
|
|
1346
|
-
tier: config.tier,
|
|
1347
|
-
framework: config.framework,
|
|
1348
|
-
outputPath: options.output,
|
|
1349
|
-
content: {
|
|
1350
|
-
heading: config.heading,
|
|
1351
|
-
subheading: config.subheading || void 0,
|
|
1352
|
-
description: config.description || void 0,
|
|
1353
|
-
cta: config.ctaText ? {
|
|
1354
|
-
text: config.ctaText,
|
|
1355
|
-
href: config.ctaHref || "#"
|
|
1356
|
-
} : void 0
|
|
1357
|
-
}
|
|
1358
|
-
};
|
|
1359
|
-
logger.startSpinner("Generating section...");
|
|
1360
|
-
const generator = new import_vibe_core.SectionGenerator();
|
|
1361
|
-
const result = await generator.generateSection(sectionConfig);
|
|
1362
|
-
if (result.isFailure()) {
|
|
1363
|
-
logger.stopSpinnerFail("Generation failed");
|
|
1364
|
-
logger.error(result.getError().message);
|
|
1365
|
-
process.exit(1);
|
|
1366
|
-
}
|
|
1367
|
-
logger.stopSpinnerSuccess("Section generated");
|
|
1368
|
-
const sectionResult = result.getValue();
|
|
1369
|
-
if (options.dryRun) {
|
|
1370
|
-
logger.newline();
|
|
1371
|
-
logger.header("Generated Code (Preview)");
|
|
1372
|
-
logger.code(sectionResult.code);
|
|
1373
|
-
logger.newline();
|
|
1374
|
-
logger.info("Dry run mode - No files written");
|
|
1375
|
-
logger.newline();
|
|
1376
|
-
logger.info("Metadata:");
|
|
1377
|
-
logger.info(` Template: ${sectionResult.metadata.template}`);
|
|
1378
|
-
logger.info(` Lines of code: ${sectionResult.metadata.linesOfCode}`);
|
|
1379
|
-
logger.info(` Child components: ${sectionResult.metadata.childComponentCount}`);
|
|
1380
|
-
return;
|
|
1381
|
-
}
|
|
1382
|
-
const outputPath = options.output ?? generateSectionPath(config);
|
|
1383
|
-
logger.startSpinner(`Writing to ${outputPath}...`);
|
|
1384
|
-
await fs3.mkdir(path3.dirname(outputPath), { recursive: true });
|
|
1385
|
-
await fs3.writeFile(outputPath, sectionResult.code, "utf-8");
|
|
1386
|
-
logger.stopSpinnerSuccess(`Section created: ${outputPath}`);
|
|
1387
|
-
logger.newline();
|
|
1388
|
-
logger.box(
|
|
1389
|
-
`\u2728 ${config.name} section generated successfully!
|
|
1390
|
-
|
|
1391
|
-
File: ${outputPath}
|
|
1392
|
-
Template: ${config.template}
|
|
1393
|
-
Lines: ${sectionResult.metadata.linesOfCode}
|
|
1394
|
-
Design: ${config.designSystem}
|
|
1395
|
-
Tier: ${config.tier}`,
|
|
1396
|
-
{ title: "Success", borderColor: "green" }
|
|
1397
|
-
);
|
|
1398
|
-
printNextSteps("section");
|
|
1399
|
-
}
|
|
1400
|
-
async function generatePage(options) {
|
|
1401
|
-
let config;
|
|
1402
|
-
if (options.interactive ?? !options.name) {
|
|
1403
|
-
config = await promptPageConfig();
|
|
1404
|
-
} else {
|
|
1405
|
-
config = {
|
|
1406
|
-
name: options.name ?? "",
|
|
1407
|
-
template: options.template ?? "landing-saas",
|
|
1408
|
-
framework: options.framework ?? "react",
|
|
1409
|
-
designSystem: options.design ?? "material-design",
|
|
1410
|
-
tier: options.tier ?? "standard",
|
|
1411
|
-
title: options.title ?? "My Page",
|
|
1412
|
-
description: options.description ?? ""
|
|
1413
|
-
};
|
|
1414
|
-
}
|
|
1415
|
-
if (!config.name) {
|
|
1416
|
-
logger.error("Page name is required");
|
|
1417
|
-
process.exit(1);
|
|
1418
|
-
}
|
|
1419
|
-
logger.newline();
|
|
1420
|
-
logger.info(`Generating ${config.tier} ${config.template} page...`);
|
|
1421
|
-
logger.info(`Design System: ${config.designSystem}`);
|
|
1422
|
-
logger.info(`Framework: ${config.framework}`);
|
|
1423
|
-
logger.newline();
|
|
1424
|
-
const pageConfig = {
|
|
1425
|
-
name: config.name,
|
|
1426
|
-
template: config.template,
|
|
1427
|
-
designSystem: config.designSystem,
|
|
1428
|
-
tier: config.tier,
|
|
1429
|
-
framework: config.framework,
|
|
1430
|
-
outputPath: options.output,
|
|
1431
|
-
meta: {
|
|
1432
|
-
title: config.title,
|
|
1433
|
-
description: config.description || void 0
|
|
1434
|
-
}
|
|
1435
|
-
};
|
|
1436
|
-
logger.startSpinner("Generating page...");
|
|
1437
|
-
const generator = new import_vibe_core.PageGenerator();
|
|
1438
|
-
const result = await generator.generatePage(pageConfig);
|
|
1439
|
-
if (result.isFailure()) {
|
|
1440
|
-
logger.stopSpinnerFail("Generation failed");
|
|
1441
|
-
logger.error(result.getError().message);
|
|
1442
|
-
process.exit(1);
|
|
1443
|
-
}
|
|
1444
|
-
logger.stopSpinnerSuccess("Page generated");
|
|
1445
|
-
const pageResult = result.getValue();
|
|
1446
|
-
if (options.dryRun) {
|
|
1447
|
-
logger.newline();
|
|
1448
|
-
logger.header("Generated Code (Preview)");
|
|
1449
|
-
logger.code(pageResult.code);
|
|
1450
|
-
logger.newline();
|
|
1451
|
-
logger.info("Dry run mode - No files written");
|
|
1452
|
-
logger.newline();
|
|
1453
|
-
logger.info("Metadata:");
|
|
1454
|
-
logger.info(` Template: ${pageResult.metadata.template}`);
|
|
1455
|
-
logger.info(` Framework: ${pageResult.metadata.framework}`);
|
|
1456
|
-
logger.info(` Lines of code: ${pageResult.metadata.linesOfCode}`);
|
|
1457
|
-
logger.info(` Sections: ${pageResult.metadata.sectionCount}`);
|
|
1458
|
-
return;
|
|
1459
|
-
}
|
|
1460
|
-
const outputPath = options.output ?? generatePagePath(config);
|
|
1461
|
-
logger.startSpinner(`Writing to ${outputPath}...`);
|
|
1462
|
-
await fs3.mkdir(path3.dirname(outputPath), { recursive: true });
|
|
1463
|
-
await fs3.writeFile(outputPath, pageResult.code, "utf-8");
|
|
1464
|
-
logger.stopSpinnerSuccess(`Page created: ${outputPath}`);
|
|
1465
|
-
logger.newline();
|
|
1466
|
-
logger.box(
|
|
1467
|
-
`\u2728 ${config.name} page generated successfully!
|
|
1468
|
-
|
|
1469
|
-
File: ${outputPath}
|
|
1470
|
-
Template: ${config.template}
|
|
1471
|
-
Lines: ${pageResult.metadata.linesOfCode}
|
|
1472
|
-
Framework: ${config.framework}
|
|
1473
|
-
Design: ${config.designSystem}
|
|
1474
|
-
Tier: ${config.tier}`,
|
|
1475
|
-
{ title: "Success", borderColor: "green" }
|
|
1476
|
-
);
|
|
1477
|
-
printNextSteps("page");
|
|
1478
|
-
}
|
|
1479
|
-
function generateComponentPath(config) {
|
|
1480
|
-
const ext = getFileExtension(config.framework);
|
|
1481
|
-
const fileName = `${config.name}.${ext}`;
|
|
1482
|
-
return path3.join(process.cwd(), "src", "components", fileName);
|
|
1483
|
-
}
|
|
1484
|
-
function generateSectionPath(config) {
|
|
1485
|
-
const ext = getFileExtension(config.framework);
|
|
1486
|
-
const fileName = `${config.name}.${ext}`;
|
|
1487
|
-
return path3.join(process.cwd(), "src", "sections", fileName);
|
|
1488
|
-
}
|
|
1489
|
-
function generatePagePath(config) {
|
|
1490
|
-
const ext = getFileExtension(config.framework);
|
|
1491
|
-
const fileName = `${config.name}.${ext}`;
|
|
1492
|
-
const pageDir = config.framework === "nextjs" ? "app" : "pages";
|
|
1493
|
-
return path3.join(process.cwd(), "src", pageDir, fileName);
|
|
1494
|
-
}
|
|
1495
|
-
function getFileExtension(framework) {
|
|
1496
|
-
const extensions = {
|
|
1497
|
-
react: "tsx",
|
|
1498
|
-
vue: "vue",
|
|
1499
|
-
angular: "component.ts",
|
|
1500
|
-
svelte: "svelte",
|
|
1501
|
-
solid: "tsx"
|
|
1502
|
-
};
|
|
1503
|
-
return extensions[framework] || "tsx";
|
|
1504
|
-
}
|
|
1505
|
-
function printNextSteps(type) {
|
|
1506
|
-
logger.newline();
|
|
1507
|
-
logger.info("Next steps:");
|
|
1508
|
-
if (type === "component") {
|
|
1509
|
-
logger.code(" 1. Import the component in your app");
|
|
1510
|
-
logger.code(" 2. Review and customize as needed");
|
|
1511
|
-
logger.code(" 3. Run your dev server to test");
|
|
1512
|
-
} else if (type === "section") {
|
|
1513
|
-
logger.code(" 1. Import the section in your page");
|
|
1514
|
-
logger.code(" 2. Customize content props (heading, description, etc.)");
|
|
1515
|
-
logger.code(" 3. Add your own images and assets");
|
|
1516
|
-
logger.code(" 4. Run your dev server to preview");
|
|
1517
|
-
} else {
|
|
1518
|
-
logger.code(" 1. Set up routing for your page");
|
|
1519
|
-
logger.code(" 2. Customize page content and sections");
|
|
1520
|
-
logger.code(" 3. Add SEO meta tags if needed");
|
|
1521
|
-
logger.code(" 4. Run your dev server to preview");
|
|
1522
|
-
}
|
|
1523
|
-
logger.newline();
|
|
1524
|
-
}
|
|
1525
228
|
|
|
1526
229
|
// src/commands/init.ts
|
|
1527
|
-
var fs4 = __toESM(require("fs/promises"));
|
|
1528
|
-
var path4 = __toESM(require("path"));
|
|
1529
|
-
var import_commander4 = require("commander");
|
|
1530
230
|
function generateClaudeMd(config) {
|
|
1531
231
|
const tier = config.tier || "standard";
|
|
1532
232
|
return `# Claude Code Instructions - ${config.projectName}
|
|
@@ -1732,7 +432,7 @@ Before ANY commit, AI Agent MUST verify:
|
|
|
1732
432
|
**Powered by Nikkory Vibe**
|
|
1733
433
|
`;
|
|
1734
434
|
}
|
|
1735
|
-
var initCommand = new
|
|
435
|
+
var initCommand = new import_commander.Command("init").description("Initialize a new Nikkory Vibe project with AI Agent Inspector").argument("[project-name]", "Project name (kebab-case)").option("-f, --framework <framework>", "Frontend framework", "react").option("-d, --design <system>", "Default design system", "material-design").option("-t, --tier <tier>", "Quality tier (basic, standard, enterprise)", "standard").option("--backend", "Include backend (NestJS)").option("--no-install", "Skip dependency installation").option("--no-claude", "Skip CLAUDE.md generation").action(
|
|
1736
436
|
async (projectName, options) => {
|
|
1737
437
|
try {
|
|
1738
438
|
logger.header("\u{1F3A8} Nikkory Vibe - Project Initialization");
|
|
@@ -1753,9 +453,9 @@ var initCommand = new import_commander4.Command("init").description("Initialize
|
|
|
1753
453
|
includeBackend: options.backend ?? false
|
|
1754
454
|
};
|
|
1755
455
|
}
|
|
1756
|
-
const projectPath =
|
|
456
|
+
const projectPath = path.join(process.cwd(), projectName);
|
|
1757
457
|
try {
|
|
1758
|
-
await
|
|
458
|
+
await fs.access(projectPath);
|
|
1759
459
|
logger.error(`Directory "${projectName}" already exists`);
|
|
1760
460
|
process.exit(1);
|
|
1761
461
|
} catch {
|
|
@@ -1770,7 +470,7 @@ var initCommand = new import_commander4.Command("init").description("Initialize
|
|
|
1770
470
|
}
|
|
1771
471
|
logger.newline();
|
|
1772
472
|
logger.startSpinner("Creating project structure...");
|
|
1773
|
-
await
|
|
473
|
+
await fs.mkdir(projectPath, { recursive: true });
|
|
1774
474
|
await createProjectStructure(projectPath, config);
|
|
1775
475
|
logger.stopSpinnerSuccess("Project structure created");
|
|
1776
476
|
logger.startSpinner("Creating package.json...");
|
|
@@ -1831,12 +531,12 @@ async function createProjectStructure(projectPath, config) {
|
|
|
1831
531
|
dirs.push("api/src/modules", "api/src/common", "api/prisma");
|
|
1832
532
|
}
|
|
1833
533
|
for (const dir of dirs) {
|
|
1834
|
-
await
|
|
534
|
+
await fs.mkdir(path.join(projectPath, dir), { recursive: true });
|
|
1835
535
|
}
|
|
1836
536
|
}
|
|
1837
537
|
async function createClaudeMd(projectPath, config) {
|
|
1838
538
|
const content = generateClaudeMd(config);
|
|
1839
|
-
await
|
|
539
|
+
await fs.writeFile(path.join(projectPath, "CLAUDE.md"), content, "utf-8");
|
|
1840
540
|
}
|
|
1841
541
|
async function createPackageJson(projectPath, config) {
|
|
1842
542
|
const packageJson = {
|
|
@@ -1860,8 +560,8 @@ async function createPackageJson(projectPath, config) {
|
|
|
1860
560
|
"@nikkory/vibe-cli": "^1.0.0"
|
|
1861
561
|
}
|
|
1862
562
|
};
|
|
1863
|
-
await
|
|
1864
|
-
|
|
563
|
+
await fs.writeFile(
|
|
564
|
+
path.join(projectPath, "package.json"),
|
|
1865
565
|
JSON.stringify(packageJson, null, 2),
|
|
1866
566
|
"utf-8"
|
|
1867
567
|
);
|
|
@@ -1921,8 +621,8 @@ async function createConfigFiles(projectPath, _config) {
|
|
|
1921
621
|
include: ["src/**/*"],
|
|
1922
622
|
exclude: ["node_modules"]
|
|
1923
623
|
};
|
|
1924
|
-
await
|
|
1925
|
-
|
|
624
|
+
await fs.writeFile(
|
|
625
|
+
path.join(projectPath, "tsconfig.json"),
|
|
1926
626
|
JSON.stringify(tsConfig, null, 2),
|
|
1927
627
|
"utf-8"
|
|
1928
628
|
);
|
|
@@ -1957,7 +657,7 @@ npm-debug.log*
|
|
|
1957
657
|
yarn-debug.log*
|
|
1958
658
|
yarn-error.log*
|
|
1959
659
|
`;
|
|
1960
|
-
await
|
|
660
|
+
await fs.writeFile(path.join(projectPath, ".gitignore"), gitignore, "utf-8");
|
|
1961
661
|
}
|
|
1962
662
|
async function createReadme(projectPath, config) {
|
|
1963
663
|
const readme = `# ${config.projectName}
|
|
@@ -2051,12 +751,12 @@ ${config.projectName}/
|
|
|
2051
751
|
|
|
2052
752
|
Powered by Nikkory
|
|
2053
753
|
`;
|
|
2054
|
-
await
|
|
754
|
+
await fs.writeFile(path.join(projectPath, "README.md"), readme, "utf-8");
|
|
2055
755
|
}
|
|
2056
756
|
|
|
2057
757
|
// src/commands/list.ts
|
|
2058
|
-
var
|
|
2059
|
-
var listCommand = new
|
|
758
|
+
var import_commander2 = require("commander");
|
|
759
|
+
var listCommand = new import_commander2.Command("list").alias("ls").description("List available templates and design systems").argument("[category]", "Category to list (templates, designs, tiers)", "all").option("--json", "Output as JSON").action((category, options) => {
|
|
2060
760
|
try {
|
|
2061
761
|
if (options.json) {
|
|
2062
762
|
const data = getAllData();
|
|
@@ -2265,7 +965,7 @@ function getAllData() {
|
|
|
2265
965
|
}
|
|
2266
966
|
|
|
2267
967
|
// src/commands/matrix-generate.ts
|
|
2268
|
-
var
|
|
968
|
+
var import_commander3 = require("commander");
|
|
2269
969
|
var import_chalk2 = __toESM(require("chalk"));
|
|
2270
970
|
var import_ora2 = __toESM(require("ora"));
|
|
2271
971
|
var import_vibe_engine = require("@nikkory/vibe-engine");
|
|
@@ -2273,7 +973,7 @@ var import_vibe_engine = require("@nikkory/vibe-engine");
|
|
|
2273
973
|
// src/generators/component-generator.ts
|
|
2274
974
|
var import_promises = require("fs/promises");
|
|
2275
975
|
var import_path = require("path");
|
|
2276
|
-
var
|
|
976
|
+
var ComponentGenerator = class {
|
|
2277
977
|
/**
|
|
2278
978
|
* Write generated code to file
|
|
2279
979
|
*
|
|
@@ -2299,8 +999,8 @@ var ComponentGenerator2 = class {
|
|
|
2299
999
|
};
|
|
2300
1000
|
|
|
2301
1001
|
// src/commands/matrix-generate.ts
|
|
2302
|
-
var matrixGenerateCommand = new
|
|
2303
|
-
"-
|
|
1002
|
+
var matrixGenerateCommand = new import_commander3.Command("add").alias("gen").alias("generate").description("Add/Generate UI component using Matrix system (24 factors, 12 design systems, 3 tiers)").argument("<component>", "Component ID (e.g., button, input, card)").option(
|
|
1003
|
+
"-s, --design-system <system>",
|
|
2304
1004
|
"Design system (material-design, ios-hig, glassmorphism, neumorphism, brutalism, minimalism, fluent, carbon, ant-design, chakra, atlassian, blueprint)",
|
|
2305
1005
|
"material-design"
|
|
2306
1006
|
).option(
|
|
@@ -2338,7 +1038,7 @@ var matrixGenerateCommand = new import_commander6.Command("matrix-generate").des
|
|
|
2338
1038
|
};
|
|
2339
1039
|
const config = resolver.resolve(input);
|
|
2340
1040
|
const code = templateEngine.generate(config);
|
|
2341
|
-
const generator = new
|
|
1041
|
+
const generator = new ComponentGenerator();
|
|
2342
1042
|
if (options.output) {
|
|
2343
1043
|
await generator.writeToFile(options.output, code);
|
|
2344
1044
|
spinner.succeed(import_chalk2.default.green(`Generated ${config.componentName} \u2192 ${options.output}`));
|
|
@@ -2360,12 +1060,9 @@ var matrixGenerateCommand = new import_commander6.Command("matrix-generate").des
|
|
|
2360
1060
|
});
|
|
2361
1061
|
|
|
2362
1062
|
// src/index.ts
|
|
2363
|
-
var program = new
|
|
2364
|
-
program.name("nikkory-vibe").description("Nikkory Vibe - Production-ready code in seconds").version("1.0
|
|
2365
|
-
program.addCommand(generateCommand);
|
|
1063
|
+
var program = new import_commander4.Command();
|
|
1064
|
+
program.name("nikkory-vibe").description("Nikkory Vibe - Production-ready code in seconds").version("2.1.0");
|
|
2366
1065
|
program.addCommand(matrixGenerateCommand);
|
|
2367
|
-
program.addCommand(initCommand);
|
|
2368
1066
|
program.addCommand(listCommand);
|
|
2369
|
-
program.addCommand(
|
|
2370
|
-
program.addCommand(copyCommand);
|
|
1067
|
+
program.addCommand(initCommand);
|
|
2371
1068
|
program.parse(process.argv);
|