bunkit-cli 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +335 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -24438,7 +24438,8 @@ coverage = true
|
|
|
24438
24438
|
"@types/react": "^19.1.0",
|
|
24439
24439
|
"@types/react-dom": "^19.1.0",
|
|
24440
24440
|
"@types/node": "^22.10.6",
|
|
24441
|
-
typescript: "^5.7.2"
|
|
24441
|
+
typescript: "^5.7.2",
|
|
24442
|
+
tailwindcss: "^4.1.5"
|
|
24442
24443
|
}
|
|
24443
24444
|
};
|
|
24444
24445
|
await writeFile(join(projectPath, "apps/web/package.json"), JSON.stringify(webPackageJson, null, 2));
|
|
@@ -24461,7 +24462,8 @@ coverage = true
|
|
|
24461
24462
|
"@types/react": "^19.1.0",
|
|
24462
24463
|
"@types/react-dom": "^19.1.0",
|
|
24463
24464
|
"@types/node": "^22.10.6",
|
|
24464
|
-
typescript: "^5.7.2"
|
|
24465
|
+
typescript: "^5.7.2",
|
|
24466
|
+
tailwindcss: "^4.1.5"
|
|
24465
24467
|
}
|
|
24466
24468
|
};
|
|
24467
24469
|
await writeFile(join(projectPath, "apps/platform/package.json"), JSON.stringify(platformPackageJson, null, 2));
|
|
@@ -24471,7 +24473,8 @@ coverage = true
|
|
|
24471
24473
|
private: true,
|
|
24472
24474
|
scripts: {
|
|
24473
24475
|
dev: "bun run --hot src/index.ts",
|
|
24474
|
-
start: "bun run src/index.ts"
|
|
24476
|
+
start: "bun run src/index.ts",
|
|
24477
|
+
typecheck: "tsc --noEmit"
|
|
24475
24478
|
},
|
|
24476
24479
|
dependencies: {
|
|
24477
24480
|
hono: "catalog:",
|
|
@@ -24507,6 +24510,335 @@ export interface ApiResponse<T = unknown> {
|
|
|
24507
24510
|
}
|
|
24508
24511
|
`;
|
|
24509
24512
|
await writeFile(join(projectPath, "packages/types/src/index.ts"), typesContent);
|
|
24513
|
+
const utilsPackageJson = {
|
|
24514
|
+
name: `@${context.packageName}/utils`,
|
|
24515
|
+
version: "0.0.0",
|
|
24516
|
+
private: true,
|
|
24517
|
+
main: "./src/index.ts",
|
|
24518
|
+
types: "./src/index.ts"
|
|
24519
|
+
};
|
|
24520
|
+
await writeFile(join(projectPath, "packages/utils/package.json"), JSON.stringify(utilsPackageJson, null, 2));
|
|
24521
|
+
const utilsContent = `// Shared utilities for ${context.projectName}
|
|
24522
|
+
|
|
24523
|
+
export function formatDate(date: Date): string {
|
|
24524
|
+
return new Intl.DateTimeFormat('en-US', {
|
|
24525
|
+
year: 'numeric',
|
|
24526
|
+
month: 'long',
|
|
24527
|
+
day: 'numeric',
|
|
24528
|
+
}).format(date);
|
|
24529
|
+
}
|
|
24530
|
+
|
|
24531
|
+
export function validateEmail(email: string): boolean {
|
|
24532
|
+
const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
|
|
24533
|
+
return emailRegex.test(email);
|
|
24534
|
+
}
|
|
24535
|
+
|
|
24536
|
+
export function generateId(): string {
|
|
24537
|
+
return Math.random().toString(36).substring(2, 15);
|
|
24538
|
+
}
|
|
24539
|
+
`;
|
|
24540
|
+
await writeFile(join(projectPath, "packages/utils/src/index.ts"), utilsContent);
|
|
24541
|
+
await ensureDirectory(join(projectPath, "apps/web/src/app"));
|
|
24542
|
+
const webLayoutContent = `import type { Metadata } from 'next';
|
|
24543
|
+
import './globals.css';
|
|
24544
|
+
|
|
24545
|
+
export const metadata: Metadata = {
|
|
24546
|
+
title: '${context.projectName}',
|
|
24547
|
+
description: 'Enterprise SaaS built with bunkit \uD83C\uDF5E',
|
|
24548
|
+
};
|
|
24549
|
+
|
|
24550
|
+
export default function RootLayout({
|
|
24551
|
+
children,
|
|
24552
|
+
}: {
|
|
24553
|
+
children: React.ReactNode;
|
|
24554
|
+
}) {
|
|
24555
|
+
return (
|
|
24556
|
+
<html lang="en">
|
|
24557
|
+
<body>{children}</body>
|
|
24558
|
+
</html>
|
|
24559
|
+
);
|
|
24560
|
+
}
|
|
24561
|
+
`;
|
|
24562
|
+
await writeFile(join(projectPath, "apps/web/src/app/layout.tsx"), webLayoutContent);
|
|
24563
|
+
const webPageContent = `export default function Home() {
|
|
24564
|
+
return (
|
|
24565
|
+
<main className="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100">
|
|
24566
|
+
<div className="text-center space-y-6 p-8">
|
|
24567
|
+
<h1 className="text-6xl font-bold text-gray-900">
|
|
24568
|
+
Welcome to ${context.projectName} \uD83C\uDF5E
|
|
24569
|
+
</h1>
|
|
24570
|
+
<p className="text-xl text-gray-600 max-w-2xl">
|
|
24571
|
+
Enterprise-grade SaaS monorepo built with Next.js 16, React 19, Hono, and Bun
|
|
24572
|
+
</p>
|
|
24573
|
+
<div className="flex gap-4 justify-center mt-8">
|
|
24574
|
+
<a
|
|
24575
|
+
href="/dashboard"
|
|
24576
|
+
className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition"
|
|
24577
|
+
>
|
|
24578
|
+
Get Started
|
|
24579
|
+
</a>
|
|
24580
|
+
<a
|
|
24581
|
+
href="/docs"
|
|
24582
|
+
className="px-6 py-3 bg-gray-200 text-gray-800 rounded-lg hover:bg-gray-300 transition"
|
|
24583
|
+
>
|
|
24584
|
+
Documentation
|
|
24585
|
+
</a>
|
|
24586
|
+
</div>
|
|
24587
|
+
</div>
|
|
24588
|
+
</main>
|
|
24589
|
+
);
|
|
24590
|
+
}
|
|
24591
|
+
`;
|
|
24592
|
+
await writeFile(join(projectPath, "apps/web/src/app/page.tsx"), webPageContent);
|
|
24593
|
+
const webGlobalsCssContent = `@import "tailwindcss";
|
|
24594
|
+
|
|
24595
|
+
@theme {
|
|
24596
|
+
--color-primary: oklch(0.6 0.2 250);
|
|
24597
|
+
--color-secondary: oklch(0.5 0.15 280);
|
|
24598
|
+
}
|
|
24599
|
+
`;
|
|
24600
|
+
await writeFile(join(projectPath, "apps/web/src/app/globals.css"), webGlobalsCssContent);
|
|
24601
|
+
const webNextConfigContent = `import type { NextConfig } from 'next';
|
|
24602
|
+
|
|
24603
|
+
const nextConfig: NextConfig = {
|
|
24604
|
+
/* config options here */
|
|
24605
|
+
};
|
|
24606
|
+
|
|
24607
|
+
export default nextConfig;
|
|
24608
|
+
`;
|
|
24609
|
+
await writeFile(join(projectPath, "apps/web/next.config.ts"), webNextConfigContent);
|
|
24610
|
+
const webTailwindConfigContent = `import type { Config } from 'tailwindcss';
|
|
24611
|
+
|
|
24612
|
+
const config: Config = {
|
|
24613
|
+
content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'],
|
|
24614
|
+
theme: {
|
|
24615
|
+
extend: {},
|
|
24616
|
+
},
|
|
24617
|
+
plugins: [],
|
|
24618
|
+
};
|
|
24619
|
+
|
|
24620
|
+
export default config;
|
|
24621
|
+
`;
|
|
24622
|
+
await writeFile(join(projectPath, "apps/web/tailwind.config.ts"), webTailwindConfigContent);
|
|
24623
|
+
const webTsconfigContent = {
|
|
24624
|
+
compilerOptions: {
|
|
24625
|
+
target: "ES2017",
|
|
24626
|
+
lib: ["dom", "dom.iterable", "esnext"],
|
|
24627
|
+
allowJs: true,
|
|
24628
|
+
skipLibCheck: true,
|
|
24629
|
+
strict: true,
|
|
24630
|
+
noEmit: true,
|
|
24631
|
+
esModuleInterop: true,
|
|
24632
|
+
module: "esnext",
|
|
24633
|
+
moduleResolution: "bundler",
|
|
24634
|
+
resolveJsonModule: true,
|
|
24635
|
+
isolatedModules: true,
|
|
24636
|
+
jsx: "preserve",
|
|
24637
|
+
incremental: true,
|
|
24638
|
+
plugins: [
|
|
24639
|
+
{
|
|
24640
|
+
name: "next"
|
|
24641
|
+
}
|
|
24642
|
+
],
|
|
24643
|
+
paths: {
|
|
24644
|
+
"@/*": ["./src/*"]
|
|
24645
|
+
}
|
|
24646
|
+
},
|
|
24647
|
+
include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
24648
|
+
exclude: ["node_modules"]
|
|
24649
|
+
};
|
|
24650
|
+
await writeFile(join(projectPath, "apps/web/tsconfig.json"), JSON.stringify(webTsconfigContent, null, 2));
|
|
24651
|
+
await ensureDirectory(join(projectPath, "apps/platform/src/app"));
|
|
24652
|
+
const platformLayoutContent = `import type { Metadata } from 'next';
|
|
24653
|
+
import './globals.css';
|
|
24654
|
+
|
|
24655
|
+
export const metadata: Metadata = {
|
|
24656
|
+
title: '${context.projectName} - Admin Dashboard',
|
|
24657
|
+
description: 'Admin dashboard for ${context.projectName}',
|
|
24658
|
+
};
|
|
24659
|
+
|
|
24660
|
+
export default function RootLayout({
|
|
24661
|
+
children,
|
|
24662
|
+
}: {
|
|
24663
|
+
children: React.ReactNode;
|
|
24664
|
+
}) {
|
|
24665
|
+
return (
|
|
24666
|
+
<html lang="en">
|
|
24667
|
+
<body>{children}</body>
|
|
24668
|
+
</html>
|
|
24669
|
+
);
|
|
24670
|
+
}
|
|
24671
|
+
`;
|
|
24672
|
+
await writeFile(join(projectPath, "apps/platform/src/app/layout.tsx"), platformLayoutContent);
|
|
24673
|
+
const platformPageContent = `export default function Dashboard() {
|
|
24674
|
+
return (
|
|
24675
|
+
<main className="min-h-screen bg-gray-50">
|
|
24676
|
+
<div className="max-w-7xl mx-auto py-12 px-4">
|
|
24677
|
+
<header className="mb-8">
|
|
24678
|
+
<h1 className="text-4xl font-bold text-gray-900">
|
|
24679
|
+
Admin Dashboard
|
|
24680
|
+
</h1>
|
|
24681
|
+
<p className="text-gray-600 mt-2">
|
|
24682
|
+
Manage your ${context.projectName} platform
|
|
24683
|
+
</p>
|
|
24684
|
+
</header>
|
|
24685
|
+
|
|
24686
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
24687
|
+
<div className="bg-white p-6 rounded-lg shadow">
|
|
24688
|
+
<h2 className="text-xl font-semibold mb-2">Users</h2>
|
|
24689
|
+
<p className="text-3xl font-bold text-blue-600">1,234</p>
|
|
24690
|
+
</div>
|
|
24691
|
+
<div className="bg-white p-6 rounded-lg shadow">
|
|
24692
|
+
<h2 className="text-xl font-semibold mb-2">Revenue</h2>
|
|
24693
|
+
<p className="text-3xl font-bold text-green-600">$12,345</p>
|
|
24694
|
+
</div>
|
|
24695
|
+
<div className="bg-white p-6 rounded-lg shadow">
|
|
24696
|
+
<h2 className="text-xl font-semibold mb-2">Active</h2>
|
|
24697
|
+
<p className="text-3xl font-bold text-purple-600">567</p>
|
|
24698
|
+
</div>
|
|
24699
|
+
</div>
|
|
24700
|
+
</div>
|
|
24701
|
+
</main>
|
|
24702
|
+
);
|
|
24703
|
+
}
|
|
24704
|
+
`;
|
|
24705
|
+
await writeFile(join(projectPath, "apps/platform/src/app/page.tsx"), platformPageContent);
|
|
24706
|
+
const platformGlobalsCssContent = `@import "tailwindcss";
|
|
24707
|
+
|
|
24708
|
+
@theme {
|
|
24709
|
+
--color-primary: oklch(0.6 0.2 250);
|
|
24710
|
+
--color-secondary: oklch(0.5 0.15 280);
|
|
24711
|
+
}
|
|
24712
|
+
`;
|
|
24713
|
+
await writeFile(join(projectPath, "apps/platform/src/app/globals.css"), platformGlobalsCssContent);
|
|
24714
|
+
const platformNextConfigContent = `import type { NextConfig } from 'next';
|
|
24715
|
+
|
|
24716
|
+
const nextConfig: NextConfig = {
|
|
24717
|
+
/* config options here */
|
|
24718
|
+
};
|
|
24719
|
+
|
|
24720
|
+
export default nextConfig;
|
|
24721
|
+
`;
|
|
24722
|
+
await writeFile(join(projectPath, "apps/platform/next.config.ts"), platformNextConfigContent);
|
|
24723
|
+
const platformTailwindConfigContent = `import type { Config } from 'tailwindcss';
|
|
24724
|
+
|
|
24725
|
+
const config: Config = {
|
|
24726
|
+
content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'],
|
|
24727
|
+
theme: {
|
|
24728
|
+
extend: {},
|
|
24729
|
+
},
|
|
24730
|
+
plugins: [],
|
|
24731
|
+
};
|
|
24732
|
+
|
|
24733
|
+
export default config;
|
|
24734
|
+
`;
|
|
24735
|
+
await writeFile(join(projectPath, "apps/platform/tailwind.config.ts"), platformTailwindConfigContent);
|
|
24736
|
+
const platformTsconfigContent = {
|
|
24737
|
+
compilerOptions: {
|
|
24738
|
+
target: "ES2017",
|
|
24739
|
+
lib: ["dom", "dom.iterable", "esnext"],
|
|
24740
|
+
allowJs: true,
|
|
24741
|
+
skipLibCheck: true,
|
|
24742
|
+
strict: true,
|
|
24743
|
+
noEmit: true,
|
|
24744
|
+
esModuleInterop: true,
|
|
24745
|
+
module: "esnext",
|
|
24746
|
+
moduleResolution: "bundler",
|
|
24747
|
+
resolveJsonModule: true,
|
|
24748
|
+
isolatedModules: true,
|
|
24749
|
+
jsx: "preserve",
|
|
24750
|
+
incremental: true,
|
|
24751
|
+
plugins: [
|
|
24752
|
+
{
|
|
24753
|
+
name: "next"
|
|
24754
|
+
}
|
|
24755
|
+
],
|
|
24756
|
+
paths: {
|
|
24757
|
+
"@/*": ["./src/*"]
|
|
24758
|
+
}
|
|
24759
|
+
},
|
|
24760
|
+
include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
24761
|
+
exclude: ["node_modules"]
|
|
24762
|
+
};
|
|
24763
|
+
await writeFile(join(projectPath, "apps/platform/tsconfig.json"), JSON.stringify(platformTsconfigContent, null, 2));
|
|
24764
|
+
await ensureDirectory(join(projectPath, "apps/api/src"));
|
|
24765
|
+
const apiIndexContent = `import { Hono } from 'hono';
|
|
24766
|
+
import { serve } from 'bun';
|
|
24767
|
+
import { logger } from 'hono/logger';
|
|
24768
|
+
import { cors } from 'hono/cors';
|
|
24769
|
+
|
|
24770
|
+
const app = new Hono();
|
|
24771
|
+
|
|
24772
|
+
// Middleware
|
|
24773
|
+
app.use('*', logger());
|
|
24774
|
+
app.use('*', cors());
|
|
24775
|
+
|
|
24776
|
+
// Routes
|
|
24777
|
+
app.get('/', (context) => {
|
|
24778
|
+
return context.json({
|
|
24779
|
+
message: 'Welcome to ${context.projectName} API \uD83C\uDF5E',
|
|
24780
|
+
version: '1.0.0',
|
|
24781
|
+
});
|
|
24782
|
+
});
|
|
24783
|
+
|
|
24784
|
+
app.get('/health', (context) => {
|
|
24785
|
+
return context.json({
|
|
24786
|
+
status: 'ok',
|
|
24787
|
+
timestamp: new Date().toISOString(),
|
|
24788
|
+
});
|
|
24789
|
+
});
|
|
24790
|
+
|
|
24791
|
+
app.get('/api/users', (context) => {
|
|
24792
|
+
return context.json({
|
|
24793
|
+
users: [
|
|
24794
|
+
{ id: 1, email: 'john@example.com', name: 'John Doe' },
|
|
24795
|
+
{ id: 2, email: 'jane@example.com', name: 'Jane Smith' },
|
|
24796
|
+
],
|
|
24797
|
+
});
|
|
24798
|
+
});
|
|
24799
|
+
|
|
24800
|
+
// 404 handler
|
|
24801
|
+
app.notFound((context) => {
|
|
24802
|
+
return context.json({ error: 'Not found' }, 404);
|
|
24803
|
+
});
|
|
24804
|
+
|
|
24805
|
+
// Error handler
|
|
24806
|
+
app.onError((error, context) => {
|
|
24807
|
+
console.error(\`Error: \${error}\`);
|
|
24808
|
+
return context.json({ error: 'Internal server error' }, 500);
|
|
24809
|
+
});
|
|
24810
|
+
|
|
24811
|
+
// Start server
|
|
24812
|
+
serve({
|
|
24813
|
+
fetch: app.fetch,
|
|
24814
|
+
port: 3001,
|
|
24815
|
+
development: {
|
|
24816
|
+
hmr: true,
|
|
24817
|
+
console: true,
|
|
24818
|
+
},
|
|
24819
|
+
});
|
|
24820
|
+
|
|
24821
|
+
console.log('\uD83D\uDE80 ${context.projectName} API running on http://localhost:3001');
|
|
24822
|
+
`;
|
|
24823
|
+
await writeFile(join(projectPath, "apps/api/src/index.ts"), apiIndexContent);
|
|
24824
|
+
const apiTsconfigContent = {
|
|
24825
|
+
compilerOptions: {
|
|
24826
|
+
lib: ["ESNext"],
|
|
24827
|
+
target: "ESNext",
|
|
24828
|
+
module: "ESNext",
|
|
24829
|
+
moduleDetection: "force",
|
|
24830
|
+
allowJs: true,
|
|
24831
|
+
moduleResolution: "bundler",
|
|
24832
|
+
allowImportingTsExtensions: true,
|
|
24833
|
+
verbatimModuleSyntax: true,
|
|
24834
|
+
noEmit: true,
|
|
24835
|
+
strict: true,
|
|
24836
|
+
skipLibCheck: true,
|
|
24837
|
+
noFallthroughCasesInSwitch: true,
|
|
24838
|
+
types: ["@types/bun"]
|
|
24839
|
+
}
|
|
24840
|
+
};
|
|
24841
|
+
await writeFile(join(projectPath, "apps/api/tsconfig.json"), JSON.stringify(apiTsconfigContent, null, 2));
|
|
24510
24842
|
const readmeContent = `# ${context.projectName}
|
|
24511
24843
|
|
|
24512
24844
|
Enterprise-grade SaaS monorepo created with [bunkit](https://github.com/Arakiss/bunkit) \uD83C\uDF5E
|