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.
- package/README.md +61 -3
- package/dist/index.js +684 -178
- 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.
|
|
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(`
|
|
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: "
|
|
3789
|
+
borderColor: "cyan",
|
|
3790
3790
|
borderStyle: "round",
|
|
3791
|
-
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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
|
|
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
|
|
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
|
|
28019
|
+
message: "\uD83C\uDFA8 Select project preset",
|
|
27802
28020
|
options: [
|
|
27803
28021
|
{
|
|
27804
28022
|
value: "minimal",
|
|
27805
28023
|
label: "\u26A1 Minimal",
|
|
27806
|
-
hint: "Single
|
|
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
|
|
27811
|
-
hint: "Next.js 16 + React 19 -
|
|
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 +
|
|
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
|
|
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
|
|
28057
|
+
hint: "Production-ready PostgreSQL with type-safe Drizzle ORM queries"
|
|
27840
28058
|
},
|
|
27841
28059
|
{
|
|
27842
28060
|
value: "supabase",
|
|
27843
|
-
label: "Supabase",
|
|
27844
|
-
hint: "
|
|
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
|
|
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: "
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
28281
|
+
hint: "64+ accessible components, fully customizable, production-ready"
|
|
27964
28282
|
},
|
|
27965
28283
|
{
|
|
27966
28284
|
value: "none",
|
|
27967
28285
|
label: "None",
|
|
27968
|
-
hint: "
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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: "
|
|
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
|
|
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
|
|
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
|
|
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
|
|
28165
|
-
|
|
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
|
-
|
|
28168
|
-
|
|
28169
|
-
|
|
28170
|
-
|
|
28171
|
-
|
|
28172
|
-
|
|
28173
|
-
|
|
28174
|
-
|
|
28175
|
-
|
|
28176
|
-
|
|
28177
|
-
|
|
28178
|
-
|
|
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(
|
|
28181
|
-
|
|
28182
|
-
|
|
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: "
|
|
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
|
-
|
|
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
|
|
28592
|
+
s.message(`${source_default.cyan("\uD83E\uDD16")} Configuring Ultracite for AI editors...`);
|
|
28243
28593
|
}
|
|
28244
28594
|
if (docker) {
|
|
28245
|
-
s.message("\uD83D\uDC33
|
|
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
|
-
|
|
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
|
-
|
|
28639
|
+
componentSpinner.stop(`${source_default.green("\u2705")} Default components installed`);
|
|
28289
28640
|
} catch (error) {
|
|
28290
|
-
|
|
28291
|
-
|
|
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
|
|
28300
|
-
|
|
28301
|
-
|
|
28302
|
-
|
|
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(
|
|
28307
|
-
padding: 1,
|
|
28308
|
-
title:
|
|
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
|
-
|
|
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(
|
|
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\
|
|
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.
|
|
28372
|
-
|
|
28373
|
-
|
|
28374
|
-
|
|
28375
|
-
|
|
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(
|
|
28379
|
-
padding: 1,
|
|
28380
|
-
title:
|
|
28832
|
+
` + boxen(nextStepsContent, {
|
|
28833
|
+
padding: { top: 1, bottom: 1, left: 2, right: 2 },
|
|
28834
|
+
title: `${getPresetEmoji()} Next Steps`,
|
|
28381
28835
|
titleAlignment: "left",
|
|
28382
|
-
borderColor: "
|
|
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
|
|
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
|
|
28478
|
-
placeholder: "apps/
|
|
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: "
|
|
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: "
|
|
28514
|
-
{ value: "library", label: "Library", hint: "
|
|
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(`${
|
|
29021
|
+
Me(`${import_picocolors4.default.bold("Next steps:")}
|
|
28553
29022
|
|
|
28554
|
-
${
|
|
28555
|
-
${
|
|
29023
|
+
${import_picocolors4.default.cyan(`cd ${workspaceName}`)}
|
|
29024
|
+
${import_picocolors4.default.cyan(devCommand)}
|
|
28556
29025
|
|
|
28557
|
-
${
|
|
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" ? `${
|
|
28563
|
-
import { example } from '${getWorkspaceName(workspaceName)}'` : ""}`,
|
|
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
|
|
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
|
|
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: "
|
|
29205
|
+
message: "Select package type",
|
|
28737
29206
|
options: [
|
|
28738
|
-
{ value: "library", label: "Library", hint: "Shared code
|
|
28739
|
-
{ value: "utils", label: "
|
|
28740
|
-
{ value: "types", label: "
|
|
28741
|
-
{ value: "config", label: "
|
|
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(`${
|
|
29255
|
+
Me(`${import_picocolors5.default.bold("Next steps:")}
|
|
28787
29256
|
|
|
28788
|
-
${
|
|
28789
|
-
${
|
|
29257
|
+
${import_picocolors5.default.bold("1. Use in other workspaces:")}
|
|
29258
|
+
${import_picocolors5.default.cyan(`import { example } from '${fullPackageName}'`)}
|
|
28790
29259
|
|
|
28791
|
-
${
|
|
28792
|
-
${
|
|
28793
|
-
${
|
|
28794
|
-
${
|
|
28795
|
-
${
|
|
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
|
-
${
|
|
28798
|
-
${
|
|
28799
|
-
${
|
|
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
|
-
${
|
|
29270
|
+
${import_picocolors5.default.bold("Package info:")}
|
|
28802
29271
|
Name: ${fullPackageName}
|
|
28803
29272
|
Type: ${type}
|
|
28804
|
-
Path: ${workspacePath}`,
|
|
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)
|
|
28889
|
-
placeholder: "button,
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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>", "
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
29507
|
+
Se(import_picocolors6.default.red("\u274C Feature installation failed"));
|
|
29002
29508
|
process.exit(1);
|
|
29003
29509
|
}
|
|
29004
29510
|
});
|