@dinachi/cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +171 -30
- package/package.json +1 -1
- package/templates/button/button.tsx +1 -1
- package/templates/dialog/dialog.tsx +1 -1
- package/templates/select/select.tsx +1 -1
package/dist/index.js
CHANGED
|
@@ -411,7 +411,30 @@ ${pluginsContent},
|
|
|
411
411
|
}
|
|
412
412
|
return { exists: true };
|
|
413
413
|
}
|
|
414
|
-
|
|
414
|
+
async function handleIndexFile(sourcePath, targetPath, componentName, allFilesAdded, aliasPath) {
|
|
415
|
+
let templateContent = await fs2.readFile(sourcePath, "utf-8");
|
|
416
|
+
templateContent = templateContent.replace(/^\/\/ @ts-nocheck\s*\n/m, "");
|
|
417
|
+
if (!fs2.existsSync(targetPath)) {
|
|
418
|
+
await fs2.writeFile(targetPath, templateContent);
|
|
419
|
+
allFilesAdded.push({ name: "index.ts", path: path2.join(aliasPath, "index.ts") });
|
|
420
|
+
} else {
|
|
421
|
+
const existingContent = await fs2.readFile(targetPath, "utf-8");
|
|
422
|
+
const exportRegex = /export\s+\*\s+from\s+['"]\.\/([^'"]+)['"]/g;
|
|
423
|
+
const templateExports = [];
|
|
424
|
+
let match;
|
|
425
|
+
while ((match = exportRegex.exec(templateContent)) !== null) {
|
|
426
|
+
templateExports.push(match[1]);
|
|
427
|
+
}
|
|
428
|
+
const componentExportExists = existingContent.includes(`export * from './${componentName}'`);
|
|
429
|
+
if (!componentExportExists && templateExports.includes(componentName)) {
|
|
430
|
+
const newExportLine = `export * from './${componentName}'`;
|
|
431
|
+
const updatedContent = existingContent.trim() + "\n" + newExportLine + "\n";
|
|
432
|
+
await fs2.writeFile(targetPath, updatedContent);
|
|
433
|
+
allFilesAdded.push({ name: "index.ts", path: path2.join(aliasPath, "index.ts") });
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
var addCommand = new Command("add").description("Add a component to your project").argument("[component]", "Name of the component (optional when using --all)").option("-y, --yes", "Skip confirmation prompts").option("-o, --overwrite", "Overwrite existing files").option("-a, --all", "Install all available components").action(async (componentName, options) => {
|
|
415
438
|
const spinner = ora("Adding component...").start();
|
|
416
439
|
try {
|
|
417
440
|
const config = await getConfig();
|
|
@@ -420,17 +443,40 @@ var addCommand = new Command("add").description("Add a component to your project
|
|
|
420
443
|
process.exit(1);
|
|
421
444
|
}
|
|
422
445
|
const registry = getComponentRegistry();
|
|
423
|
-
|
|
424
|
-
if (
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
446
|
+
let componentsToInstall = [];
|
|
447
|
+
if (options.all) {
|
|
448
|
+
const allComponents = Object.keys(registry);
|
|
449
|
+
spinner.text = `Installing all ${allComponents.length} components...`;
|
|
450
|
+
const allComponentsWithDeps = /* @__PURE__ */ new Set();
|
|
451
|
+
for (const name of allComponents) {
|
|
452
|
+
allComponentsWithDeps.add(name);
|
|
453
|
+
const deps = getComponentDependencies(name);
|
|
454
|
+
deps.forEach((dep) => allComponentsWithDeps.add(dep));
|
|
455
|
+
}
|
|
456
|
+
componentsToInstall = Array.from(allComponentsWithDeps);
|
|
457
|
+
} else {
|
|
458
|
+
if (!componentName) {
|
|
459
|
+
spinner.fail("\u274C Component name is required when not using --all flag.");
|
|
460
|
+
console.log("Available components:");
|
|
461
|
+
Object.keys(registry).forEach((name) => {
|
|
462
|
+
console.log(` ${chalk.cyan(name)}`);
|
|
463
|
+
});
|
|
464
|
+
process.exit(1);
|
|
465
|
+
}
|
|
466
|
+
const component = registry[componentName];
|
|
467
|
+
if (!component) {
|
|
468
|
+
spinner.fail(`\u274C Component "${componentName}" not found.`);
|
|
469
|
+
console.log("Available components:");
|
|
470
|
+
Object.keys(registry).forEach((name) => {
|
|
471
|
+
console.log(` ${chalk.cyan(name)}`);
|
|
472
|
+
});
|
|
473
|
+
process.exit(1);
|
|
474
|
+
}
|
|
475
|
+
componentsToInstall = [componentName, ...getComponentDependencies(componentName)];
|
|
476
|
+
}
|
|
477
|
+
if (!options.all) {
|
|
478
|
+
spinner.text = `Installing ${componentsToInstall.join(", ")}...`;
|
|
431
479
|
}
|
|
432
|
-
const componentsToInstall = [componentName, ...getComponentDependencies(componentName)];
|
|
433
|
-
spinner.text = `Installing ${componentsToInstall.join(", ")}...`;
|
|
434
480
|
const componentDir = path2.join(process.cwd(), config.aliases.ui.replace("@/", "src/"));
|
|
435
481
|
await fs2.ensureDir(componentDir);
|
|
436
482
|
let allFilesAdded = [];
|
|
@@ -474,14 +520,18 @@ var addCommand = new Command("add").description("Add a component to your project
|
|
|
474
520
|
for (const file of comp.files) {
|
|
475
521
|
const sourcePath = path2.join(__dirname2, "../templates", name, file.name);
|
|
476
522
|
const targetPath = path2.join(componentDir, file.name);
|
|
477
|
-
if (
|
|
478
|
-
|
|
479
|
-
|
|
523
|
+
if (file.name === "index.ts") {
|
|
524
|
+
await handleIndexFile(sourcePath, targetPath, name, allFilesAdded, config.aliases.ui);
|
|
525
|
+
} else {
|
|
526
|
+
if (fs2.existsSync(targetPath) && !options.overwrite) {
|
|
527
|
+
spinner.warn(`\u26A0\uFE0F ${file.name} already exists. Use --overwrite to replace it.`);
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
let content = await fs2.readFile(sourcePath, "utf-8");
|
|
531
|
+
content = content.replace(/^\/\/ @ts-nocheck\s*\n/m, "");
|
|
532
|
+
await fs2.writeFile(targetPath, content);
|
|
533
|
+
allFilesAdded.push({ name: file.name, path: path2.join(config.aliases.ui, file.name) });
|
|
480
534
|
}
|
|
481
|
-
let content = await fs2.readFile(sourcePath, "utf-8");
|
|
482
|
-
content = content.replace(/^\/\/ @ts-nocheck\s*\n/m, "");
|
|
483
|
-
await fs2.writeFile(targetPath, content);
|
|
484
|
-
allFilesAdded.push({ name: file.name, path: path2.join(config.aliases.ui, file.name) });
|
|
485
535
|
}
|
|
486
536
|
if (comp.dependencies?.length) {
|
|
487
537
|
allDepsInstalled.push(...comp.dependencies);
|
|
@@ -492,12 +542,12 @@ var addCommand = new Command("add").description("Add a component to your project
|
|
|
492
542
|
spinner.text = "Updating Tailwind configuration...";
|
|
493
543
|
tailwindConfigInfo = await ensureTailwindConfig(allDepsInstalled);
|
|
494
544
|
}
|
|
545
|
+
const packageJsonPath = path2.join(process.cwd(), "package.json");
|
|
546
|
+
const packageJson = JSON.parse(await fs2.readFile(packageJsonPath, "utf-8"));
|
|
547
|
+
const allDeps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
548
|
+
const missingDeps = [...new Set(allDepsInstalled)].filter((dep) => !allDeps[dep]);
|
|
495
549
|
if (allDepsInstalled.length > 0) {
|
|
496
550
|
spinner.text = "Installing dependencies...";
|
|
497
|
-
const packageJsonPath = path2.join(process.cwd(), "package.json");
|
|
498
|
-
const packageJson = JSON.parse(await fs2.readFile(packageJsonPath, "utf-8"));
|
|
499
|
-
const allDeps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
500
|
-
const missingDeps = [...new Set(allDepsInstalled)].filter((dep) => !allDeps[dep]);
|
|
501
551
|
if (missingDeps.length > 0) {
|
|
502
552
|
try {
|
|
503
553
|
const packageManager = getPackageManager();
|
|
@@ -506,9 +556,15 @@ var addCommand = new Command("add").description("Add a component to your project
|
|
|
506
556
|
} catch (error) {
|
|
507
557
|
spinner.warn(`\u26A0\uFE0F Failed to install dependencies. Please install manually: ${missingDeps.join(" ")}`);
|
|
508
558
|
}
|
|
559
|
+
} else {
|
|
560
|
+
spinner.text = "All dependencies already installed.";
|
|
509
561
|
}
|
|
510
562
|
}
|
|
511
|
-
|
|
563
|
+
if (options.all) {
|
|
564
|
+
spinner.succeed(`\u2705 Added all ${componentsToInstall.length} components!`);
|
|
565
|
+
} else {
|
|
566
|
+
spinner.succeed(`\u2705 Added ${componentsToInstall.join(", ")} component(s)!`);
|
|
567
|
+
}
|
|
512
568
|
console.log();
|
|
513
569
|
console.log("Files added:");
|
|
514
570
|
allFilesAdded.forEach((file) => {
|
|
@@ -522,12 +578,18 @@ var addCommand = new Command("add").description("Add a component to your project
|
|
|
522
578
|
console.log(` ${chalk.blue("~")} tailwind.config.js (updated with tailwindcss-animate plugin)`);
|
|
523
579
|
}
|
|
524
580
|
}
|
|
525
|
-
if (
|
|
581
|
+
if (missingDeps.length > 0) {
|
|
526
582
|
console.log();
|
|
527
583
|
console.log("Dependencies installed:");
|
|
528
|
-
|
|
584
|
+
missingDeps.forEach((dep) => {
|
|
529
585
|
console.log(` ${chalk.green("\u2713")} ${dep}`);
|
|
530
586
|
});
|
|
587
|
+
} else if (allDepsInstalled.length > 0) {
|
|
588
|
+
console.log();
|
|
589
|
+
console.log("Dependencies (already installed):");
|
|
590
|
+
[...new Set(allDepsInstalled)].forEach((dep) => {
|
|
591
|
+
console.log(` ${chalk.blue("~")} ${dep}`);
|
|
592
|
+
});
|
|
531
593
|
}
|
|
532
594
|
} catch (error) {
|
|
533
595
|
spinner.fail(`\u274C Failed to add component: ${error instanceof Error ? error.message : error}`);
|
|
@@ -556,18 +618,21 @@ var initCommand = new Command2("init").description("Initialize Dinachi UI in you
|
|
|
556
618
|
console.log(chalk2.red("\u274C No package.json found. Please run this command in a valid project."));
|
|
557
619
|
process.exit(1);
|
|
558
620
|
}
|
|
621
|
+
const projectConfig = detectProjectType();
|
|
622
|
+
console.log(chalk2.gray(`Detected ${projectConfig.framework} project`));
|
|
623
|
+
console.log();
|
|
559
624
|
const response = await prompts([
|
|
560
625
|
{
|
|
561
626
|
type: "text",
|
|
562
627
|
name: "componentsPath",
|
|
563
628
|
message: "Where would you like to install components?",
|
|
564
|
-
initial:
|
|
629
|
+
initial: projectConfig.componentsPath
|
|
565
630
|
},
|
|
566
631
|
{
|
|
567
632
|
type: "text",
|
|
568
633
|
name: "utilsPath",
|
|
569
634
|
message: "Where would you like to install utilities?",
|
|
570
|
-
initial:
|
|
635
|
+
initial: projectConfig.utilsPath
|
|
571
636
|
},
|
|
572
637
|
{
|
|
573
638
|
type: "confirm",
|
|
@@ -603,13 +668,14 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
603
668
|
const installCmd = `${packageManager} ${packageManager === "npm" ? "install" : "add"} ${deps.join(" ")}`;
|
|
604
669
|
execSync2(installCmd, { stdio: "inherit" });
|
|
605
670
|
}
|
|
671
|
+
const rscEnabled = projectConfig.framework === "next.js";
|
|
606
672
|
const configContent = `{
|
|
607
673
|
"style": "default",
|
|
608
|
-
"rsc":
|
|
674
|
+
"rsc": ${rscEnabled},
|
|
609
675
|
"tsx": true,
|
|
610
676
|
"tailwind": {
|
|
611
|
-
"config": "
|
|
612
|
-
"css": "
|
|
677
|
+
"config": "${projectConfig.tailwindConfig}",
|
|
678
|
+
"css": "${projectConfig.cssPath}",
|
|
613
679
|
"baseColor": "slate",
|
|
614
680
|
"cssVariables": true
|
|
615
681
|
},
|
|
@@ -629,6 +695,18 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
629
695
|
console.log(` 1. Add a component: ${chalk2.cyan("npx @dinachi/cli add button")}`);
|
|
630
696
|
console.log(` 2. Components will be installed to: ${chalk2.cyan("@/components/ui")}`);
|
|
631
697
|
console.log(` 3. Utils available at: ${chalk2.cyan("@/lib/utils")}`);
|
|
698
|
+
if (projectConfig.framework === "next.js") {
|
|
699
|
+
console.log();
|
|
700
|
+
console.log(chalk2.blue("\u{1F4DD} Next.js specific notes:"));
|
|
701
|
+
console.log(` - RSC (React Server Components) enabled in config`);
|
|
702
|
+
console.log(` - Make sure to add "use client" directive if needed`);
|
|
703
|
+
console.log(` - Tailwind config set to: ${chalk2.cyan(projectConfig.tailwindConfig)}`);
|
|
704
|
+
} else if (projectConfig.framework === "remix") {
|
|
705
|
+
console.log();
|
|
706
|
+
console.log(chalk2.blue("\u{1F4DD} Remix specific notes:"));
|
|
707
|
+
console.log(` - Components will be installed to: ${chalk2.cyan(projectConfig.componentsPath)}`);
|
|
708
|
+
console.log(` - Utils will be installed to: ${chalk2.cyan(projectConfig.utilsPath)}`);
|
|
709
|
+
}
|
|
632
710
|
console.log();
|
|
633
711
|
console.log("\u{1F4A1} Tip: Install globally for shorter commands:");
|
|
634
712
|
console.log(` ${chalk2.cyan("npm install -g @dinachi/cli")}`);
|
|
@@ -643,6 +721,69 @@ function getPackageManager2() {
|
|
|
643
721
|
if (fs3.existsSync("yarn.lock")) return "yarn";
|
|
644
722
|
return "npm";
|
|
645
723
|
}
|
|
724
|
+
function detectProjectType() {
|
|
725
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
726
|
+
if (!fs3.existsSync(packageJsonPath)) {
|
|
727
|
+
return {
|
|
728
|
+
framework: "react",
|
|
729
|
+
componentsPath: "./src/components/ui",
|
|
730
|
+
utilsPath: "./src/lib",
|
|
731
|
+
tailwindConfig: "tailwind.config.js",
|
|
732
|
+
cssPath: "src/index.css",
|
|
733
|
+
srcDir: "src"
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf-8"));
|
|
737
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
738
|
+
if (deps.next) {
|
|
739
|
+
return {
|
|
740
|
+
framework: "next.js",
|
|
741
|
+
componentsPath: "./src/components/ui",
|
|
742
|
+
utilsPath: "./src/lib",
|
|
743
|
+
tailwindConfig: "tailwind.config.ts",
|
|
744
|
+
cssPath: "src/app/globals.css",
|
|
745
|
+
srcDir: "src"
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
if (deps.vite || deps["@vitejs/plugin-react"]) {
|
|
749
|
+
return {
|
|
750
|
+
framework: "vite",
|
|
751
|
+
componentsPath: "./src/components/ui",
|
|
752
|
+
utilsPath: "./src/lib",
|
|
753
|
+
tailwindConfig: "tailwind.config.js",
|
|
754
|
+
cssPath: "src/index.css",
|
|
755
|
+
srcDir: "src"
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
if (deps["react-scripts"]) {
|
|
759
|
+
return {
|
|
760
|
+
framework: "create-react-app",
|
|
761
|
+
componentsPath: "./src/components/ui",
|
|
762
|
+
utilsPath: "./src/lib",
|
|
763
|
+
tailwindConfig: "tailwind.config.js",
|
|
764
|
+
cssPath: "src/index.css",
|
|
765
|
+
srcDir: "src"
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
if (deps["@remix-run/react"]) {
|
|
769
|
+
return {
|
|
770
|
+
framework: "remix",
|
|
771
|
+
componentsPath: "./app/components/ui",
|
|
772
|
+
utilsPath: "./app/lib",
|
|
773
|
+
tailwindConfig: "tailwind.config.ts",
|
|
774
|
+
cssPath: "app/tailwind.css",
|
|
775
|
+
srcDir: "app"
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
return {
|
|
779
|
+
framework: "react",
|
|
780
|
+
componentsPath: "./src/components/ui",
|
|
781
|
+
utilsPath: "./src/lib",
|
|
782
|
+
tailwindConfig: "tailwind.config.js",
|
|
783
|
+
cssPath: "src/index.css",
|
|
784
|
+
srcDir: "src"
|
|
785
|
+
};
|
|
786
|
+
}
|
|
646
787
|
|
|
647
788
|
// src/index.ts
|
|
648
789
|
var program = new Command3();
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@ import { cva, type VariantProps } from "class-variance-authority"
|
|
|
4
4
|
import { cn } from "@/lib/utils"
|
|
5
5
|
|
|
6
6
|
const buttonVariants = cva(
|
|
7
|
-
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
7
|
+
"inline-flex items-center cursor-pointer justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
8
8
|
{
|
|
9
9
|
variants: {
|
|
10
10
|
variant: {
|
|
@@ -12,7 +12,7 @@ const DialogTrigger = React.forwardRef<
|
|
|
12
12
|
<BaseDialog.Trigger
|
|
13
13
|
ref={ref}
|
|
14
14
|
className={cn(
|
|
15
|
-
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors",
|
|
15
|
+
"inline-flex items-center cursor-pointer justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors",
|
|
16
16
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
17
17
|
"disabled:pointer-events-none disabled:opacity-50",
|
|
18
18
|
"bg-primary text-primary-foreground hover:bg-primary/90",
|
|
@@ -23,7 +23,7 @@ const SelectTrigger = React.forwardRef<
|
|
|
23
23
|
<SelectPrimitive.Trigger
|
|
24
24
|
ref={ref}
|
|
25
25
|
className={cn(
|
|
26
|
-
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
26
|
+
"flex h-10 w-full items-center cursor-pointer justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
27
27
|
className
|
|
28
28
|
)}
|
|
29
29
|
{...props}
|