create-kofi-stack 2.1.1 → 2.1.3
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 +98 -23
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -409,17 +409,54 @@ async function generateProject(config, options = {}) {
|
|
|
409
409
|
p2.log.info(`Creating project in ${pc2.cyan(config.targetDir)}`);
|
|
410
410
|
console.log();
|
|
411
411
|
try {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
412
|
+
const presetUrl = buildShadcnPresetUrl(config);
|
|
413
|
+
if (config.structure === "standalone") {
|
|
414
|
+
spinner.start("Creating project with shadcn/ui...");
|
|
415
|
+
try {
|
|
416
|
+
await execa("pnpm", ["dlx", "shadcn@latest", "create", config.projectName, "--template", "next", "--preset", presetUrl, "--src-dir"], {
|
|
417
|
+
cwd: path2.dirname(config.targetDir),
|
|
418
|
+
stdio: "pipe"
|
|
419
|
+
});
|
|
420
|
+
spinner.succeed("Base project created with shadcn/ui");
|
|
421
|
+
} catch {
|
|
422
|
+
if (await fs.pathExists(config.targetDir)) {
|
|
423
|
+
spinner.succeed("Base project created with shadcn/ui");
|
|
424
|
+
} else {
|
|
425
|
+
spinner.fail("Failed to create project with shadcn");
|
|
426
|
+
throw new Error("shadcn create failed and project directory was not created");
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
const workspaceFile = path2.join(config.targetDir, "pnpm-workspace.yaml");
|
|
430
|
+
if (await fs.pathExists(workspaceFile)) {
|
|
431
|
+
await fs.remove(workspaceFile);
|
|
432
|
+
}
|
|
433
|
+
spinner.start("Adding Convex and authentication...");
|
|
434
|
+
const result = await generateVirtualProject(config);
|
|
435
|
+
if (!result.success) {
|
|
436
|
+
spinner.fail("Failed to generate project files");
|
|
437
|
+
console.error(pc2.red("Errors:"), result.errors?.join("\n"));
|
|
438
|
+
process.exit(1);
|
|
439
|
+
}
|
|
440
|
+
await writeNodeToDisk(result.tree.root, config.targetDir, {
|
|
441
|
+
skipExisting: ["src/app/globals.css", "tailwind.config.ts", "components.json", "next.config.ts", "postcss.config.mjs"]
|
|
442
|
+
});
|
|
443
|
+
spinner.succeed("Convex and authentication added");
|
|
444
|
+
spinner.start("Merging dependencies...");
|
|
445
|
+
await mergePackageJson(config.targetDir, result.tree.root);
|
|
446
|
+
spinner.succeed("Dependencies merged");
|
|
447
|
+
} else {
|
|
448
|
+
spinner.start("Generating project files...");
|
|
449
|
+
const result = await generateVirtualProject(config);
|
|
450
|
+
if (!result.success) {
|
|
451
|
+
spinner.fail("Failed to generate project");
|
|
452
|
+
console.error(pc2.red("Errors:"), result.errors?.join("\n"));
|
|
453
|
+
process.exit(1);
|
|
454
|
+
}
|
|
455
|
+
spinner.succeed("Project files generated");
|
|
456
|
+
spinner.start("Writing files to disk...");
|
|
457
|
+
await writeNodeToDisk(result.tree.root, config.targetDir);
|
|
458
|
+
spinner.succeed("Files written to disk");
|
|
418
459
|
}
|
|
419
|
-
spinner.succeed("Project files generated");
|
|
420
|
-
spinner.start("Writing files to disk...");
|
|
421
|
-
await writeNodeToDisk(result.tree.root, config.targetDir);
|
|
422
|
-
spinner.succeed("Files written to disk");
|
|
423
460
|
spinner.start("Generating secrets...");
|
|
424
461
|
const backendEnvPath = config.structure === "monorepo" ? path2.join(config.targetDir, "packages/backend/.env.local") : path2.join(config.targetDir, ".env.local");
|
|
425
462
|
await updateEnvWithSecrets(backendEnvPath, {
|
|
@@ -450,17 +487,17 @@ async function generateProject(config, options = {}) {
|
|
|
450
487
|
spinner.warn("Failed to install dependencies. Run pnpm install manually.");
|
|
451
488
|
}
|
|
452
489
|
const shadcnDir = config.structure === "monorepo" ? path2.join(config.targetDir, "apps/web") : config.targetDir;
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
490
|
+
if (config.structure === "monorepo") {
|
|
491
|
+
spinner.start("Initializing shadcn/ui in apps/web...");
|
|
492
|
+
try {
|
|
493
|
+
await execa("pnpm", ["dlx", "shadcn@latest", "init", "--defaults", "--force"], {
|
|
494
|
+
cwd: shadcnDir,
|
|
495
|
+
stdio: "pipe"
|
|
496
|
+
});
|
|
497
|
+
spinner.succeed("shadcn/ui initialized");
|
|
498
|
+
} catch {
|
|
499
|
+
spinner.warn("Failed to initialize shadcn. Run manually in apps/web: pnpm dlx shadcn@latest init");
|
|
500
|
+
}
|
|
464
501
|
}
|
|
465
502
|
spinner.start("Installing shadcn/ui components...");
|
|
466
503
|
try {
|
|
@@ -630,8 +667,13 @@ async function setupPayload(config) {
|
|
|
630
667
|
}
|
|
631
668
|
p2.log.success("Payload CMS configured successfully!");
|
|
632
669
|
}
|
|
633
|
-
async function writeNodeToDisk(node, targetDir) {
|
|
670
|
+
async function writeNodeToDisk(node, targetDir, options = {}) {
|
|
671
|
+
const { skipExisting = [], basePath = "" } = options;
|
|
634
672
|
if (node.type === "file") {
|
|
673
|
+
const relativePath = basePath ? `${basePath}/${node.name}` : node.name;
|
|
674
|
+
if (skipExisting.includes(relativePath)) {
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
635
677
|
const filePath = path2.join(targetDir, node.name);
|
|
636
678
|
await fs.ensureDir(path2.dirname(filePath));
|
|
637
679
|
if (Buffer.isBuffer(node.content)) {
|
|
@@ -642,7 +684,11 @@ async function writeNodeToDisk(node, targetDir) {
|
|
|
642
684
|
} else {
|
|
643
685
|
await fs.ensureDir(targetDir);
|
|
644
686
|
for (const child of node.children) {
|
|
687
|
+
const childRelativePath = basePath ? `${basePath}/${child.name}` : child.name;
|
|
645
688
|
if (child.type === "file") {
|
|
689
|
+
if (skipExisting.includes(childRelativePath)) {
|
|
690
|
+
continue;
|
|
691
|
+
}
|
|
646
692
|
const filePath = path2.join(targetDir, child.name);
|
|
647
693
|
await fs.ensureDir(path2.dirname(filePath));
|
|
648
694
|
if (Buffer.isBuffer(child.content)) {
|
|
@@ -651,11 +697,40 @@ async function writeNodeToDisk(node, targetDir) {
|
|
|
651
697
|
await fs.writeFile(filePath, child.content, "utf-8");
|
|
652
698
|
}
|
|
653
699
|
} else {
|
|
654
|
-
await writeNodeToDisk(child, path2.join(targetDir, child.name)
|
|
700
|
+
await writeNodeToDisk(child, path2.join(targetDir, child.name), {
|
|
701
|
+
skipExisting,
|
|
702
|
+
basePath: childRelativePath
|
|
703
|
+
});
|
|
655
704
|
}
|
|
656
705
|
}
|
|
657
706
|
}
|
|
658
707
|
}
|
|
708
|
+
async function mergePackageJson(targetDir, virtualRoot) {
|
|
709
|
+
const packageJsonPath = path2.join(targetDir, "package.json");
|
|
710
|
+
const existingPkg = await fs.readJson(packageJsonPath);
|
|
711
|
+
let ourPkgContent;
|
|
712
|
+
if (virtualRoot.type === "directory") {
|
|
713
|
+
const pkgFile = virtualRoot.children.find((c) => c.name === "package.json");
|
|
714
|
+
if (pkgFile?.type === "file" && typeof pkgFile.content === "string") {
|
|
715
|
+
ourPkgContent = pkgFile.content;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
if (!ourPkgContent) return;
|
|
719
|
+
const ourPkg = JSON.parse(ourPkgContent);
|
|
720
|
+
existingPkg.dependencies = {
|
|
721
|
+
...existingPkg.dependencies,
|
|
722
|
+
...ourPkg.dependencies
|
|
723
|
+
};
|
|
724
|
+
existingPkg.devDependencies = {
|
|
725
|
+
...existingPkg.devDependencies,
|
|
726
|
+
...ourPkg.devDependencies
|
|
727
|
+
};
|
|
728
|
+
existingPkg.scripts = {
|
|
729
|
+
...existingPkg.scripts,
|
|
730
|
+
...ourPkg.scripts
|
|
731
|
+
};
|
|
732
|
+
await fs.writeJson(packageJsonPath, existingPkg, { spaces: 2 });
|
|
733
|
+
}
|
|
659
734
|
|
|
660
735
|
// src/index.ts
|
|
661
736
|
import { readFileSync } from "fs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-kofi-stack",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"description": "Scaffold opinionated full-stack projects with Next.js, Convex, Better-Auth, and more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"gradient-string": "^2.0.2",
|
|
18
18
|
"ora": "^8.0.0",
|
|
19
19
|
"picocolors": "^1.0.0",
|
|
20
|
-
"kofi-stack-
|
|
21
|
-
"kofi-stack-
|
|
20
|
+
"kofi-stack-types": "^2.1.0",
|
|
21
|
+
"kofi-stack-template-generator": "^2.1.3"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/fs-extra": "^11.0.4",
|