bunkit-cli 0.7.0 → 0.8.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.
Files changed (3) hide show
  1. package/README.md +61 -3
  2. package/dist/index.js +684 -178
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3773,22 +3773,23 @@ var quotes, getRandomQuote = () => {
3773
3773
  `, createBanner = (version = "0.3.1") => {
3774
3774
  const quote = getRandomQuote();
3775
3775
  const content = [
3776
- source_default.yellow(logo.trim()),
3776
+ source_default.yellowBright(logo.trim()),
3777
3777
  "",
3778
- source_default.cyan("\uD83C\uDF5E Bake production-ready apps in seconds"),
3779
- source_default.dim("Modern \u2022 Fast \u2022 Opinionated"),
3778
+ source_default.bold.cyan("\uD83C\uDF5E Bake production-ready apps in seconds"),
3779
+ source_default.dim("Modern \u2022 Fast \u2022 Opinionated \u2022 Type-Safe"),
3780
3780
  "",
3781
- source_default.cyan(quote),
3781
+ source_default.italic.cyan(quote),
3782
3782
  "",
3783
- source_default.dim(`v${version}`)
3783
+ source_default.dim(`Version ${version}`)
3784
3784
  ].join(`
3785
3785
  `);
3786
3786
  return boxen(content, {
3787
- padding: 1,
3787
+ padding: { top: 1, bottom: 1, left: 2, right: 2 },
3788
3788
  margin: { top: 1, bottom: 1 },
3789
- borderColor: "gray",
3789
+ borderColor: "cyan",
3790
3790
  borderStyle: "round",
3791
- dimBorder: true
3791
+ title: "bunkit",
3792
+ titleAlignment: "center"
3792
3793
  });
3793
3794
  }, showBanner = (version) => {
3794
3795
  console.log(createBanner(version));
@@ -22651,7 +22652,10 @@ var init_types2 = __esm(() => {
22651
22652
  features: exports_external.array(exports_external.string()).optional(),
22652
22653
  git: exports_external.boolean().default(true),
22653
22654
  install: exports_external.boolean().default(true),
22654
- database: exports_external.enum(["postgres-drizzle", "supabase", "sqlite-drizzle", "none"]).optional(),
22655
+ database: exports_external.enum(["postgres-drizzle", "supabase", "supabase-drizzle", "sqlite-drizzle", "none"]).optional(),
22656
+ supabasePreset: exports_external.enum(["full-stack", "auth-only", "database-only", "custom"]).optional(),
22657
+ supabaseFeatures: exports_external.array(exports_external.enum(["auth", "storage", "realtime", "edge-functions", "database"])).optional(),
22658
+ supabaseWithDrizzle: exports_external.boolean().optional(),
22655
22659
  codeQuality: exports_external.enum(["ultracite", "biome"]).default("ultracite"),
22656
22660
  tsStrictness: exports_external.enum(["strict", "moderate", "loose"]).default("strict"),
22657
22661
  uiLibrary: exports_external.enum(["shadcn", "none"]).optional(),
@@ -22813,7 +22817,10 @@ function createTemplateContext(config) {
22813
22817
  pathAliases: config.pathAliases,
22814
22818
  shadcnStyle: config.shadcnStyle,
22815
22819
  shadcnBaseColor: config.shadcnBaseColor,
22816
- shadcnRadius: config.shadcnRadius
22820
+ shadcnRadius: config.shadcnRadius,
22821
+ supabasePreset: config.supabasePreset,
22822
+ supabaseFeatures: config.supabaseFeatures,
22823
+ supabaseWithDrizzle: config.supabaseWithDrizzle
22817
22824
  };
22818
22825
  }
22819
22826
  var import_fs_extra2;
@@ -24539,14 +24546,13 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
24539
24546
 
24540
24547
  // src/index.ts
24541
24548
  init_src();
24542
- var import_picocolors7 = __toESM(require_picocolors(), 1);
24549
+ var import_picocolors6 = __toESM(require_picocolors(), 1);
24543
24550
 
24544
24551
  // src/commands/init.enhanced.ts
24545
24552
  init_boxen();
24546
24553
  init_source();
24547
24554
  init_dist();
24548
24555
  init_src();
24549
- var import_picocolors4 = __toESM(require_picocolors(), 1);
24550
24556
 
24551
24557
  // ../templates/src/render.ts
24552
24558
  var import_ejs = __toESM(require_ejs(), 1);
@@ -24909,12 +24915,12 @@ services:
24909
24915
  - "3000:3000"
24910
24916
  environment:
24911
24917
  - NODE_ENV=production
24912
- ${context.database && context.database !== "none" && context.database !== "supabase" ? "- DATABASE_URL=${DATABASE_URL:-postgres://postgres:postgres@db:5432/${context.projectName}}" : ""}
24913
- ${context.database && context.database !== "none" && context.database !== "supabase" ? `depends_on:
24918
+ ${context.database && context.database !== "none" && context.database !== "supabase" && context.database !== "supabase-drizzle" ? "- DATABASE_URL=${DATABASE_URL:-postgres://postgres:postgres@db:5432/${context.projectName}}" : ""}
24919
+ ${context.database && context.database !== "none" && context.database !== "supabase" && context.database !== "supabase-drizzle" ? `depends_on:
24914
24920
  - db` : ""}
24915
24921
  restart: unless-stopped
24916
24922
 
24917
- ${context.database && context.database !== "none" && context.database !== "supabase" ? `db:
24923
+ ${context.database && context.database !== "none" && context.database !== "supabase" && context.database !== "supabase-drizzle" ? `db:
24918
24924
  image: ${context.database === "sqlite-drizzle" ? "alpine:latest" : "postgres:16-alpine"}
24919
24925
  ${context.database !== "sqlite-drizzle" ? `environment:
24920
24926
  - POSTGRES_USER=postgres
@@ -25069,7 +25075,7 @@ jobs:
25069
25075
  ${context.preset === "web" || context.preset === "full" ? `- name: Build application
25070
25076
  run: bun run build
25071
25077
  env:
25072
- ${context.database === "supabase" ? `NEXT_PUBLIC_SUPABASE_URL: \${{ secrets.SUPABASE_URL }}
25078
+ ${context.database === "supabase" || context.database === "supabase-drizzle" ? `NEXT_PUBLIC_SUPABASE_URL: \${{ secrets.SUPABASE_URL }}
25073
25079
  NEXT_PUBLIC_SUPABASE_ANON_KEY: \${{ secrets.SUPABASE_ANON_KEY }}
25074
25080
  ` : ""}NODE_ENV: production` : ""}
25075
25081
 
@@ -26514,7 +26520,114 @@ DATABASE_URL=postgresql://postgres:postgres@localhost:5432/${context.projectName
26514
26520
  `;
26515
26521
  await writeFile(join(projectPath, ".env.example"), envExample);
26516
26522
  }
26517
- async function setupSupabase(projectPath, context, isMonorepo = false) {
26523
+ async function setupSupabaseOnly(projectPath, context, isMonorepo = false) {
26524
+ const dbPath = isMonorepo ? join(projectPath, "packages/db") : join(projectPath, "src/db");
26525
+ await ensureDirectory(dbPath);
26526
+ const features = context.supabaseFeatures || ["auth", "storage", "realtime", "database"];
26527
+ const hasAuth = features.includes("auth");
26528
+ const hasStorage = features.includes("storage");
26529
+ const hasRealtime = features.includes("realtime");
26530
+ const hasEdgeFunctions = features.includes("edge-functions");
26531
+ const hasDatabase = features.includes("database");
26532
+ const clientContent = `import { createClient } from '@supabase/supabase-js';
26533
+
26534
+ // Supabase client
26535
+ export const supabase = createClient(
26536
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
26537
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
26538
+ {
26539
+ auth: {
26540
+ autoRefreshToken: true,
26541
+ persistSession: true,
26542
+ detectSessionInUrl: true,
26543
+ },
26544
+ }
26545
+ );
26546
+
26547
+ ${hasAuth ? `// Auth helpers
26548
+ export const auth = supabase.auth;` : ""}
26549
+
26550
+ ${hasStorage ? `// Storage helpers
26551
+ export const storage = supabase.storage;` : ""}
26552
+
26553
+ ${hasRealtime ? `// Realtime helpers
26554
+ export const realtime = supabase.realtime;` : ""}
26555
+
26556
+ ${hasEdgeFunctions ? `// Edge Functions helpers
26557
+ export const functions = supabase.functions;` : ""}
26558
+
26559
+ ${hasDatabase ? `// Database helpers (using Supabase client directly)
26560
+ export const db = supabase.from;` : ""}
26561
+ `;
26562
+ await writeFile(join(dbPath, "index.ts"), clientContent);
26563
+ const examplesContent = `// Supabase usage examples
26564
+ import { supabase${hasAuth ? ", auth" : ""}${hasStorage ? ", storage" : ""}${hasRealtime ? ", realtime" : ""}${hasEdgeFunctions ? ", functions" : ""}${hasDatabase ? ", db" : ""} } from './index';
26565
+
26566
+ ${hasAuth ? `// Auth example
26567
+ export async function signUp(email: string, password: string) {
26568
+ const { data, error } = await auth.signUp({
26569
+ email,
26570
+ password,
26571
+ });
26572
+ return { data, error };
26573
+ }
26574
+
26575
+ export async function signIn(email: string, password: string) {
26576
+ const { data, error } = await auth.signInWithPassword({
26577
+ email,
26578
+ password,
26579
+ });
26580
+ return { data, error };
26581
+ }
26582
+
26583
+ export async function signOut() {
26584
+ const { error } = await auth.signOut();
26585
+ return { error };
26586
+ }` : ""}
26587
+
26588
+ ${hasStorage ? `// Storage example
26589
+ export async function uploadFile(bucket: string, path: string, file: File) {
26590
+ const { data, error } = await storage.from(bucket).upload(path, file);
26591
+ return { data, error };
26592
+ }
26593
+
26594
+ export function getPublicUrl(bucket: string, path: string) {
26595
+ const { data } = storage.from(bucket).getPublicUrl(path);
26596
+ return data.publicUrl;
26597
+ }` : ""}
26598
+
26599
+ ${hasRealtime ? `// Realtime example
26600
+ export function subscribeToChannel(channel: string, callback: (payload: any) => void) {
26601
+ const channelInstance = realtime.channel(channel);
26602
+ channelInstance.on('postgres_changes', { event: '*', schema: 'public', table: '*' }, callback);
26603
+ channelInstance.subscribe();
26604
+ return channelInstance;
26605
+ }` : ""}
26606
+
26607
+ ${hasEdgeFunctions ? `// Edge Functions example
26608
+ export async function invokeFunction(functionName: string, body?: any) {
26609
+ const { data, error } = await functions.invoke(functionName, { body });
26610
+ return { data, error };
26611
+ }` : ""}
26612
+
26613
+ ${hasDatabase ? `// Database example (using Supabase client directly)
26614
+ export async function getUsers() {
26615
+ const { data, error } = await supabase.from('users').select('*');
26616
+ return { data, error };
26617
+ }` : ""}
26618
+ `;
26619
+ await writeFile(join(dbPath, "examples.ts"), examplesContent);
26620
+ if (hasEdgeFunctions) {
26621
+ await ensureDirectory(join(projectPath, "supabase/functions"));
26622
+ }
26623
+ const envExample = `# Supabase
26624
+ NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
26625
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
26626
+ ${hasDatabase ? "DATABASE_URL=postgresql://postgres:[password]@db.your-project.supabase.co:5432/postgres" : ""}
26627
+ `;
26628
+ await writeFile(join(projectPath, ".env.example"), envExample);
26629
+ }
26630
+ async function setupSupabaseDrizzle(projectPath, context, isMonorepo = false) {
26518
26631
  const dbPath = isMonorepo ? join(projectPath, "packages/db") : join(projectPath, "src/db");
26519
26632
  await ensureDirectory(join(dbPath, "schema"));
26520
26633
  const drizzleConfig = `import { defineConfig } from 'drizzle-kit';
@@ -26529,6 +26642,12 @@ export default defineConfig({
26529
26642
  });
26530
26643
  `;
26531
26644
  await writeFile(join(isMonorepo ? join(projectPath, "packages/db") : projectPath, "drizzle.config.ts"), drizzleConfig);
26645
+ const features = context.supabaseFeatures || ["auth", "storage", "realtime", "database"];
26646
+ const hasAuth = features.includes("auth");
26647
+ const hasStorage = features.includes("storage");
26648
+ const hasRealtime = features.includes("realtime");
26649
+ const hasEdgeFunctions = features.includes("edge-functions");
26650
+ const hasDatabase = features.includes("database");
26532
26651
  const clientContent = `import { createClient } from '@supabase/supabase-js';
26533
26652
  import { drizzle } from 'drizzle-orm/postgres-js';
26534
26653
  import postgres from 'postgres';
@@ -26537,14 +26656,95 @@ import * as schema from './schema';
26537
26656
  // Supabase client for auth, storage, realtime
26538
26657
  export const supabase = createClient(
26539
26658
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
26540
- process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
26659
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
26660
+ {
26661
+ auth: {
26662
+ autoRefreshToken: true,
26663
+ persistSession: true,
26664
+ detectSessionInUrl: true,
26665
+ },
26666
+ }
26541
26667
  );
26542
26668
 
26669
+ ${hasAuth ? `// Auth helpers
26670
+ export const auth = supabase.auth;` : ""}
26671
+
26672
+ ${hasStorage ? `// Storage helpers
26673
+ export const storage = supabase.storage;` : ""}
26674
+
26675
+ ${hasRealtime ? `// Realtime helpers
26676
+ export const realtime = supabase.realtime;` : ""}
26677
+
26678
+ ${hasEdgeFunctions ? `// Edge Functions helpers
26679
+ export const functions = supabase.functions;` : ""}
26680
+
26543
26681
  // Drizzle client for type-safe database queries
26544
- const queryClient = postgres(process.env.DATABASE_URL!);
26545
- export const db = drizzle(queryClient, { schema });
26682
+ ${hasDatabase ? `const queryClient = postgres(process.env.DATABASE_URL!);
26683
+ export const db = drizzle(queryClient, { schema });` : "// Database queries via Drizzle ORM"}
26546
26684
  `;
26547
26685
  await writeFile(join(dbPath, "index.ts"), clientContent);
26686
+ const examplesContent = `// Supabase + Drizzle usage examples
26687
+ import { supabase${hasAuth ? ", auth" : ""}${hasStorage ? ", storage" : ""}${hasRealtime ? ", realtime" : ""}${hasEdgeFunctions ? ", functions" : ""}, db } from './index';
26688
+ import { users } from './schema';
26689
+ import { eq } from 'drizzle-orm';
26690
+
26691
+ ${hasAuth ? `// Auth example
26692
+ export async function signUp(email: string, password: string) {
26693
+ const { data, error } = await auth.signUp({
26694
+ email,
26695
+ password,
26696
+ });
26697
+ return { data, error };
26698
+ }
26699
+
26700
+ export async function signIn(email: string, password: string) {
26701
+ const { data, error } = await auth.signInWithPassword({
26702
+ email,
26703
+ password,
26704
+ });
26705
+ return { data, error };
26706
+ }
26707
+
26708
+ export async function signOut() {
26709
+ const { error } = await auth.signOut();
26710
+ return { error };
26711
+ }` : ""}
26712
+
26713
+ ${hasStorage ? `// Storage example
26714
+ export async function uploadFile(bucket: string, path: string, file: File) {
26715
+ const { data, error } = await storage.from(bucket).upload(path, file);
26716
+ return { data, error };
26717
+ }
26718
+
26719
+ export function getPublicUrl(bucket: string, path: string) {
26720
+ const { data } = storage.from(bucket).getPublicUrl(path);
26721
+ return data.publicUrl;
26722
+ }` : ""}
26723
+
26724
+ ${hasRealtime ? `// Realtime example
26725
+ export function subscribeToChannel(channel: string, callback: (payload: any) => void) {
26726
+ const channelInstance = realtime.channel(channel);
26727
+ channelInstance.on('postgres_changes', { event: '*', schema: 'public', table: '*' }, callback);
26728
+ channelInstance.subscribe();
26729
+ return channelInstance;
26730
+ }` : ""}
26731
+
26732
+ ${hasEdgeFunctions ? `// Edge Functions example
26733
+ export async function invokeFunction(functionName: string, body?: any) {
26734
+ const { data, error } = await functions.invoke(functionName, { body });
26735
+ return { data, error };
26736
+ }` : ""}
26737
+
26738
+ ${hasDatabase ? `// Database example (using Drizzle ORM)
26739
+ export async function getUsers() {
26740
+ return await db.select().from(users);
26741
+ }
26742
+
26743
+ export async function getUserById(id: string) {
26744
+ return await db.select().from(users).where(eq(users.id, id));
26745
+ }` : ""}
26746
+ `;
26747
+ await writeFile(join(dbPath, "examples.ts"), examplesContent);
26548
26748
  const schemaContent = `import { pgTable, text, timestamp, uuid, boolean } from 'drizzle-orm/pg-core';
26549
26749
 
26550
26750
  export const users = pgTable('users', {
@@ -26568,10 +26768,13 @@ export const profiles = pgTable('profiles', {
26568
26768
  `;
26569
26769
  await writeFile(join(dbPath, "schema/index.ts"), schemaContent);
26570
26770
  await ensureDirectory(join(projectPath, "supabase/migrations"));
26771
+ if (hasEdgeFunctions) {
26772
+ await ensureDirectory(join(projectPath, "supabase/functions"));
26773
+ }
26571
26774
  const envExample = `# Supabase
26572
26775
  NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
26573
26776
  NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
26574
- DATABASE_URL=postgresql://postgres:[password]@db.your-project.supabase.co:5432/postgres
26777
+ ${hasDatabase ? "DATABASE_URL=postgresql://postgres:[password]@db.your-project.supabase.co:5432/postgres" : ""}
26575
26778
  `;
26576
26779
  await writeFile(join(projectPath, ".env.example"), envExample);
26577
26780
  }
@@ -26631,6 +26834,10 @@ function getDatabaseDependencies(databaseType) {
26631
26834
  postgres: "^3.4.5"
26632
26835
  };
26633
26836
  case "supabase":
26837
+ return {
26838
+ "@supabase/supabase-js": "^2.48.1"
26839
+ };
26840
+ case "supabase-drizzle":
26634
26841
  return {
26635
26842
  "@supabase/supabase-js": "^2.48.1",
26636
26843
  "drizzle-orm": "^0.38.0",
@@ -26817,7 +27024,9 @@ coverage = true
26817
27024
  if (context.database === "postgres-drizzle") {
26818
27025
  await setupPostgresDrizzle(projectPath, context, false);
26819
27026
  } else if (context.database === "supabase") {
26820
- await setupSupabase(projectPath, context, false);
27027
+ await setupSupabaseOnly(projectPath, context, false);
27028
+ } else if (context.database === "supabase-drizzle") {
27029
+ await setupSupabaseDrizzle(projectPath, context, false);
26821
27030
  } else if (context.database === "sqlite-drizzle") {
26822
27031
  await setupSQLiteDrizzle(projectPath, context, false);
26823
27032
  }
@@ -27401,14 +27610,21 @@ Built with \u2764\uFE0F using Bun monorepo features
27401
27610
  main: "./src/index.ts",
27402
27611
  types: "./src/index.ts",
27403
27612
  dependencies: context.database === "supabase" ? {
27613
+ "@supabase/supabase-js": "catalog:"
27614
+ } : context.database === "supabase-drizzle" ? {
27404
27615
  "@supabase/supabase-js": "catalog:",
27405
27616
  "drizzle-orm": "catalog:",
27406
27617
  postgres: "catalog:"
27407
- } : {
27618
+ } : context.database === "postgres-drizzle" ? {
27619
+ "drizzle-orm": "catalog:",
27620
+ postgres: "catalog:"
27621
+ } : context.database === "sqlite-drizzle" ? {
27408
27622
  "drizzle-orm": "catalog:"
27409
- },
27623
+ } : {},
27410
27624
  devDependencies: {
27411
- "drizzle-kit": "catalog:",
27625
+ ...context.database === "postgres-drizzle" || context.database === "supabase-drizzle" || context.database === "sqlite-drizzle" ? {
27626
+ "drizzle-kit": "catalog:"
27627
+ } : {},
27412
27628
  "@types/bun": "latest",
27413
27629
  typescript: "catalog:"
27414
27630
  }
@@ -27417,7 +27633,9 @@ Built with \u2764\uFE0F using Bun monorepo features
27417
27633
  if (context.database === "postgres-drizzle") {
27418
27634
  await setupPostgresDrizzle(dbPackagePath, context, true);
27419
27635
  } else if (context.database === "supabase") {
27420
- await setupSupabase(dbPackagePath, context, true);
27636
+ await setupSupabaseOnly(dbPackagePath, context, true);
27637
+ } else if (context.database === "supabase-drizzle") {
27638
+ await setupSupabaseDrizzle(dbPackagePath, context, true);
27421
27639
  } else if (context.database === "sqlite-drizzle") {
27422
27640
  await setupSQLiteDrizzle(dbPackagePath, context, true);
27423
27641
  }
@@ -27443,7 +27661,7 @@ services:
27443
27661
  - "3000:3000"
27444
27662
  environment:
27445
27663
  - NODE_ENV=production
27446
- ${context.database === "supabase" ? "- NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}" : ""}
27664
+ ${context.database === "supabase" || context.database === "supabase-drizzle" ? "- NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}" : ""}
27447
27665
  restart: unless-stopped
27448
27666
 
27449
27667
  platform:
@@ -27454,7 +27672,7 @@ services:
27454
27672
  - "3001:3000"
27455
27673
  environment:
27456
27674
  - NODE_ENV=production
27457
- ${context.database === "supabase" ? "- NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}" : ""}
27675
+ ${context.database === "supabase" || context.database === "supabase-drizzle" ? "- NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL}\n - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}" : ""}
27458
27676
  restart: unless-stopped
27459
27677
 
27460
27678
  api:
@@ -27774,7 +27992,7 @@ async function enhancedInitCommand(options = {}) {
27774
27992
  throw new Error("Project name is required in non-interactive mode. " + "Provide it via BUNKIT_PROJECT_NAME env var or --name flag.");
27775
27993
  }
27776
27994
  projectName = await he({
27777
- message: "\uD83D\uDCE6 What is your project named?",
27995
+ message: "\uD83D\uDCE6 Project name",
27778
27996
  placeholder: "my-awesome-project",
27779
27997
  validate: (value) => {
27780
27998
  const result = validateProjectName(value);
@@ -27798,27 +28016,27 @@ async function enhancedInitCommand(options = {}) {
27798
28016
  throw new Error("Preset is required in non-interactive mode. " + "Provide it via BUNKIT_PRESET env var or --preset flag.");
27799
28017
  }
27800
28018
  preset = await ve({
27801
- message: "\uD83C\uDFA8 Which preset would you like?",
28019
+ message: "\uD83C\uDFA8 Select project preset",
27802
28020
  options: [
27803
28021
  {
27804
28022
  value: "minimal",
27805
28023
  label: "\u26A1 Minimal",
27806
- hint: "Single file, clean start - perfect for learning Bun"
28024
+ hint: "Single-file project, clean start - perfect for CLIs and scripts"
27807
28025
  },
27808
28026
  {
27809
28027
  value: "web",
27810
- label: "\uD83C\uDF10 Web App",
27811
- hint: "Next.js 16 + React 19 - full-stack web application"
28028
+ label: "\uD83C\uDF10 Web Application",
28029
+ hint: "Next.js 16 + React 19 + Tailwind CSS 4 - production-ready web app"
27812
28030
  },
27813
28031
  {
27814
28032
  value: "api",
27815
28033
  label: "\uD83D\uDE80 API Server",
27816
- hint: "Hono + Bun.serve() - ultra-fast REST API"
28034
+ hint: "Hono 4 + Bun.serve() - ultra-fast REST API with native HMR"
27817
28035
  },
27818
28036
  {
27819
28037
  value: "full",
27820
28038
  label: "\uD83D\uDCE6 Full-Stack Monorepo",
27821
- hint: "Web + Platform + API - enterprise SaaS setup"
28039
+ hint: "Web + API + shared packages - enterprise-grade SaaS architecture"
27822
28040
  }
27823
28041
  ]
27824
28042
  });
@@ -27831,27 +28049,32 @@ async function enhancedInitCommand(options = {}) {
27831
28049
  if (!database && (preset === "api" || preset === "full")) {
27832
28050
  if (!isNonInteractive) {
27833
28051
  database = await ve({
27834
- message: "\uD83D\uDDC4\uFE0F Database setup?",
28052
+ message: "\uD83D\uDDC4\uFE0F Database configuration",
27835
28053
  options: [
27836
28054
  {
27837
28055
  value: "postgres-drizzle",
27838
28056
  label: "PostgreSQL + Drizzle ORM",
27839
- hint: "Production-ready, type-safe SQL database"
28057
+ hint: "Production-ready PostgreSQL with type-safe Drizzle ORM queries"
27840
28058
  },
27841
28059
  {
27842
28060
  value: "supabase",
27843
- label: "Supabase",
27844
- hint: "PostgreSQL + Auth + Storage + Realtime - all-in-one"
28061
+ label: "Supabase (Client Only)",
28062
+ hint: "Supabase JS client only - Auth, Storage, Realtime without Drizzle ORM"
28063
+ },
28064
+ {
28065
+ value: "supabase-drizzle",
28066
+ label: "Supabase + Drizzle ORM",
28067
+ hint: "Full Supabase stack with Drizzle ORM for type-safe database queries"
27845
28068
  },
27846
28069
  {
27847
28070
  value: "sqlite-drizzle",
27848
28071
  label: "SQLite + Drizzle ORM",
27849
- hint: "Local-first, embedded database - perfect for prototypes"
28072
+ hint: "Local-first embedded database - perfect for prototypes and local development"
27850
28073
  },
27851
28074
  {
27852
28075
  value: "none",
27853
28076
  label: "None",
27854
- hint: "I'll add it later"
28077
+ hint: "Skip database setup - add later if needed"
27855
28078
  }
27856
28079
  ]
27857
28080
  });
@@ -27863,21 +28086,116 @@ async function enhancedInitCommand(options = {}) {
27863
28086
  database = "none";
27864
28087
  }
27865
28088
  }
28089
+ let supabasePreset;
28090
+ let supabaseFeatures;
28091
+ let supabaseWithDrizzle;
28092
+ if (database === "supabase" || database === "supabase-drizzle") {
28093
+ supabaseWithDrizzle = database === "supabase-drizzle";
28094
+ const presetEnv = process.env.BUNKIT_SUPABASE_PRESET;
28095
+ supabasePreset = presetEnv || options.supabasePreset;
28096
+ if (!supabasePreset && !isNonInteractive) {
28097
+ supabasePreset = await ve({
28098
+ message: "\uD83C\uDFAF Supabase configuration preset",
28099
+ options: [
28100
+ {
28101
+ value: "full-stack",
28102
+ label: "Full Stack (Recommended)",
28103
+ hint: "Complete Supabase setup - Auth, Storage, Realtime, and Database"
28104
+ },
28105
+ {
28106
+ value: "auth-only",
28107
+ label: "Auth Only",
28108
+ hint: "Authentication only - perfect for simple apps with external data"
28109
+ },
28110
+ {
28111
+ value: "database-only",
28112
+ label: "Database Only",
28113
+ hint: "PostgreSQL database access only - no Auth, Storage, or Realtime"
28114
+ },
28115
+ {
28116
+ value: "custom",
28117
+ label: "Custom",
28118
+ hint: "Manually select Supabase features to include"
28119
+ }
28120
+ ]
28121
+ });
28122
+ if (pD(supabasePreset)) {
28123
+ xe("Operation cancelled.");
28124
+ process.exit(0);
28125
+ }
28126
+ } else if (!supabasePreset) {
28127
+ supabasePreset = "full-stack";
28128
+ }
28129
+ if (supabasePreset === "full-stack") {
28130
+ supabaseFeatures = ["auth", "storage", "realtime", "database"];
28131
+ } else if (supabasePreset === "auth-only") {
28132
+ supabaseFeatures = ["auth"];
28133
+ } else if (supabasePreset === "database-only") {
28134
+ supabaseFeatures = ["database"];
28135
+ } else {
28136
+ const availableFeaturesEnv = process.env.BUNKIT_SUPABASE_FEATURES;
28137
+ let availableFeatures;
28138
+ if (availableFeaturesEnv) {
28139
+ availableFeatures = availableFeaturesEnv.split(",").map((f) => f.trim());
28140
+ } else if (options.supabaseFeatures) {
28141
+ availableFeatures = Array.isArray(options.supabaseFeatures) ? options.supabaseFeatures : String(options.supabaseFeatures).split(",").map((f) => f.trim());
28142
+ }
28143
+ if (!availableFeatures && !isNonInteractive) {
28144
+ const selectedFeatures = await fe({
28145
+ message: "\u2728 Select Supabase features to include",
28146
+ options: [
28147
+ {
28148
+ value: "auth",
28149
+ label: "Authentication",
28150
+ hint: "User authentication and authorization (sign up, sign in, sessions)"
28151
+ },
28152
+ {
28153
+ value: "storage",
28154
+ label: "Storage",
28155
+ hint: "File storage and CDN for images, documents, and media"
28156
+ },
28157
+ {
28158
+ value: "realtime",
28159
+ label: "Realtime",
28160
+ hint: "Real-time subscriptions and live updates via WebSockets"
28161
+ },
28162
+ {
28163
+ value: "edge-functions",
28164
+ label: "Edge Functions",
28165
+ hint: "Serverless functions deployed at the edge for low latency"
28166
+ },
28167
+ {
28168
+ value: "database",
28169
+ label: "Database",
28170
+ hint: "PostgreSQL database access via Supabase client"
28171
+ }
28172
+ ]
28173
+ });
28174
+ if (pD(selectedFeatures)) {
28175
+ xe("Operation cancelled.");
28176
+ process.exit(0);
28177
+ }
28178
+ supabaseFeatures = selectedFeatures.length > 0 ? selectedFeatures : ["auth", "database"];
28179
+ } else {
28180
+ supabaseFeatures = availableFeatures || ["auth", "database"];
28181
+ }
28182
+ }
28183
+ }
27866
28184
  let codeQuality = getOptionValue("BUNKIT_CODE_QUALITY", options.codeQuality, "ultracite");
27867
28185
  if (!codeQuality) {
27868
28186
  if (!isNonInteractive) {
27869
28187
  codeQuality = await ve({
27870
- message: "\uD83E\uDD16 Code quality setup?",
28188
+ message: "\uD83E\uDD16 Code quality tool",
27871
28189
  options: [
27872
28190
  {
27873
28191
  value: "ultracite",
27874
28192
  label: "Ultracite (Recommended)",
27875
- hint: "AI-optimized Biome preset - syncs rules for Cursor, Claude, Windsurf"
28193
+ hint: "AI-optimized Biome preset - syncs rules for Cursor, Claude Code, Windsurf, Zed"
27876
28194
  },
27877
28195
  {
27878
28196
  value: "biome",
27879
28197
  label: "Biome",
27880
- hint: "Standard Biome with good defaults - fast and reliable"
28198
+ hint: "Standard Biome configuration - fast, reliable, zero-config linting and formatting"
27881
28199
  }
27882
28200
  ]
27883
28201
  });
@@ -27893,22 +28211,22 @@ async function enhancedInitCommand(options = {}) {
27893
28211
  if (!tsStrictness) {
27894
28212
  if (!isNonInteractive) {
27895
28213
  tsStrictness = await ve({
27896
- message: "\uD83D\uDD12 TypeScript strictness?",
28214
+ message: "\uD83D\uDD12 TypeScript strictness level",
27897
28215
  options: [
27898
28216
  {
27899
28217
  value: "strict",
27900
28218
  label: "Strict (Recommended)",
27901
- hint: "Maximum type safety - catches bugs early, prevents headaches"
28219
+ hint: "Maximum type safety - catches bugs early, prevents runtime errors"
27902
28220
  },
27903
28221
  {
27904
28222
  value: "moderate",
27905
28223
  label: "Moderate",
27906
- hint: "Balanced - good safety without being too rigid"
28224
+ hint: "Balanced type checking - good safety without excessive strictness"
27907
28225
  },
27908
28226
  {
27909
28227
  value: "loose",
27910
28228
  label: "Loose",
27911
- hint: "Minimal checks - quick prototyping, migrate from JavaScript"
28229
+ hint: "Minimal type checking - quick prototyping, easier migration from JavaScript"
27912
28230
  }
27913
28231
  ]
27914
28232
  });
@@ -27924,22 +28242,22 @@ async function enhancedInitCommand(options = {}) {
27924
28242
  if (!cssFramework && (preset === "web" || preset === "full")) {
27925
28243
  if (!isNonInteractive) {
27926
28244
  cssFramework = await ve({
27927
- message: "\uD83C\uDFA8 CSS framework?",
28245
+ message: "\uD83C\uDFA8 CSS framework",
27928
28246
  options: [
27929
28247
  {
27930
28248
  value: "tailwind",
27931
28249
  label: "Tailwind CSS 4 (Recommended)",
27932
- hint: "Utility-first, fast, modern - with OKLCH colors and @theme"
28250
+ hint: "Utility-first CSS framework - fast, modern, with OKLCH colors and @theme"
27933
28251
  },
27934
28252
  {
27935
28253
  value: "vanilla",
27936
28254
  label: "Vanilla CSS",
27937
- hint: "Plain CSS files - full control, no framework"
28255
+ hint: "Plain CSS files - full control, no framework dependencies"
27938
28256
  },
27939
28257
  {
27940
28258
  value: "css-modules",
27941
28259
  label: "CSS Modules",
27942
- hint: "Scoped CSS - automatic class name generation"
28260
+ hint: "Scoped CSS with automatic class name generation - prevents style conflicts"
27943
28261
  }
27944
28262
  ]
27945
28263
  });
@@ -27955,17 +28273,17 @@ async function enhancedInitCommand(options = {}) {
27955
28273
  if (!uiLibrary && (preset === "web" || preset === "full") && cssFramework === "tailwind") {
27956
28274
  if (!isNonInteractive) {
27957
28275
  uiLibrary = await ve({
27958
- message: "\uD83E\uDDE9 UI component library?",
28276
+ message: "\uD83E\uDDE9 UI component library",
27959
28277
  options: [
27960
28278
  {
27961
28279
  value: "shadcn",
27962
28280
  label: "shadcn/ui (Recommended)",
27963
- hint: "64+ components, accessible, customizable - production-ready"
28281
+ hint: "64+ accessible components, fully customizable, production-ready"
27964
28282
  },
27965
28283
  {
27966
28284
  value: "none",
27967
28285
  label: "None",
27968
- hint: "I'll build my own components"
28286
+ hint: "Skip UI library - build custom components or add later"
27969
28287
  }
27970
28288
  ]
27971
28289
  });
@@ -27981,17 +28299,17 @@ async function enhancedInitCommand(options = {}) {
27981
28299
  if (!shadcnStyle && uiLibrary === "shadcn") {
27982
28300
  if (!isNonInteractive) {
27983
28301
  shadcnStyle = await ve({
27984
- message: "\uD83C\uDFA8 shadcn/ui style?",
28302
+ message: "\uD83C\uDFA8 shadcn/ui component style",
27985
28303
  options: [
27986
28304
  {
27987
28305
  value: "new-york",
27988
28306
  label: "New York (Recommended)",
27989
- hint: "Modern, clean design with rounded corners and subtle shadows"
28307
+ hint: "Modern design aesthetic - rounded corners, subtle shadows, clean look"
27990
28308
  },
27991
28309
  {
27992
28310
  value: "default",
27993
28311
  label: "Default",
27994
- hint: "Classic design with sharper edges and more contrast"
28312
+ hint: "Classic design aesthetic - sharper edges, higher contrast, traditional look"
27995
28313
  }
27996
28314
  ]
27997
28315
  });
@@ -28007,32 +28325,32 @@ async function enhancedInitCommand(options = {}) {
28007
28325
  if (!shadcnBaseColor && uiLibrary === "shadcn") {
28008
28326
  if (!isNonInteractive) {
28009
28327
  shadcnBaseColor = await ve({
28010
- message: "\uD83C\uDFA8 shadcn/ui base color?",
28328
+ message: "\uD83C\uDFA8 shadcn/ui base color theme",
28011
28329
  options: [
28012
28330
  {
28013
28331
  value: "zinc",
28014
28332
  label: "Zinc (Recommended)",
28015
- hint: "Neutral gray - versatile and modern"
28333
+ hint: "Neutral gray palette - versatile, modern, works with any accent color"
28016
28334
  },
28017
28335
  {
28018
28336
  value: "neutral",
28019
28337
  label: "Neutral",
28020
- hint: "Pure neutral - no color cast"
28338
+ hint: "Pure neutral palette - no color cast, perfect grayscale"
28021
28339
  },
28022
28340
  {
28023
28341
  value: "gray",
28024
28342
  label: "Gray",
28025
- hint: "Warm gray - slightly warmer than zinc"
28343
+ hint: "Warm gray palette - slightly warmer tone than zinc"
28026
28344
  },
28027
28345
  {
28028
28346
  value: "slate",
28029
28347
  label: "Slate",
28030
- hint: "Cool gray - slightly bluer tone"
28348
+ hint: "Cool gray palette - slightly bluer tone, modern and crisp"
28031
28349
  },
28032
28350
  {
28033
28351
  value: "stone",
28034
28352
  label: "Stone",
28035
- hint: "Warm beige-gray - earthy and natural"
28353
+ hint: "Warm beige-gray palette - earthy, natural, organic feel"
28036
28354
  }
28037
28355
  ]
28038
28356
  });
@@ -28048,8 +28366,8 @@ async function enhancedInitCommand(options = {}) {
28048
28366
  if (!shadcnRadius && uiLibrary === "shadcn") {
28049
28367
  if (!isNonInteractive) {
28050
28368
  const radiusInput = await he({
28051
- message: "\uD83D\uDCD0 Border radius?",
28052
- placeholder: "0.625rem",
28369
+ message: "\uD83D\uDCD0 Component border radius",
28370
+ placeholder: "0.625rem (default)",
28053
28371
  initialValue: "0.625rem",
28054
28372
  validate: (value) => {
28055
28373
  if (!value.trim()) {
@@ -28073,22 +28391,22 @@ async function enhancedInitCommand(options = {}) {
28073
28391
  if (!testing) {
28074
28392
  if (!isNonInteractive) {
28075
28393
  testing = await ve({
28076
- message: "\uD83E\uDDEA Testing framework?",
28394
+ message: "\uD83E\uDDEA Testing framework",
28077
28395
  options: [
28078
28396
  {
28079
28397
  value: "bun-test",
28080
28398
  label: "Bun Test (Recommended)",
28081
- hint: "Built-in, fast, Jest-compatible - no extra dependencies"
28399
+ hint: "Built-in testing framework - fast, Jest-compatible, zero configuration"
28082
28400
  },
28083
28401
  {
28084
28402
  value: "vitest",
28085
28403
  label: "Vitest",
28086
- hint: "Vite-powered, fast, ESM-first - popular in ecosystem"
28404
+ hint: "Vite-powered testing framework - fast, ESM-first, popular ecosystem choice"
28087
28405
  },
28088
28406
  {
28089
28407
  value: "none",
28090
28408
  label: "None",
28091
- hint: "I'll add testing later"
28409
+ hint: "Skip testing setup - add testing framework later if needed"
28092
28410
  }
28093
28411
  ]
28094
28412
  });
@@ -28104,7 +28422,7 @@ async function enhancedInitCommand(options = {}) {
28104
28422
  if (docker === undefined) {
28105
28423
  if (!isNonInteractive) {
28106
28424
  docker = await ye({
28107
- message: "\uD83D\uDC33 Add Docker configuration?",
28425
+ message: "\uD83D\uDC33 Include Docker configuration",
28108
28426
  initialValue: false
28109
28427
  });
28110
28428
  if (pD(docker)) {
@@ -28119,7 +28437,7 @@ async function enhancedInitCommand(options = {}) {
28119
28437
  if (cicd === undefined) {
28120
28438
  if (!isNonInteractive) {
28121
28439
  cicd = await ye({
28122
- message: "\u2699\uFE0F Add GitHub Actions CI/CD?",
28440
+ message: "\u2699\uFE0F Include GitHub Actions CI/CD workflow",
28123
28441
  initialValue: false
28124
28442
  });
28125
28443
  if (pD(cicd)) {
@@ -28134,7 +28452,7 @@ async function enhancedInitCommand(options = {}) {
28134
28452
  if (shouldInstall === undefined) {
28135
28453
  if (!isNonInteractive) {
28136
28454
  shouldInstall = await ye({
28137
- message: "\uD83D\uDCE5 Install dependencies?",
28455
+ message: "\uD83D\uDCE5 Install dependencies after project creation",
28138
28456
  initialValue: true
28139
28457
  });
28140
28458
  if (pD(shouldInstall)) {
@@ -28149,7 +28467,7 @@ async function enhancedInitCommand(options = {}) {
28149
28467
  if (shouldInitGit === undefined) {
28150
28468
  if (!isNonInteractive) {
28151
28469
  shouldInitGit = await ye({
28152
- message: "\uD83D\uDD27 Initialize git repository?",
28470
+ message: "\uD83D\uDD27 Initialize Git repository",
28153
28471
  initialValue: true
28154
28472
  });
28155
28473
  if (pD(shouldInitGit)) {
@@ -28161,32 +28479,56 @@ async function enhancedInitCommand(options = {}) {
28161
28479
  }
28162
28480
  }
28163
28481
  if (!isNonInteractive) {
28164
- const summaryLines = [
28165
- `${source_default.bold("Project:")} ${source_default.cyan(projectName)}`,
28482
+ const configSummary = [
28483
+ "",
28484
+ `${source_default.bold.cyan("\uD83D\uDCE6 Project Configuration")}`,
28485
+ `${source_default.dim("\u2500".repeat(40))}`,
28486
+ `${source_default.bold("Project Name:")} ${source_default.cyan(projectName)}`,
28166
28487
  `${source_default.bold("Preset:")} ${source_default.cyan(preset)}`,
28167
- database ? `${source_default.bold("Database:")} ${source_default.cyan(database)}` : "",
28168
- `${source_default.bold("Code Quality:")} ${source_default.cyan(codeQuality)}`,
28169
- `${source_default.bold("TypeScript:")} ${source_default.cyan(tsStrictness)}`,
28170
- cssFramework ? `${source_default.bold("CSS:")} ${source_default.cyan(cssFramework)}` : "",
28171
- uiLibrary ? `${source_default.bold("UI Library:")} ${source_default.cyan(uiLibrary)}` : "",
28172
- uiLibrary === "shadcn" && shadcnStyle ? `${source_default.bold("shadcn Style:")} ${source_default.cyan(shadcnStyle)}` : "",
28173
- uiLibrary === "shadcn" && shadcnBaseColor ? `${source_default.bold("shadcn Base Color:")} ${source_default.cyan(shadcnBaseColor)}` : "",
28174
- uiLibrary === "shadcn" && shadcnRadius ? `${source_default.bold("shadcn Radius:")} ${source_default.cyan(shadcnRadius)}` : "",
28175
- `${source_default.bold("Testing:")} ${source_default.cyan(testing)}`,
28176
- docker ? `${source_default.bold("Docker:")} ${source_default.green("\u2713")}` : "",
28177
- cicd ? `${source_default.bold("CI/CD:")} ${source_default.green("\u2713")}` : ""
28178
- ].filter(Boolean);
28488
+ "",
28489
+ database && database !== "none" ? [
28490
+ `${source_default.bold.yellow("\uD83D\uDDC4\uFE0F Database")}`,
28491
+ ` ${source_default.bold("Type:")} ${source_default.cyan(database)}`,
28492
+ (database === "supabase" || database === "supabase-drizzle") && supabasePreset ? ` ${source_default.bold("Preset:")} ${source_default.cyan(supabasePreset)}` : "",
28493
+ (database === "supabase" || database === "supabase-drizzle") && supabaseFeatures ? ` ${source_default.bold("Features:")} ${source_default.cyan(supabaseFeatures.join(", "))}` : ""
28494
+ ].filter(Boolean).join(`
28495
+ `) : "",
28496
+ "",
28497
+ `${source_default.bold.yellow("\uD83D\uDEE0\uFE0F Development Tools")}`,
28498
+ ` ${source_default.bold("Code Quality:")} ${source_default.cyan(codeQuality)}`,
28499
+ ` ${source_default.bold("TypeScript:")} ${source_default.cyan(tsStrictness)}`,
28500
+ ` ${source_default.bold("Testing:")} ${source_default.cyan(testing)}`,
28501
+ "",
28502
+ cssFramework ? [
28503
+ `${source_default.bold.yellow("\uD83C\uDFA8 Styling")}`,
28504
+ ` ${source_default.bold("CSS Framework:")} ${source_default.cyan(cssFramework)}`,
28505
+ uiLibrary ? ` ${source_default.bold("UI Library:")} ${source_default.cyan(uiLibrary)}` : "",
28506
+ uiLibrary === "shadcn" && shadcnStyle ? ` ${source_default.bold(" Style:")} ${source_default.cyan(shadcnStyle)}` : "",
28507
+ uiLibrary === "shadcn" && shadcnBaseColor ? ` ${source_default.bold(" Base Color:")} ${source_default.cyan(shadcnBaseColor)}` : "",
28508
+ uiLibrary === "shadcn" && shadcnRadius ? ` ${source_default.bold(" Radius:")} ${source_default.cyan(shadcnRadius)}` : ""
28509
+ ].filter(Boolean).join(`
28510
+ `) : "",
28511
+ "",
28512
+ docker || cicd ? [
28513
+ `${source_default.bold.yellow("\uD83D\uDE80 Deployment")}`,
28514
+ docker ? ` ${source_default.bold("Docker:")} ${source_default.green("\u2713 Enabled")}` : "",
28515
+ cicd ? ` ${source_default.bold("CI/CD:")} ${source_default.green("\u2713 Enabled")}` : ""
28516
+ ].filter(Boolean).join(`
28517
+ `) : "",
28518
+ ""
28519
+ ].filter(Boolean).join(`
28520
+ `);
28179
28521
  console.log(`
28180
- ` + boxen(summaryLines.join(`
28181
- `), {
28182
- padding: 1,
28183
- title: "\uD83D\uDCCB Configuration",
28522
+ ` + boxen(configSummary, {
28523
+ padding: { top: 1, bottom: 1, left: 2, right: 2 },
28524
+ title: "\uD83D\uDCCB Configuration Summary",
28184
28525
  titleAlignment: "left",
28185
28526
  borderColor: "cyan",
28186
- borderStyle: "round"
28527
+ borderStyle: "round",
28528
+ dimBorder: false
28187
28529
  }));
28188
28530
  const confirm = await ye({
28189
- message: "Proceed with this configuration?",
28531
+ message: "Confirm project configuration",
28190
28532
  initialValue: true
28191
28533
  });
28192
28534
  if (pD(confirm) || !confirm) {
@@ -28194,8 +28536,9 @@ async function enhancedInitCommand(options = {}) {
28194
28536
  process.exit(0);
28195
28537
  }
28196
28538
  }
28539
+ console.log("");
28197
28540
  const s = Y2();
28198
- s.start("\uD83D\uDD28 Creating project structure...");
28541
+ s.start(`${source_default.cyan("\uD83D\uDD28")} Creating project structure...`);
28199
28542
  try {
28200
28543
  const config = {
28201
28544
  name: projectName,
@@ -28215,12 +28558,15 @@ async function enhancedInitCommand(options = {}) {
28215
28558
  pathAliases: true,
28216
28559
  shadcnStyle,
28217
28560
  shadcnBaseColor,
28218
- shadcnRadius
28561
+ shadcnRadius,
28562
+ supabasePreset,
28563
+ supabaseFeatures,
28564
+ supabaseWithDrizzle
28219
28565
  };
28220
28566
  await createProject(config);
28221
28567
  const projectPath = join(process.cwd(), config.path);
28222
28568
  const context = createTemplateContext(config);
28223
- s.message("\uD83D\uDCDD Generating files...");
28569
+ s.message(`${source_default.cyan("\uD83D\uDCDD")} Generating project files...`);
28224
28570
  switch (preset) {
28225
28571
  case "minimal":
28226
28572
  await buildMinimalPreset(projectPath, context);
@@ -28236,18 +28582,22 @@ async function enhancedInitCommand(options = {}) {
28236
28582
  break;
28237
28583
  }
28238
28584
  if (database && database !== "none") {
28239
- s.message(`\uD83D\uDDC4\uFE0F Setting up ${database}...`);
28585
+ const dbName = database === "postgres-drizzle" ? "PostgreSQL + Drizzle ORM" : database === "supabase" ? "Supabase (Client Only)" : database === "supabase-drizzle" ? "Supabase + Drizzle ORM" : database === "sqlite-drizzle" ? "SQLite + Drizzle ORM" : database;
28586
+ s.message(`${source_default.cyan("\uD83D\uDDC4\uFE0F")} Configuring ${dbName}...`);
28587
+ }
28588
+ if (uiLibrary === "shadcn") {
28589
+ s.message(`${source_default.cyan("\uD83C\uDFA8")} Setting up shadcn/ui components...`);
28240
28590
  }
28241
28591
  if (codeQuality === "ultracite") {
28242
- s.message("\uD83E\uDD16 Configuring Ultracite for AI editors...");
28592
+ s.message(`${source_default.cyan("\uD83E\uDD16")} Configuring Ultracite for AI editors...`);
28243
28593
  }
28244
28594
  if (docker) {
28245
- s.message("\uD83D\uDC33 Adding Docker configuration...");
28595
+ s.message(`${source_default.cyan("\uD83D\uDC33")} Adding Docker configuration...`);
28246
28596
  }
28247
28597
  if (cicd) {
28248
- s.message("\u2699\uFE0F Adding GitHub Actions...");
28598
+ s.message(`${source_default.cyan("\u2699\uFE0F")} Adding GitHub Actions CI/CD workflow...`);
28249
28599
  }
28250
- s.stop("\u2705 Project created!");
28600
+ s.stop(`${source_default.green("\u2705")} Project structure created successfully!`);
28251
28601
  if (shouldInstall && preset !== "full") {
28252
28602
  const additionalDeps = {};
28253
28603
  if (database && database !== "none") {
@@ -28274,7 +28624,8 @@ async function enhancedInitCommand(options = {}) {
28274
28624
  await installDependencies(projectPath);
28275
28625
  }
28276
28626
  if (shouldInstall && uiLibrary === "shadcn" && (preset === "web" || preset === "full")) {
28277
- s.message("\uD83E\uDDE9 Installing default shadcn/ui components...");
28627
+ const componentSpinner = Y2();
28628
+ componentSpinner.start(`${source_default.cyan("\uD83E\uDDE9")} Installing default shadcn/ui components (button, card)...`);
28278
28629
  try {
28279
28630
  if (preset === "full") {
28280
28631
  await installDefaultShadcnComponents(join(projectPath, "packages/ui"), {
@@ -28285,10 +28636,10 @@ async function enhancedInitCommand(options = {}) {
28285
28636
  silent: true
28286
28637
  });
28287
28638
  }
28288
- s.message("\u2705 Default components (button, card) installed");
28639
+ componentSpinner.stop(`${source_default.green("\u2705")} Default components installed`);
28289
28640
  } catch (error) {
28290
- s.message("\u26A0\uFE0F Could not install default components automatically");
28291
- s.message(" Install them manually: bunx shadcn@latest add button card");
28641
+ componentSpinner.stop(`${source_default.yellow("\u26A0\uFE0F")} Could not install automatically`);
28642
+ Me("Install manually: bunx shadcn@latest add button card", "Component Installation");
28292
28643
  }
28293
28644
  }
28294
28645
  const getDevCommand = () => {
@@ -28296,23 +28647,97 @@ async function enhancedInitCommand(options = {}) {
28296
28647
  return "bun dev";
28297
28648
  return "bun run dev";
28298
28649
  };
28299
- const nextSteps = [
28300
- `${source_default.cyan("cd")} ${projectName}`,
28301
- shouldInstall ? "" : `${source_default.cyan("bun install")}`,
28302
- `${source_default.cyan(getDevCommand())} ${source_default.dim("# Start development")}`
28650
+ const getPresetEmoji = () => {
28651
+ switch (preset) {
28652
+ case "minimal":
28653
+ return "\u26A1";
28654
+ case "web":
28655
+ return "\uD83C\uDF10";
28656
+ case "api":
28657
+ return "\uD83D\uDE80";
28658
+ case "full":
28659
+ return "\uD83D\uDCE6";
28660
+ default:
28661
+ return "\u2728";
28662
+ }
28663
+ };
28664
+ const nextStepsContent = [
28665
+ `${source_default.bold.cyan("\uD83D\uDCC1 Navigate to your project")}`,
28666
+ `${source_default.cyan("cd")} ${source_default.bold(projectName)}`,
28667
+ "",
28668
+ shouldInstall ? "" : [
28669
+ `${source_default.bold.cyan("\uD83D\uDCE6 Install dependencies")}`,
28670
+ `${source_default.cyan("bun install")}`,
28671
+ ""
28672
+ ].join(`
28673
+ `),
28674
+ `${source_default.bold.cyan("\uD83D\uDE80 Start development")}`,
28675
+ `${source_default.cyan(getDevCommand())} ${source_default.dim("# Start development server")}`,
28676
+ "",
28677
+ `${source_default.dim("\u2500".repeat(40))}`,
28678
+ `${source_default.bold.yellow("\uD83D\uDCA1 Quick Tips")}`,
28679
+ "",
28680
+ database && database !== "none" ? ` ${source_default.dim("\u2022")} Configure your database connection in ${source_default.cyan(".env")}` : "",
28681
+ uiLibrary === "shadcn" ? ` ${source_default.dim("\u2022")} Add more components: ${source_default.cyan("bunkit add component --all")}` : "",
28682
+ preset === "full" ? ` ${source_default.dim("\u2022")} Add workspaces: ${source_default.cyan("bunkit add workspace")}` : "",
28683
+ preset === "full" ? ` ${source_default.dim("\u2022")} Add packages: ${source_default.cyan("bunkit add package")}` : "",
28684
+ ` ${source_default.dim("\u2022")} Read the ${source_default.cyan("README.md")} for project-specific documentation`,
28685
+ database === "supabase" || database === "supabase-drizzle" ? ` ${source_default.dim("\u2022")} Check ${source_default.cyan("SHADCN.md")} for shadcn/ui usage guide` : ""
28303
28686
  ].filter(Boolean).join(`
28304
28687
  `);
28305
28688
  console.log(`
28306
- ` + boxen(nextSteps, {
28307
- padding: 1,
28308
- title: "\uD83D\uDE80 Next steps",
28689
+ ` + boxen(nextStepsContent, {
28690
+ padding: { top: 1, bottom: 1, left: 2, right: 2 },
28691
+ title: `${getPresetEmoji()} Next Steps`,
28309
28692
  titleAlignment: "left",
28310
28693
  borderColor: "green",
28311
- borderStyle: "round"
28694
+ borderStyle: "round",
28695
+ dimBorder: false
28696
+ }));
28697
+ const projectSummary = [
28698
+ `${source_default.bold.green("\u2728 Project created successfully!")}`,
28699
+ "",
28700
+ `${source_default.dim("Project location:")} ${source_default.cyan(join(process.cwd(), projectName))}`,
28701
+ `${source_default.dim("Preset:")} ${source_default.cyan(preset)}`,
28702
+ database && database !== "none" ? `${source_default.dim("Database:")} ${source_default.cyan(database)}` : "",
28703
+ uiLibrary ? `${source_default.dim("UI Library:")} ${source_default.cyan(uiLibrary)}` : "",
28704
+ "",
28705
+ `${source_default.dim("Happy coding! \uD83C\uDF89")}`
28706
+ ].filter(Boolean).join(`
28707
+ `);
28708
+ console.log(`
28709
+ ` + boxen(projectSummary, {
28710
+ padding: { top: 1, bottom: 1, left: 2, right: 2 },
28711
+ borderColor: "green",
28712
+ borderStyle: "round",
28713
+ dimBorder: true
28312
28714
  }));
28313
28715
  } catch (error) {
28314
- s.stop("\u274C Failed to create project");
28315
- xe(`${import_picocolors4.default.red("Error:")} ${error.message}`);
28716
+ s.stop(`${source_default.red("\u274C")} Failed to create project`);
28717
+ const errorMessage = error.message;
28718
+ const errorBox = [
28719
+ `${source_default.bold.red("Error occurred during project creation")}`,
28720
+ "",
28721
+ source_default.red(errorMessage),
28722
+ "",
28723
+ `${source_default.dim("\u2500".repeat(40))}`,
28724
+ `${source_default.bold.yellow("\uD83D\uDCA1 Troubleshooting Tips")}`,
28725
+ "",
28726
+ ` ${source_default.dim("\u2022")} Check if the directory already exists`,
28727
+ ` ${source_default.dim("\u2022")} Ensure you have write permissions`,
28728
+ ` ${source_default.dim("\u2022")} Verify your internet connection (for dependency installation)`,
28729
+ ` ${source_default.dim("\u2022")} Try running with ${source_default.cyan("--no-install")} to skip dependency installation`,
28730
+ "",
28731
+ `${source_default.dim("Need help?")} ${source_default.cyan("https://github.com/Arakiss/bunkit/issues")}`
28732
+ ].join(`
28733
+ `);
28734
+ console.log(`
28735
+ ` + boxen(errorBox, {
28736
+ padding: { top: 1, bottom: 1, left: 2, right: 2 },
28737
+ borderColor: "red",
28738
+ borderStyle: "round"
28739
+ }));
28740
+ xe("Operation cancelled due to error");
28316
28741
  process.exit(1);
28317
28742
  }
28318
28743
  }
@@ -28331,8 +28756,9 @@ async function createCommand2(preset, name, options) {
28331
28756
  if (!validation2.valid) {
28332
28757
  throw new Error(`Invalid project name: ${validation2.error}`);
28333
28758
  }
28759
+ console.log("");
28334
28760
  const s = Y2();
28335
- s.start(`Creating ${preset} project: ${name}`);
28761
+ s.start(`${source_default.cyan("\uD83D\uDD28")} Creating ${preset} project: ${source_default.bold(name)}`);
28336
28762
  try {
28337
28763
  const config = {
28338
28764
  name,
@@ -28349,11 +28775,11 @@ async function createCommand2(preset, name, options) {
28349
28775
  envExample: true,
28350
28776
  pathAliases: true
28351
28777
  };
28352
- s.message("\uD83D\uDD28 Creating project structure...");
28778
+ s.message(`${source_default.cyan("\uD83D\uDCC1")} Creating project structure...`);
28353
28779
  await createProject(config);
28354
28780
  const projectPath = join(process.cwd(), config.path);
28355
28781
  const context = createTemplateContext(config);
28356
- s.message("\uD83D\uDCDD Generating files...");
28782
+ s.message(`${source_default.cyan("\uD83D\uDCDD")} Generating project files...`);
28357
28783
  switch (preset) {
28358
28784
  case "minimal":
28359
28785
  await buildMinimalPreset(projectPath, context);
@@ -28368,22 +28794,65 @@ async function createCommand2(preset, name, options) {
28368
28794
  await buildFullPreset(projectPath, context);
28369
28795
  break;
28370
28796
  }
28371
- s.stop(`Project ${name} created!`);
28372
- const nextSteps = [
28373
- `${source_default.cyan("cd")} ${name}`,
28374
- source_default.cyan(preset === "web" ? "bun dev" : "bun run dev")
28375
- ].join(`
28797
+ s.message(`${source_default.cyan("\u2728")} Finalizing setup...`);
28798
+ s.stop(`${source_default.green("\u2705")} Project ${source_default.bold(name)} created successfully!`);
28799
+ const getPresetEmoji = () => {
28800
+ switch (preset) {
28801
+ case "minimal":
28802
+ return "\u26A1";
28803
+ case "web":
28804
+ return "\uD83C\uDF10";
28805
+ case "api":
28806
+ return "\uD83D\uDE80";
28807
+ case "full":
28808
+ return "\uD83D\uDCE6";
28809
+ default:
28810
+ return "\u2728";
28811
+ }
28812
+ };
28813
+ const nextStepsContent = [
28814
+ `${source_default.bold.cyan("\uD83D\uDCC1 Navigate to your project")}`,
28815
+ `${source_default.cyan("cd")} ${source_default.bold(name)}`,
28816
+ "",
28817
+ options.install === false ? [
28818
+ `${source_default.bold.cyan("\uD83D\uDCE6 Install dependencies")}`,
28819
+ `${source_default.cyan("bun install")}`,
28820
+ ""
28821
+ ].join(`
28822
+ `) : "",
28823
+ `${source_default.bold.cyan("\uD83D\uDE80 Start development")}`,
28824
+ `${source_default.cyan(preset === "web" ? "bun dev" : "bun run dev")} ${source_default.dim("# Start development server")}`,
28825
+ "",
28826
+ `${source_default.dim("\u2500".repeat(40))}`,
28827
+ `${source_default.bold.yellow("\uD83D\uDCA1 Tip")}`,
28828
+ ` Use ${source_default.cyan("bunkit init")} for full customization options`
28829
+ ].filter(Boolean).join(`
28376
28830
  `);
28377
28831
  console.log(`
28378
- ` + boxen(nextSteps, {
28379
- padding: 1,
28380
- title: "\uD83D\uDCCB Next steps",
28832
+ ` + boxen(nextStepsContent, {
28833
+ padding: { top: 1, bottom: 1, left: 2, right: 2 },
28834
+ title: `${getPresetEmoji()} Next Steps`,
28381
28835
  titleAlignment: "left",
28382
- borderColor: "cyan",
28383
- borderStyle: "round"
28836
+ borderColor: "green",
28837
+ borderStyle: "round",
28838
+ dimBorder: false
28384
28839
  }));
28385
28840
  } catch (error) {
28386
- s.stop("\u274C Project creation failed");
28841
+ s.stop(`${source_default.red("\u274C")} Project creation failed`);
28842
+ const errorBox = [
28843
+ `${source_default.bold.red("Error occurred")}`,
28844
+ "",
28845
+ source_default.red(error.message),
28846
+ "",
28847
+ `${source_default.dim("Need help?")} ${source_default.cyan("https://github.com/Arakiss/bunkit/issues")}`
28848
+ ].join(`
28849
+ `);
28850
+ console.log(`
28851
+ ` + boxen(errorBox, {
28852
+ padding: { top: 1, bottom: 1, left: 2, right: 2 },
28853
+ borderColor: "red",
28854
+ borderStyle: "round"
28855
+ }));
28387
28856
  throw error;
28388
28857
  }
28389
28858
  }
@@ -28391,7 +28860,7 @@ async function createCommand2(preset, name, options) {
28391
28860
  // src/commands/add/workspace.ts
28392
28861
  init_dist();
28393
28862
  init_src();
28394
- var import_picocolors5 = __toESM(require_picocolors(), 1);
28863
+ var import_picocolors4 = __toESM(require_picocolors(), 1);
28395
28864
  function getWorkspaceDependencies(preset) {
28396
28865
  switch (preset) {
28397
28866
  case "nextjs":
@@ -28474,8 +28943,8 @@ async function addWorkspaceCommand(options = {}) {
28474
28943
  let workspaceName = options.name;
28475
28944
  if (!workspaceName) {
28476
28945
  const nameInput = await he({
28477
- message: "Workspace name (e.g., apps/admin or packages/email):",
28478
- placeholder: "apps/dashboard",
28946
+ message: "Workspace name",
28947
+ placeholder: "apps/admin or packages/email",
28479
28948
  validate: (value) => {
28480
28949
  if (!value)
28481
28950
  return "Workspace name is required";
@@ -28503,15 +28972,15 @@ async function addWorkspaceCommand(options = {}) {
28503
28972
  let preset = options.preset;
28504
28973
  if (!preset) {
28505
28974
  const presetChoice = await ve({
28506
- message: "Choose workspace preset:",
28975
+ message: "Select workspace preset",
28507
28976
  options: [
28508
28977
  {
28509
28978
  value: "nextjs",
28510
- label: "Next.js",
28511
- hint: "Next.js 16 + React 19 + Tailwind"
28979
+ label: "Next.js Application",
28980
+ hint: "Next.js 16 + React 19 + Tailwind CSS 4 - production-ready web app"
28512
28981
  },
28513
- { value: "hono", label: "Hono API", hint: "Fast API with Bun.serve()" },
28514
- { value: "library", label: "Library", hint: "Shared package" }
28982
+ { value: "hono", label: "Hono API Server", hint: "Hono 4 + Bun.serve() - ultra-fast REST API" },
28983
+ { value: "library", label: "Shared Library", hint: "Reusable package for shared code and components" }
28515
28984
  ]
28516
28985
  });
28517
28986
  if (pD(presetChoice)) {
@@ -28549,18 +29018,18 @@ async function addWorkspaceCommand(options = {}) {
28549
29018
  spinner.stop("Dependencies installed");
28550
29019
  M2.success(`Workspace "${workspaceName}" created successfully!`);
28551
29020
  const devCommand = preset === "nextjs" ? "next dev" : preset === "hono" ? "bun dev" : "bun run build";
28552
- Me(`${import_picocolors5.default.bold("Next steps:")}
29021
+ Me(`${import_picocolors4.default.bold("Next steps:")}
28553
29022
 
28554
- ${import_picocolors5.default.cyan(`cd ${workspaceName}`)}
28555
- ${import_picocolors5.default.cyan(devCommand)}
29023
+ ${import_picocolors4.default.cyan(`cd ${workspaceName}`)}
29024
+ ${import_picocolors4.default.cyan(devCommand)}
28556
29025
 
28557
- ${import_picocolors5.default.bold("Workspace info:")}
29026
+ ${import_picocolors4.default.bold("Workspace info:")}
28558
29027
  Name: ${getWorkspaceName(workspaceName)}
28559
29028
  Type: ${preset}
28560
29029
  Path: ${workspaceName}
28561
29030
 
28562
- ${preset === "library" ? `${import_picocolors5.default.bold("Usage in other workspaces:")}
28563
- import { example } from '${getWorkspaceName(workspaceName)}'` : ""}`, import_picocolors5.default.green("Workspace ready!"));
29031
+ ${preset === "library" ? `${import_picocolors4.default.bold("Usage in other workspaces:")}
29032
+ import { example } from '${getWorkspaceName(workspaceName)}'` : ""}`, import_picocolors4.default.green("Workspace ready!"));
28564
29033
  } catch (error) {
28565
29034
  spinner.stop("Failed");
28566
29035
  throw error;
@@ -28570,7 +29039,7 @@ ${preset === "library" ? `${import_picocolors5.default.bold("Usage in other work
28570
29039
  // src/commands/add/package.ts
28571
29040
  init_dist();
28572
29041
  init_src();
28573
- var import_picocolors6 = __toESM(require_picocolors(), 1);
29042
+ var import_picocolors5 = __toESM(require_picocolors(), 1);
28574
29043
  async function generatePackageFiles(packagePath, packageName, type) {
28575
29044
  const { writeFile: writeFile2 } = await Promise.resolve().then(() => (init_src(), exports_src));
28576
29045
  await ensureDirectory(join(packagePath, "src"));
@@ -28695,8 +29164,8 @@ async function addPackageCommand(options = {}) {
28695
29164
  let packageName = options.name;
28696
29165
  if (!packageName) {
28697
29166
  const nameInput = await he({
28698
- message: "Package name (e.g., @myapp/email or utils):",
28699
- placeholder: "@myapp/email",
29167
+ message: "Package name",
29168
+ placeholder: "@myapp/email or utils",
28700
29169
  validate: (value) => {
28701
29170
  if (!value)
28702
29171
  return "Package name is required";
@@ -28733,12 +29202,12 @@ async function addPackageCommand(options = {}) {
28733
29202
  let type = options.type;
28734
29203
  if (!type) {
28735
29204
  const typeChoice = await ve({
28736
- message: "Choose package type:",
29205
+ message: "Select package type",
28737
29206
  options: [
28738
- { value: "library", label: "Library", hint: "Shared code/components" },
28739
- { value: "utils", label: "Utils", hint: "Utility functions" },
28740
- { value: "types", label: "Types", hint: "TypeScript types" },
28741
- { value: "config", label: "Config", hint: "Configuration" }
29207
+ { value: "library", label: "Library", hint: "Shared code and components - reusable across workspaces" },
29208
+ { value: "utils", label: "Utilities", hint: "Utility functions and helpers - common operations" },
29209
+ { value: "types", label: "Type Definitions", hint: "Shared TypeScript types and interfaces" },
29210
+ { value: "config", label: "Configuration", hint: "Shared configuration files and settings" }
28742
29211
  ]
28743
29212
  });
28744
29213
  if (pD(typeChoice)) {
@@ -28783,25 +29252,25 @@ async function addPackageCommand(options = {}) {
28783
29252
  await installDependencies(cwd2, {});
28784
29253
  spinner.stop("Dependencies installed");
28785
29254
  M2.success(`Package "${fullPackageName}" created successfully!`);
28786
- Me(`${import_picocolors6.default.bold("Next steps:")}
29255
+ Me(`${import_picocolors5.default.bold("Next steps:")}
28787
29256
 
28788
- ${import_picocolors6.default.bold("1. Use in other workspaces:")}
28789
- ${import_picocolors6.default.cyan(`import { example } from '${fullPackageName}'`)}
29257
+ ${import_picocolors5.default.bold("1. Use in other workspaces:")}
29258
+ ${import_picocolors5.default.cyan(`import { example } from '${fullPackageName}'`)}
28790
29259
 
28791
- ${import_picocolors6.default.bold("2. Add to workspace dependencies:")}
28792
- ${import_picocolors6.default.dim("// In apps/web/package.json")}
28793
- ${import_picocolors6.default.cyan('"dependencies": {')}
28794
- ${import_picocolors6.default.cyan(` "${fullPackageName}": "workspace:*"`)}
28795
- ${import_picocolors6.default.cyan("}")}
29260
+ ${import_picocolors5.default.bold("2. Add to workspace dependencies:")}
29261
+ ${import_picocolors5.default.dim("// In apps/web/package.json")}
29262
+ ${import_picocolors5.default.cyan('"dependencies": {')}
29263
+ ${import_picocolors5.default.cyan(` "${fullPackageName}": "workspace:*"`)}
29264
+ ${import_picocolors5.default.cyan("}")}
28796
29265
 
28797
- ${import_picocolors6.default.bold("3. Develop the package:")}
28798
- ${import_picocolors6.default.cyan(`cd ${workspacePath}`)}
28799
- ${import_picocolors6.default.cyan("# Edit src/index.ts")}
29266
+ ${import_picocolors5.default.bold("3. Develop the package:")}
29267
+ ${import_picocolors5.default.cyan(`cd ${workspacePath}`)}
29268
+ ${import_picocolors5.default.cyan("# Edit src/index.ts")}
28800
29269
 
28801
- ${import_picocolors6.default.bold("Package info:")}
29270
+ ${import_picocolors5.default.bold("Package info:")}
28802
29271
  Name: ${fullPackageName}
28803
29272
  Type: ${type}
28804
- Path: ${workspacePath}`, import_picocolors6.default.green("Package ready!"));
29273
+ Path: ${workspacePath}`, import_picocolors5.default.green("Package ready!"));
28805
29274
  } catch (error) {
28806
29275
  spinner.stop("Failed");
28807
29276
  throw error;
@@ -28869,7 +29338,7 @@ async function addComponentCommand(options = {}) {
28869
29338
  "tooltip"
28870
29339
  ];
28871
29340
  const selected = await fe({
28872
- message: "Select components to install:",
29341
+ message: "Select shadcn/ui components to install",
28873
29342
  options: popularComponents.map((comp) => ({
28874
29343
  value: comp,
28875
29344
  label: comp
@@ -28885,8 +29354,8 @@ async function addComponentCommand(options = {}) {
28885
29354
  components = options.components;
28886
29355
  } else {
28887
29356
  const componentInput = await he({
28888
- message: "Component name(s) to install?",
28889
- placeholder: "button, card, input",
29357
+ message: "Component name(s)",
29358
+ placeholder: "button,card,input (comma-separated)",
28890
29359
  validate: (value) => {
28891
29360
  if (!value.trim()) {
28892
29361
  return "Please enter at least one component name";
@@ -28964,30 +29433,68 @@ async function addCommand(feature, options) {
28964
29433
  var packageJson = await Bun.file(new URL("../package.json", import.meta.url)).json();
28965
29434
  var VERSION = packageJson.version;
28966
29435
  var program2 = new Command;
28967
- program2.name("bunkit").description("Bake production-ready apps in seconds").version(VERSION);
28968
- program2.command("init").description("Create a new project with full customization").option("--name <name>", "Project name").option("--preset <preset>", "Preset type (minimal, web, api, full)").option("--database <database>", "Database (postgres-drizzle, supabase, sqlite-drizzle, none)").option("--code-quality <quality>", "Code quality (ultracite, biome)").option("--ts-strictness <strictness>", "TypeScript strictness (strict, moderate, loose)").option("--ui-library <library>", "UI library (shadcn, none)").option("--css-framework <framework>", "CSS framework (tailwind, vanilla, css-modules)").option("--shadcn-style <style>", "shadcn/ui style (new-york, default)").option("--shadcn-base-color <color>", "shadcn/ui base color (neutral, gray, zinc, stone, slate)").option("--shadcn-radius <radius>", "shadcn/ui border radius (e.g., 0.5rem, 8px)").option("--testing <framework>", "Testing framework (bun-test, vitest, none)").option("--docker", "Add Docker configuration").option("--cicd", "Add GitHub Actions CI/CD").option("--no-git", "Skip git initialization").option("--no-install", "Skip dependency installation").option("--non-interactive", "Run without prompts (requires all options)").action(async (options) => {
29436
+ program2.name("bunkit").description("Bake production-ready apps in seconds | Modern CLI for Bun-powered projects").version(VERSION).usage("<command> [options]").addHelpText("after", `
29437
+ Examples:
29438
+ $ bunkit init Create a new project interactively
29439
+ $ bunkit create web my-app Create a Next.js web application
29440
+ $ bunkit add workspace Add a new workspace to monorepo
29441
+ $ bunkit add component --all Browse and add shadcn/ui components
29442
+
29443
+ For more information, visit: https://github.com/Arakiss/bunkit
29444
+ `);
29445
+ program2.command("init").description("Create a new project with full customization options").alias("i").option("--name <name>", "Project name (kebab-case recommended, e.g., my-awesome-app)").option("--preset <preset>", "Project preset: minimal | web | api | full").option("--database <database>", "Database option: postgres-drizzle | supabase | supabase-drizzle | sqlite-drizzle | none").option("--supabase-preset <preset>", "Supabase configuration preset: full-stack | auth-only | database-only | custom").option("--supabase-features <features>", "Comma-separated Supabase features: auth,storage,realtime,edge-functions,database").option("--code-quality <tool>", "Code quality tool: ultracite | biome").option("--ts-strictness <level>", "TypeScript strictness level: strict | moderate | loose").option("--ui-library <library>", "UI component library: shadcn | none").option("--css-framework <framework>", "CSS framework: tailwind | vanilla | css-modules").option("--shadcn-style <style>", "shadcn/ui component style: new-york | default").option("--shadcn-base-color <color>", "shadcn/ui base color theme: neutral | gray | zinc | stone | slate").option("--shadcn-radius <radius>", "shadcn/ui border radius (CSS value, e.g., 0.5rem, 8px)").option("--testing <framework>", "Testing framework: bun-test | vitest | none").option("--docker", "Include Docker configuration files").option("--cicd", "Include GitHub Actions CI/CD workflow").option("--no-git", "Skip Git repository initialization").option("--no-install", "Skip dependency installation after project creation").option("--non-interactive", "Run in non-interactive mode (requires all options via flags)").addHelpText("after", `
29446
+ Examples:
29447
+ $ bunkit init Interactive project creation
29448
+ $ bunkit init --name my-app --preset web Quick web app creation
29449
+ $ bunkit init --preset full --database supabase Full-stack with Supabase
29450
+
29451
+ Presets:
29452
+ minimal Single-file project, clean start
29453
+ web Next.js 16 + React 19 web application
29454
+ api Hono API server with Bun.serve()
29455
+ full Full-stack monorepo (web + api + packages)
29456
+ `).action(async (options) => {
28969
29457
  showBanner(VERSION);
28970
29458
  try {
28971
29459
  await enhancedInitCommand(options);
28972
- Se(import_picocolors7.default.green("\u2728 Done! Your project is ready to bake! \uD83C\uDF5E"));
29460
+ Se(import_picocolors6.default.green("\u2728 Done! Your project is ready to bake! \uD83C\uDF5E"));
28973
29461
  } catch (error) {
28974
29462
  M2.error(error.message);
28975
- Se(import_picocolors7.default.red("\u274C Project creation failed"));
29463
+ Se(import_picocolors6.default.red("\u274C Project creation failed"));
28976
29464
  process.exit(1);
28977
29465
  }
28978
29466
  });
28979
- program2.command("create").argument("<preset>", "Preset type (minimal, web, api, full)").argument("<name>", "Project name").option("--no-git", "Skip git initialization").option("--no-install", "Skip dependency installation").description("Create a new project quickly").action(async (preset, name, options) => {
29467
+ program2.command("create").alias("c").argument("<preset>", "Project preset: minimal | web | api | full").argument("<name>", "Project name (kebab-case recommended)").option("--no-git", "Skip Git repository initialization").option("--no-install", "Skip dependency installation after project creation").description("Quick project creation with sensible defaults (non-interactive)").addHelpText("after", `
29468
+ Examples:
29469
+ $ bunkit create web my-app Create Next.js web application
29470
+ $ bunkit create api my-api Create Hono API server
29471
+ $ bunkit create full my-saas Create full-stack monorepo
29472
+ $ bunkit create minimal my-tool Create minimal Bun project
29473
+
29474
+ Note: This command uses sensible defaults. Use 'bunkit init' for full customization.
29475
+ `).action(async (preset, name, options) => {
28980
29476
  showBanner(VERSION);
28981
29477
  try {
28982
29478
  await createCommand2(preset, name, options);
28983
- Se(import_picocolors7.default.green("\u2728 Done! Your project is ready to bake! \uD83C\uDF5E"));
29479
+ Se(import_picocolors6.default.green("\u2728 Done! Your project is ready to bake! \uD83C\uDF5E"));
28984
29480
  } catch (error) {
28985
29481
  M2.error(error.message);
28986
- Se(import_picocolors7.default.red("\u274C Project creation failed"));
29482
+ Se(import_picocolors6.default.red("\u274C Project creation failed"));
28987
29483
  process.exit(1);
28988
29484
  }
28989
29485
  });
28990
- program2.command("add").argument("<feature>", "Feature to add (workspace, package, component)").option("--name <name>", "Name for the feature").option("--preset <preset>", "Preset for workspace (nextjs, hono, library)").option("--type <type>", "Type for package (library, utils, types, config)").option("--components <components>", "Component names (comma-separated) for component feature").option("--all", "Show all available components (for component feature)").description("Add workspace, package, or shadcn/ui component to project").action(async (feature, options) => {
29486
+ program2.command("add").alias("a").argument("<feature>", "Feature type: workspace | package | component").option("--name <name>", "Feature name (e.g., apps/admin, @myapp/utils, button)").option("--preset <preset>", "Workspace preset: nextjs | hono | library").option("--type <type>", "Package type: library | utils | types | config").option("--components <components>", "Comma-separated component names (e.g., button,card,input)").option("--all", "Show interactive component browser (for component feature)").description("Add workspace, shared package, or shadcn/ui component to existing project").addHelpText("after", `
29487
+ Examples:
29488
+ $ bunkit add workspace --name apps/admin --preset nextjs
29489
+ $ bunkit add package --name @myapp/utils --type utils
29490
+ $ bunkit add component --components button,card,input
29491
+ $ bunkit add component --all
29492
+
29493
+ Features:
29494
+ workspace Add a new workspace to monorepo (app or package)
29495
+ package Add a shared package to monorepo
29496
+ component Add shadcn/ui components (requires shadcn/ui setup)
29497
+ `).action(async (feature, options) => {
28991
29498
  showBanner(VERSION);
28992
29499
  try {
28993
29500
  const parsedOptions = {
@@ -28995,10 +29502,9 @@ program2.command("add").argument("<feature>", "Feature to add (workspace, packag
28995
29502
  components: options.components && typeof options.components === "string" ? options.components.split(",").map((c3) => c3.trim()) : options.components
28996
29503
  };
28997
29504
  await addCommand(feature, parsedOptions);
28998
- Se(import_picocolors7.default.green("\u2728 Feature added successfully! \uD83C\uDF5E"));
28999
29505
  } catch (error) {
29000
29506
  M2.error(error.message);
29001
- Se(import_picocolors7.default.red("\u274C Feature installation failed"));
29507
+ Se(import_picocolors6.default.red("\u274C Feature installation failed"));
29002
29508
  process.exit(1);
29003
29509
  }
29004
29510
  });