create-bunspace 0.3.1 → 0.5.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/bin.js +335 -34
- package/dist/templates/fumadocs/MUST-FOLLOW-GUIDELINES.md +1616 -40
- package/dist/templates/monorepo/MUST-FOLLOW-GUIDELINES.md +1616 -40
- package/dist/templates/react-starter/MUST-FOLLOW-GUIDELINES.md +1845 -0
- package/dist/templates/react-starter/README.md +100 -0
- package/dist/templates/react-starter/bun.lock +1298 -0
- package/dist/templates/react-starter/components.json +27 -0
- package/dist/templates/react-starter/eslint.config.js +23 -0
- package/dist/templates/react-starter/index.html +36 -0
- package/dist/templates/react-starter/package.json +57 -0
- package/dist/templates/react-starter/public/registry.json +115 -0
- package/dist/templates/react-starter/public/themes/darkmatteviolet-dark.css +34 -0
- package/dist/templates/react-starter/public/themes/darkmatteviolet-light.css +34 -0
- package/dist/templates/react-starter/public/themes/default-dark.css +33 -0
- package/dist/templates/react-starter/public/themes/default-light.css +34 -0
- package/dist/templates/react-starter/public/themes/graphite-dark.css +34 -0
- package/dist/templates/react-starter/public/themes/graphite-light.css +34 -0
- package/dist/templates/react-starter/public/themes/synthwave84-dark.css +34 -0
- package/dist/templates/react-starter/public/themes/synthwave84-light.css +34 -0
- package/dist/templates/react-starter/public/vite.svg +1 -0
- package/dist/templates/react-starter/src/App.tsx +245 -0
- package/dist/templates/react-starter/src/assets/react.svg +1 -0
- package/dist/templates/react-starter/src/components/ThemeSelector.tsx +106 -0
- package/dist/templates/react-starter/src/components/animate-ui/components/buttons/icon.tsx +86 -0
- package/dist/templates/react-starter/src/components/animate-ui/components/buttons/theme-toggler.tsx +92 -0
- package/dist/templates/react-starter/src/components/animate-ui/primitives/animate/slot.tsx +96 -0
- package/dist/templates/react-starter/src/components/animate-ui/primitives/buttons/button.tsx +31 -0
- package/dist/templates/react-starter/src/components/animate-ui/primitives/effects/particles.tsx +155 -0
- package/dist/templates/react-starter/src/components/animate-ui/primitives/effects/theme-toggler.tsx +148 -0
- package/dist/templates/react-starter/src/components/component-example.tsx +444 -0
- package/dist/templates/react-starter/src/components/example.tsx +56 -0
- package/dist/templates/react-starter/src/index.css +131 -0
- package/dist/templates/react-starter/src/main.tsx +13 -0
- package/dist/templates/react-starter/src/providers/ThemeProvider.tsx +27 -0
- package/dist/templates/react-starter/tsconfig.app.json +36 -0
- package/dist/templates/react-starter/tsconfig.json +13 -0
- package/dist/templates/react-starter/tsconfig.node.json +26 -0
- package/dist/templates/react-starter/vite.config.ts +17 -0
- package/dist/templates/telegram-bot/MUST-FOLLOW-GUIDELINES.md +1845 -0
- package/package.json +6 -3
- package/templates/fumadocs/MUST-FOLLOW-GUIDELINES.md +1616 -40
- package/templates/monorepo/MUST-FOLLOW-GUIDELINES.md +1616 -40
- package/templates/react-starter/MUST-FOLLOW-GUIDELINES.md +1845 -0
- package/templates/react-starter/README.md +100 -0
- package/templates/react-starter/bun.lock +1298 -0
- package/templates/react-starter/components.json +27 -0
- package/templates/react-starter/eslint.config.js +23 -0
- package/templates/react-starter/index.html +36 -0
- package/templates/react-starter/package.json +57 -0
- package/templates/react-starter/public/registry.json +115 -0
- package/templates/react-starter/public/themes/darkmatteviolet-dark.css +34 -0
- package/templates/react-starter/public/themes/darkmatteviolet-light.css +34 -0
- package/templates/react-starter/public/themes/default-dark.css +33 -0
- package/templates/react-starter/public/themes/default-light.css +34 -0
- package/templates/react-starter/public/themes/graphite-dark.css +34 -0
- package/templates/react-starter/public/themes/graphite-light.css +34 -0
- package/templates/react-starter/public/themes/synthwave84-dark.css +34 -0
- package/templates/react-starter/public/themes/synthwave84-light.css +34 -0
- package/templates/react-starter/public/vite.svg +1 -0
- package/templates/react-starter/src/App.tsx +245 -0
- package/templates/react-starter/src/assets/react.svg +1 -0
- package/templates/react-starter/src/components/ThemeSelector.tsx +106 -0
- package/templates/react-starter/src/components/animate-ui/components/buttons/icon.tsx +86 -0
- package/templates/react-starter/src/components/animate-ui/components/buttons/theme-toggler.tsx +92 -0
- package/templates/react-starter/src/components/animate-ui/primitives/animate/slot.tsx +96 -0
- package/templates/react-starter/src/components/animate-ui/primitives/buttons/button.tsx +31 -0
- package/templates/react-starter/src/components/animate-ui/primitives/effects/particles.tsx +155 -0
- package/templates/react-starter/src/components/animate-ui/primitives/effects/theme-toggler.tsx +148 -0
- package/templates/react-starter/src/components/component-example.tsx +444 -0
- package/templates/react-starter/src/components/example.tsx +56 -0
- package/templates/react-starter/src/index.css +131 -0
- package/templates/react-starter/src/main.tsx +13 -0
- package/templates/react-starter/src/providers/ThemeProvider.tsx +27 -0
- package/templates/react-starter/tsconfig.app.json +36 -0
- package/templates/react-starter/tsconfig.json +13 -0
- package/templates/react-starter/tsconfig.node.json +26 -0
- package/templates/react-starter/vite.config.ts +17 -0
- package/templates/telegram-bot/MUST-FOLLOW-GUIDELINES.md +1845 -0
package/dist/bin.js
CHANGED
|
@@ -5189,6 +5189,11 @@ async function selectTemplate(args) {
|
|
|
5189
5189
|
title: "Fumadocs - Documentaci\xF3n con Next.js + MDX + Fumadocs",
|
|
5190
5190
|
value: "fumadocs",
|
|
5191
5191
|
description: "Bilingual documentation site with GitHub Pages deployment"
|
|
5192
|
+
},
|
|
5193
|
+
{
|
|
5194
|
+
title: "React Starter - BaseUI + React 19 + Vite 8 + Theme Manager",
|
|
5195
|
+
value: "react-starter",
|
|
5196
|
+
description: "Opinionated React starter with animated UI components and theme management"
|
|
5192
5197
|
}
|
|
5193
5198
|
]
|
|
5194
5199
|
}, {
|
|
@@ -5444,6 +5449,69 @@ Operation cancelled`));
|
|
|
5444
5449
|
runInstall: args.noInstall ? false : response.runInstall ?? true
|
|
5445
5450
|
};
|
|
5446
5451
|
}
|
|
5452
|
+
async function promptReactStarter(args) {
|
|
5453
|
+
const gitUser = await getGitUser();
|
|
5454
|
+
const parsed = parseProjectArg(args.projectName);
|
|
5455
|
+
const response = await import_prompts.default([
|
|
5456
|
+
{
|
|
5457
|
+
type: args.projectName ? null : "text",
|
|
5458
|
+
name: "name",
|
|
5459
|
+
message: "Project name",
|
|
5460
|
+
initial: parsed.name,
|
|
5461
|
+
validate: (value) => {
|
|
5462
|
+
if (!value)
|
|
5463
|
+
return "Project name is required";
|
|
5464
|
+
if (!isValidProjectName(value)) {
|
|
5465
|
+
return "Invalid name. Use lowercase letters, numbers, and hyphens only";
|
|
5466
|
+
}
|
|
5467
|
+
return true;
|
|
5468
|
+
},
|
|
5469
|
+
format: (value) => value.toLowerCase().trim()
|
|
5470
|
+
},
|
|
5471
|
+
{
|
|
5472
|
+
type: args.description ? null : "text",
|
|
5473
|
+
name: "description",
|
|
5474
|
+
message: "Description",
|
|
5475
|
+
initial: "React app with BaseUI, theme management, and animated components"
|
|
5476
|
+
},
|
|
5477
|
+
{
|
|
5478
|
+
type: args.author ? null : "text",
|
|
5479
|
+
name: "author",
|
|
5480
|
+
message: "Author",
|
|
5481
|
+
initial: gitUser || "Anonymous"
|
|
5482
|
+
},
|
|
5483
|
+
{
|
|
5484
|
+
type: args.noGit ? null : "confirm",
|
|
5485
|
+
name: "initGit",
|
|
5486
|
+
message: "Initialize git repository?",
|
|
5487
|
+
initial: true
|
|
5488
|
+
},
|
|
5489
|
+
{
|
|
5490
|
+
type: args.noInstall ? null : "confirm",
|
|
5491
|
+
name: "runInstall",
|
|
5492
|
+
message: "Run bun install?",
|
|
5493
|
+
initial: true
|
|
5494
|
+
}
|
|
5495
|
+
], {
|
|
5496
|
+
onCancel: () => {
|
|
5497
|
+
console.log(kleur_default.red(`
|
|
5498
|
+
Operation cancelled`));
|
|
5499
|
+
process.exit(0);
|
|
5500
|
+
}
|
|
5501
|
+
});
|
|
5502
|
+
const name = args.projectName ? parsed.name : response.name;
|
|
5503
|
+
const targetDir = args.dir || `./${name}`;
|
|
5504
|
+
return {
|
|
5505
|
+
template: "react-starter",
|
|
5506
|
+
name,
|
|
5507
|
+
scope: "",
|
|
5508
|
+
description: args.description || response.description || "",
|
|
5509
|
+
author: args.author || response.author || gitUser || "Anonymous",
|
|
5510
|
+
targetDir,
|
|
5511
|
+
initGit: args.noGit ? false : response.initGit ?? true,
|
|
5512
|
+
runInstall: args.noInstall ? false : response.runInstall ?? true
|
|
5513
|
+
};
|
|
5514
|
+
}
|
|
5447
5515
|
async function promptUser(args, templateType) {
|
|
5448
5516
|
if (templateType === "telegram-bot") {
|
|
5449
5517
|
return promptTelegramBot(args);
|
|
@@ -5451,6 +5519,9 @@ async function promptUser(args, templateType) {
|
|
|
5451
5519
|
if (templateType === "fumadocs") {
|
|
5452
5520
|
return promptFumadocs(args);
|
|
5453
5521
|
}
|
|
5522
|
+
if (templateType === "react-starter") {
|
|
5523
|
+
return promptReactStarter(args);
|
|
5524
|
+
}
|
|
5454
5525
|
return promptMonorepo(args);
|
|
5455
5526
|
}
|
|
5456
5527
|
async function getDefaultsMonorepo(args) {
|
|
@@ -5512,13 +5583,192 @@ async function getDefaults(args, templateType) {
|
|
|
5512
5583
|
if (templateType === "fumadocs") {
|
|
5513
5584
|
return getDefaultsFumadocs(args);
|
|
5514
5585
|
}
|
|
5586
|
+
if (templateType === "react-starter") {
|
|
5587
|
+
return getDefaultsReactStarter(args);
|
|
5588
|
+
}
|
|
5515
5589
|
return getDefaultsMonorepo(args);
|
|
5516
5590
|
}
|
|
5591
|
+
async function getDefaultsReactStarter(args) {
|
|
5592
|
+
const gitUser = await getGitUser();
|
|
5593
|
+
const parsed = parseProjectArg(args.projectName);
|
|
5594
|
+
const targetDir = args.dir || parsed.targetDir;
|
|
5595
|
+
return {
|
|
5596
|
+
template: "react-starter",
|
|
5597
|
+
name: parsed.name,
|
|
5598
|
+
scope: "",
|
|
5599
|
+
description: args.description || "React app with BaseUI, theme management, and animated components",
|
|
5600
|
+
author: args.author || gitUser || "Anonymous",
|
|
5601
|
+
targetDir,
|
|
5602
|
+
initGit: !args.noGit,
|
|
5603
|
+
runInstall: !args.noInstall
|
|
5604
|
+
};
|
|
5605
|
+
}
|
|
5517
5606
|
|
|
5518
5607
|
// src/generator.ts
|
|
5519
|
-
import { mkdir, readdir, stat, readFile, writeFile, copyFile, rename } from "fs/promises";
|
|
5520
|
-
import { join, dirname } from "path";
|
|
5608
|
+
import { mkdir, readdir, stat as stat2, readFile as readFile2, writeFile as writeFile2, copyFile, rename } from "fs/promises";
|
|
5609
|
+
import { join as join2, dirname } from "path";
|
|
5610
|
+
import { existsSync as existsSync2 } from "fs";
|
|
5611
|
+
|
|
5612
|
+
// src/guidelines-service.ts
|
|
5521
5613
|
import { existsSync } from "fs";
|
|
5614
|
+
import { readFile, writeFile } from "fs/promises";
|
|
5615
|
+
import { join } from "path";
|
|
5616
|
+
import { homedir } from "os";
|
|
5617
|
+
var LOCAL_DOTFILES_PATH = join(homedir(), "dotfiles", "MUST-FOLLOW-GUIDELINES.md");
|
|
5618
|
+
var GITHUB_RAW_URL = "https://raw.githubusercontent.com/MKS2508/dotfiles/main/MUST-FOLLOW-GUIDELINES.md";
|
|
5619
|
+
var GUIDELINES_FILENAME = "MUST-FOLLOW-GUIDELINES.md";
|
|
5620
|
+
async function fetchGuidelines() {
|
|
5621
|
+
if (existsSync(LOCAL_DOTFILES_PATH)) {
|
|
5622
|
+
try {
|
|
5623
|
+
const content = await readFile(LOCAL_DOTFILES_PATH, "utf-8");
|
|
5624
|
+
const lines = content.split(`
|
|
5625
|
+
`).length;
|
|
5626
|
+
return { content, source: "local", lines };
|
|
5627
|
+
} catch {
|
|
5628
|
+
console.log(kleur_default.yellow(" \u26A0\uFE0F Failed to read local dotfiles, trying GitHub..."));
|
|
5629
|
+
}
|
|
5630
|
+
}
|
|
5631
|
+
try {
|
|
5632
|
+
const response = await fetch(GITHUB_RAW_URL);
|
|
5633
|
+
if (response.ok) {
|
|
5634
|
+
const content = await response.text();
|
|
5635
|
+
const lines = content.split(`
|
|
5636
|
+
`).length;
|
|
5637
|
+
return { content, source: "github", lines };
|
|
5638
|
+
}
|
|
5639
|
+
} catch {}
|
|
5640
|
+
return null;
|
|
5641
|
+
}
|
|
5642
|
+
async function getGuidelinesForGeneration() {
|
|
5643
|
+
const result = await fetchGuidelines();
|
|
5644
|
+
return result?.content ?? null;
|
|
5645
|
+
}
|
|
5646
|
+
async function syncGuidelinesToTemplate(templatePath, templateName, guidelinesContent) {
|
|
5647
|
+
const guidelinesPath = join(templatePath, GUIDELINES_FILENAME);
|
|
5648
|
+
const linesCount = guidelinesContent.split(`
|
|
5649
|
+
`).length;
|
|
5650
|
+
if (!existsSync(templatePath)) {
|
|
5651
|
+
return {
|
|
5652
|
+
templateName,
|
|
5653
|
+
success: false,
|
|
5654
|
+
action: "skipped",
|
|
5655
|
+
error: "Template directory not found"
|
|
5656
|
+
};
|
|
5657
|
+
}
|
|
5658
|
+
try {
|
|
5659
|
+
if (existsSync(guidelinesPath)) {
|
|
5660
|
+
const existingContent = await readFile(guidelinesPath, "utf-8");
|
|
5661
|
+
if (existingContent === guidelinesContent) {
|
|
5662
|
+
return {
|
|
5663
|
+
templateName,
|
|
5664
|
+
success: true,
|
|
5665
|
+
action: "unchanged",
|
|
5666
|
+
linesCount
|
|
5667
|
+
};
|
|
5668
|
+
}
|
|
5669
|
+
await writeFile(guidelinesPath, guidelinesContent, "utf-8");
|
|
5670
|
+
return {
|
|
5671
|
+
templateName,
|
|
5672
|
+
success: true,
|
|
5673
|
+
action: "updated",
|
|
5674
|
+
linesCount
|
|
5675
|
+
};
|
|
5676
|
+
}
|
|
5677
|
+
await writeFile(guidelinesPath, guidelinesContent, "utf-8");
|
|
5678
|
+
return {
|
|
5679
|
+
templateName,
|
|
5680
|
+
success: true,
|
|
5681
|
+
action: "created",
|
|
5682
|
+
linesCount
|
|
5683
|
+
};
|
|
5684
|
+
} catch (error) {
|
|
5685
|
+
return {
|
|
5686
|
+
templateName,
|
|
5687
|
+
success: false,
|
|
5688
|
+
action: "skipped",
|
|
5689
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
5690
|
+
};
|
|
5691
|
+
}
|
|
5692
|
+
}
|
|
5693
|
+
async function syncGuidelinesToAllTemplates(templatesDir, templateNames) {
|
|
5694
|
+
const guidelines = await fetchGuidelines();
|
|
5695
|
+
if (!guidelines) {
|
|
5696
|
+
console.log(kleur_default.yellow(`
|
|
5697
|
+
\u26A0\uFE0F Guidelines not available (no local dotfiles or internet)`));
|
|
5698
|
+
return templateNames.map((name) => ({
|
|
5699
|
+
templateName: name,
|
|
5700
|
+
success: false,
|
|
5701
|
+
action: "skipped",
|
|
5702
|
+
error: "Guidelines source unavailable"
|
|
5703
|
+
}));
|
|
5704
|
+
}
|
|
5705
|
+
console.log(`
|
|
5706
|
+
\uD83D\uDCCB Syncing ${kleur_default.cyan(GUIDELINES_FILENAME)} from ${kleur_default.dim(guidelines.source)}...`);
|
|
5707
|
+
console.log(` ${kleur_default.dim(`(${guidelines.lines} lines)`)}
|
|
5708
|
+
`);
|
|
5709
|
+
const results = [];
|
|
5710
|
+
for (const name of templateNames) {
|
|
5711
|
+
const templatePath = join(templatesDir, name);
|
|
5712
|
+
const result = await syncGuidelinesToTemplate(templatePath, name, guidelines.content);
|
|
5713
|
+
results.push(result);
|
|
5714
|
+
const icon = result.success ? result.action === "unchanged" ? "\u2713" : "\u2705" : "\u274C";
|
|
5715
|
+
const actionText = result.action === "created" ? kleur_default.green("created") : result.action === "updated" ? kleur_default.yellow("updated") : result.action === "unchanged" ? kleur_default.dim("unchanged") : kleur_default.red("skipped");
|
|
5716
|
+
console.log(` ${icon} ${kleur_default.cyan(name)}: ${actionText}${result.error ? ` - ${result.error}` : ""}`);
|
|
5717
|
+
}
|
|
5718
|
+
return results;
|
|
5719
|
+
}
|
|
5720
|
+
async function checkGuidelinesStatus(templatesDir, templateNames) {
|
|
5721
|
+
console.log(`
|
|
5722
|
+
\uD83D\uDCCB ${kleur_default.bold("Guidelines Status Check")}
|
|
5723
|
+
`);
|
|
5724
|
+
const guidelines = await fetchGuidelines();
|
|
5725
|
+
if (guidelines) {
|
|
5726
|
+
console.log(` ${kleur_default.green("\u2713")} Source: ${kleur_default.cyan(guidelines.source)}`);
|
|
5727
|
+
console.log(` ${kleur_default.green("\u2713")} Lines: ${kleur_default.cyan(guidelines.lines.toString())}`);
|
|
5728
|
+
if (guidelines.source === "local") {
|
|
5729
|
+
console.log(` ${kleur_default.dim(` Path: ${LOCAL_DOTFILES_PATH}`)}`);
|
|
5730
|
+
} else {
|
|
5731
|
+
console.log(` ${kleur_default.dim(` URL: ${GITHUB_RAW_URL}`)}`);
|
|
5732
|
+
}
|
|
5733
|
+
} else {
|
|
5734
|
+
console.log(` ${kleur_default.red("\u2717")} Guidelines unavailable`);
|
|
5735
|
+
console.log(` ${kleur_default.dim(` Local: ${LOCAL_DOTFILES_PATH} (not found)`)}`);
|
|
5736
|
+
console.log(` ${kleur_default.dim(` GitHub: ${GITHUB_RAW_URL} (unreachable)`)}`);
|
|
5737
|
+
return;
|
|
5738
|
+
}
|
|
5739
|
+
console.log(`
|
|
5740
|
+
${kleur_default.bold("Template Status:")}
|
|
5741
|
+
`);
|
|
5742
|
+
for (const name of templateNames) {
|
|
5743
|
+
const templatePath = join(templatesDir, name);
|
|
5744
|
+
const guidelinesPath = join(templatePath, GUIDELINES_FILENAME);
|
|
5745
|
+
if (!existsSync(templatePath)) {
|
|
5746
|
+
console.log(` ${kleur_default.red("\u2717")} ${kleur_default.cyan(name)}: ${kleur_default.dim("template not found")}`);
|
|
5747
|
+
continue;
|
|
5748
|
+
}
|
|
5749
|
+
if (!existsSync(guidelinesPath)) {
|
|
5750
|
+
console.log(` ${kleur_default.yellow("\u26A0")} ${kleur_default.cyan(name)}: ${kleur_default.yellow("missing")}`);
|
|
5751
|
+
continue;
|
|
5752
|
+
}
|
|
5753
|
+
try {
|
|
5754
|
+
const content = await readFile(guidelinesPath, "utf-8");
|
|
5755
|
+
const templateLines = content.split(`
|
|
5756
|
+
`).length;
|
|
5757
|
+
const isUpToDate = content === guidelines.content;
|
|
5758
|
+
if (isUpToDate) {
|
|
5759
|
+
console.log(` ${kleur_default.green("\u2713")} ${kleur_default.cyan(name)}: ${kleur_default.green("up to date")} (${templateLines} lines)`);
|
|
5760
|
+
} else {
|
|
5761
|
+
console.log(` ${kleur_default.yellow("\u26A0")} ${kleur_default.cyan(name)}: ${kleur_default.yellow("outdated")} (${templateLines} lines vs ${guidelines.lines})`);
|
|
5762
|
+
}
|
|
5763
|
+
} catch {
|
|
5764
|
+
console.log(` ${kleur_default.red("\u2717")} ${kleur_default.cyan(name)}: ${kleur_default.red("error reading file")}`);
|
|
5765
|
+
}
|
|
5766
|
+
}
|
|
5767
|
+
console.log("");
|
|
5768
|
+
}
|
|
5769
|
+
|
|
5770
|
+
// src/generator.ts
|
|
5771
|
+
var GUIDELINES_FILENAME2 = "MUST-FOLLOW-GUIDELINES.md";
|
|
5522
5772
|
var TEXT_EXTENSIONS = new Set([
|
|
5523
5773
|
".ts",
|
|
5524
5774
|
".tsx",
|
|
@@ -5557,12 +5807,12 @@ var EXCLUDED_FILES = new Set([
|
|
|
5557
5807
|
".DS_Store"
|
|
5558
5808
|
]);
|
|
5559
5809
|
async function getTemplateDir(templateType) {
|
|
5560
|
-
const submodulePath =
|
|
5561
|
-
if (
|
|
5810
|
+
const submodulePath = join2(import.meta.dir, "..", "templates", templateType);
|
|
5811
|
+
if (existsSync2(submodulePath)) {
|
|
5562
5812
|
return submodulePath;
|
|
5563
5813
|
}
|
|
5564
|
-
const distPath =
|
|
5565
|
-
if (
|
|
5814
|
+
const distPath = join2(import.meta.dir, "..", "..", "templates", templateType);
|
|
5815
|
+
if (existsSync2(distPath)) {
|
|
5566
5816
|
return distPath;
|
|
5567
5817
|
}
|
|
5568
5818
|
throw new Error(`Template '${templateType}' not found. Checked submodules and embedded templates.`);
|
|
@@ -5570,7 +5820,7 @@ async function getTemplateDir(templateType) {
|
|
|
5570
5820
|
async function generateProject(config, templateType) {
|
|
5571
5821
|
const templateDir = await getTemplateDir(templateType);
|
|
5572
5822
|
const targetDir = config.targetDir;
|
|
5573
|
-
if (
|
|
5823
|
+
if (existsSync2(targetDir)) {
|
|
5574
5824
|
const entries = await readdir(targetDir);
|
|
5575
5825
|
if (entries.length > 0) {
|
|
5576
5826
|
printError(`Directory ${targetDir} is not empty`);
|
|
@@ -5583,12 +5833,23 @@ async function generateProject(config, templateType) {
|
|
|
5583
5833
|
printStep("Copying template files...");
|
|
5584
5834
|
await copyTemplateDir(templateDir, targetDir, placeholders);
|
|
5585
5835
|
if (templateType === "fumadocs") {
|
|
5586
|
-
const contentTemplatePath =
|
|
5587
|
-
const contentPath =
|
|
5588
|
-
if (
|
|
5836
|
+
const contentTemplatePath = join2(targetDir, "content-template");
|
|
5837
|
+
const contentPath = join2(targetDir, "content");
|
|
5838
|
+
if (existsSync2(contentTemplatePath)) {
|
|
5589
5839
|
await rename(contentTemplatePath, contentPath);
|
|
5590
5840
|
}
|
|
5591
5841
|
}
|
|
5842
|
+
printStep("Syncing MUST-FOLLOW-GUIDELINES.md...");
|
|
5843
|
+
const guidelinesContent = await getGuidelinesForGeneration();
|
|
5844
|
+
if (guidelinesContent) {
|
|
5845
|
+
const guidelinesPath = join2(targetDir, GUIDELINES_FILENAME2);
|
|
5846
|
+
await writeFile2(guidelinesPath, guidelinesContent, "utf-8");
|
|
5847
|
+
const lines = guidelinesContent.split(`
|
|
5848
|
+
`).length;
|
|
5849
|
+
printStep(`Guidelines synced (${lines} lines)`);
|
|
5850
|
+
} else {
|
|
5851
|
+
printStep("Guidelines source unavailable, using template version");
|
|
5852
|
+
}
|
|
5592
5853
|
if (config.initGit) {
|
|
5593
5854
|
printStep("Initializing git repository...");
|
|
5594
5855
|
await initGit(targetDir);
|
|
@@ -5631,6 +5892,15 @@ function generatePlaceholders(config, templateType) {
|
|
|
5631
5892
|
SUPPORTED_LOCALES: config.supportedLocales || "es,en"
|
|
5632
5893
|
};
|
|
5633
5894
|
}
|
|
5895
|
+
if (templateType === "react-starter") {
|
|
5896
|
+
const projectTitle = config.name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
5897
|
+
return {
|
|
5898
|
+
...base,
|
|
5899
|
+
PROJECT_NAME: config.name,
|
|
5900
|
+
PROJECT_TITLE: projectTitle,
|
|
5901
|
+
DESCRIPTION: config.description
|
|
5902
|
+
};
|
|
5903
|
+
}
|
|
5634
5904
|
throw new Error(`Unknown template: ${templateType}`);
|
|
5635
5905
|
}
|
|
5636
5906
|
async function copyTemplateDir(src, dest, placeholders) {
|
|
@@ -5638,9 +5908,9 @@ async function copyTemplateDir(src, dest, placeholders) {
|
|
|
5638
5908
|
for (const entry of entries) {
|
|
5639
5909
|
if (EXCLUDED_FILES.has(entry))
|
|
5640
5910
|
continue;
|
|
5641
|
-
const srcPath =
|
|
5642
|
-
const destPath =
|
|
5643
|
-
const stats = await
|
|
5911
|
+
const srcPath = join2(src, entry);
|
|
5912
|
+
const destPath = join2(dest, entry);
|
|
5913
|
+
const stats = await stat2(srcPath);
|
|
5644
5914
|
if (stats.isDirectory()) {
|
|
5645
5915
|
await mkdir(destPath, { recursive: true });
|
|
5646
5916
|
await copyTemplateDir(srcPath, destPath, placeholders);
|
|
@@ -5660,9 +5930,9 @@ function shouldReplacePlaceholders(filepath) {
|
|
|
5660
5930
|
async function copyTemplateFile(src, dest, placeholders) {
|
|
5661
5931
|
await mkdir(dirname(dest), { recursive: true });
|
|
5662
5932
|
if (shouldReplacePlaceholders(src)) {
|
|
5663
|
-
const content = await
|
|
5933
|
+
const content = await readFile2(src, "utf-8");
|
|
5664
5934
|
const replaced = replacePlaceholders(content, placeholders);
|
|
5665
|
-
await
|
|
5935
|
+
await writeFile2(dest, replaced, "utf-8");
|
|
5666
5936
|
} else {
|
|
5667
5937
|
await copyFile(src, dest);
|
|
5668
5938
|
}
|
|
@@ -5694,24 +5964,25 @@ async function runBunInstall(targetDir) {
|
|
|
5694
5964
|
|
|
5695
5965
|
// src/template-manager.ts
|
|
5696
5966
|
import { spawn } from "child_process";
|
|
5697
|
-
import { existsSync as
|
|
5698
|
-
import { join as
|
|
5699
|
-
var ROOT_DIR =
|
|
5700
|
-
var TEMPLATES_DIR =
|
|
5967
|
+
import { existsSync as existsSync3 } from "fs";
|
|
5968
|
+
import { join as join3 } from "path";
|
|
5969
|
+
var ROOT_DIR = join3(import.meta.dir, "..");
|
|
5970
|
+
var TEMPLATES_DIR = join3(ROOT_DIR, "templates");
|
|
5971
|
+
var ALL_TEMPLATES = ["monorepo", "telegram-bot", "fumadocs"];
|
|
5701
5972
|
async function listTemplates() {
|
|
5702
5973
|
console.log(`
|
|
5703
5974
|
\uD83D\uDCE6 Templates Status:
|
|
5704
5975
|
`);
|
|
5705
5976
|
const templates = ["monorepo", "telegram-bot", "fumadocs"];
|
|
5706
5977
|
for (const name of templates) {
|
|
5707
|
-
const templatePath =
|
|
5708
|
-
if (!
|
|
5978
|
+
const templatePath = join3(TEMPLATES_DIR, name);
|
|
5979
|
+
if (!existsSync3(templatePath)) {
|
|
5709
5980
|
console.log(` \u274C ${name} (missing)
|
|
5710
5981
|
`);
|
|
5711
5982
|
continue;
|
|
5712
5983
|
}
|
|
5713
|
-
const gitDir =
|
|
5714
|
-
if (
|
|
5984
|
+
const gitDir = join3(templatePath, ".git");
|
|
5985
|
+
if (existsSync3(gitDir)) {
|
|
5715
5986
|
try {
|
|
5716
5987
|
const url = await execGit(["config", "remote.origin.url"], { cwd: templatePath, silent: true });
|
|
5717
5988
|
const branch = await execGit(["rev-parse", "--abbrev-ref", "HEAD"], { cwd: templatePath, silent: true });
|
|
@@ -5731,19 +6002,19 @@ async function listTemplates() {
|
|
|
5731
6002
|
}
|
|
5732
6003
|
}
|
|
5733
6004
|
async function syncTemplates(templateName) {
|
|
5734
|
-
const templates = templateName ? [templateName] :
|
|
6005
|
+
const templates = templateName ? [templateName] : ALL_TEMPLATES;
|
|
5735
6006
|
console.log(`
|
|
5736
6007
|
\uD83D\uDD04 Syncing ${templateName ? kleur_default.cyan(templateName) : "all templates"}...
|
|
5737
6008
|
`);
|
|
5738
6009
|
for (const name of templates) {
|
|
5739
|
-
const templatePath =
|
|
5740
|
-
if (!
|
|
6010
|
+
const templatePath = join3(TEMPLATES_DIR, name);
|
|
6011
|
+
if (!existsSync3(templatePath)) {
|
|
5741
6012
|
console.log(` \u26A0\uFE0F Template '${name}' not found. Skipping.
|
|
5742
6013
|
`);
|
|
5743
6014
|
continue;
|
|
5744
6015
|
}
|
|
5745
|
-
const gitDir =
|
|
5746
|
-
if (
|
|
6016
|
+
const gitDir = join3(templatePath, ".git");
|
|
6017
|
+
if (existsSync3(gitDir)) {
|
|
5747
6018
|
console.log(` \uD83D\uDCE5 ${kleur_default.cyan(name)}:`);
|
|
5748
6019
|
try {
|
|
5749
6020
|
await execGit(["pull", "--ff-only"], { cwd: templatePath });
|
|
@@ -5758,21 +6029,22 @@ async function syncTemplates(templateName) {
|
|
|
5758
6029
|
`);
|
|
5759
6030
|
}
|
|
5760
6031
|
}
|
|
6032
|
+
await syncGuidelinesToAllTemplates(TEMPLATES_DIR, templates);
|
|
5761
6033
|
console.log(`${kleur_default.green("\u2728")} Sync complete!
|
|
5762
6034
|
`);
|
|
5763
6035
|
}
|
|
5764
6036
|
async function importTemplate(name, sourcePath) {
|
|
5765
|
-
const targetPath =
|
|
6037
|
+
const targetPath = join3(TEMPLATES_DIR, name);
|
|
5766
6038
|
console.log(`
|
|
5767
6039
|
\uD83D\uDCE6 Importing '${kleur_default.cyan(name)}' from ${sourcePath}...
|
|
5768
6040
|
`);
|
|
5769
|
-
if (
|
|
6041
|
+
if (existsSync3(targetPath)) {
|
|
5770
6042
|
console.log(` \u26A0\uFE0F Template '${name}' already exists.
|
|
5771
6043
|
`);
|
|
5772
6044
|
return;
|
|
5773
6045
|
}
|
|
5774
|
-
const sourceGitDir =
|
|
5775
|
-
if (
|
|
6046
|
+
const sourceGitDir = join3(sourcePath, ".git");
|
|
6047
|
+
if (existsSync3(sourceGitDir)) {
|
|
5776
6048
|
console.log(` \uD83D\uDD17 Adding as submodule...`);
|
|
5777
6049
|
try {
|
|
5778
6050
|
await execGit(["submodule", "add", sourcePath, `templates/${name}`]);
|
|
@@ -5846,6 +6118,10 @@ async function main(args) {
|
|
|
5846
6118
|
await handleTemplatesCommand(args.slice(1));
|
|
5847
6119
|
return;
|
|
5848
6120
|
}
|
|
6121
|
+
if (args[0] === "guidelines") {
|
|
6122
|
+
await handleGuidelinesCommand(args.slice(1));
|
|
6123
|
+
return;
|
|
6124
|
+
}
|
|
5849
6125
|
try {
|
|
5850
6126
|
const templateType = await selectTemplate(parsedArgs);
|
|
5851
6127
|
const config = parsedArgs.yes ? await getDefaults(parsedArgs, templateType) : await promptUser(parsedArgs, templateType);
|
|
@@ -5878,9 +6154,9 @@ async function handleTemplatesCommand(args) {
|
|
|
5878
6154
|
break;
|
|
5879
6155
|
default:
|
|
5880
6156
|
console.error(`
|
|
5881
|
-
|
|
6157
|
+
Unknown template command: ${command}
|
|
5882
6158
|
|
|
5883
|
-
|
|
6159
|
+
Available commands:
|
|
5884
6160
|
bun run cli templates list List all templates
|
|
5885
6161
|
bun run cli templates sync [name] Sync templates from git
|
|
5886
6162
|
bun run cli templates import <name> <path> Import template from local path
|
|
@@ -5888,6 +6164,31 @@ ${printError.info("Available commands:")}
|
|
|
5888
6164
|
process.exit(1);
|
|
5889
6165
|
}
|
|
5890
6166
|
}
|
|
6167
|
+
async function handleGuidelinesCommand(args) {
|
|
6168
|
+
const command = args[0];
|
|
6169
|
+
const templateName = args[1];
|
|
6170
|
+
const templates = templateName ? [templateName] : ALL_TEMPLATES;
|
|
6171
|
+
switch (command) {
|
|
6172
|
+
case "sync":
|
|
6173
|
+
await syncGuidelinesToAllTemplates(TEMPLATES_DIR, templates);
|
|
6174
|
+
console.log(`
|
|
6175
|
+
\u2728 Guidelines sync complete!
|
|
6176
|
+
`);
|
|
6177
|
+
break;
|
|
6178
|
+
case "check":
|
|
6179
|
+
await checkGuidelinesStatus(TEMPLATES_DIR, ALL_TEMPLATES);
|
|
6180
|
+
break;
|
|
6181
|
+
default:
|
|
6182
|
+
console.error(`
|
|
6183
|
+
Unknown guidelines command: ${command || "(none)"}
|
|
6184
|
+
|
|
6185
|
+
Available commands:
|
|
6186
|
+
bun run cli guidelines sync [template] Sync MUST-FOLLOW-GUIDELINES.md to templates
|
|
6187
|
+
bun run cli guidelines check Check guidelines status across templates
|
|
6188
|
+
`);
|
|
6189
|
+
process.exit(1);
|
|
6190
|
+
}
|
|
6191
|
+
}
|
|
5891
6192
|
|
|
5892
6193
|
// bin.ts
|
|
5893
6194
|
main(process.argv.slice(2));
|