create-buntok 0.1.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/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "create-buntok",
3
+ "version": "0.1.0",
4
+ "description": "CLI tool to create new Buntok projects",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-buntok": "./src/index.ts"
8
+ },
9
+ "files": [
10
+ "src",
11
+ "templates"
12
+ ],
13
+ "keywords": [
14
+ "buntok",
15
+ "bun",
16
+ "framework",
17
+ "cli",
18
+ "scaffold"
19
+ ],
20
+ "license": "MIT",
21
+ "devDependencies": {
22
+ "@types/bun": "latest"
23
+ }
24
+ }
package/src/index.ts ADDED
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import {
4
+ cpSync,
5
+ existsSync,
6
+ mkdirSync,
7
+ readFileSync,
8
+ readdirSync,
9
+ statSync,
10
+ unlinkSync,
11
+ writeFileSync,
12
+ } from "node:fs";
13
+ import { join, resolve } from "node:path";
14
+ import { createInterface } from "node:readline";
15
+
16
+ const TEMPLATES_DIR = join(import.meta.dir, "..", "templates");
17
+
18
+ function printBanner() {
19
+ console.log(`
20
+ \x1b[36m
21
+ ██████╗ ██╗ ██╗███╗ ██╗████████╗ ██████╗ ██╗ ██╗
22
+ ██╔══██╗██║ ██║████╗ ██║╚══██╔══╝██╔═══██╗██║ ██╔╝
23
+ ██████╔╝██║ ██║██╔██╗ ██║ ██║ ██║ ██║█████╔╝
24
+ ██╔══██╗██║ ██║██║╚██╗██║ ██║ ██║ ██║██╔═██╗
25
+ ██████╔╝╚██████╔╝██║ ╚████║ ██║ ╚██████╔╝██║ ██╗
26
+ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
27
+ \x1b[0m`);
28
+ }
29
+
30
+ function printUsage() {
31
+ console.log("Usage: bunx create-buntok <project-name>\n");
32
+ console.log("Example:");
33
+ console.log(" bunx create-buntok my-api\n");
34
+ }
35
+
36
+ function validateProjectName(name: string): boolean {
37
+ if (!name || name.length === 0) {
38
+ console.error("\x1b[31mError: Project name is required\x1b[0m");
39
+ return false;
40
+ }
41
+
42
+ if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
43
+ console.error(
44
+ "\x1b[31mError: Project name can only contain letters, numbers, hyphens, and underscores\x1b[0m",
45
+ );
46
+ return false;
47
+ }
48
+
49
+ return true;
50
+ }
51
+
52
+ function copyDirSync(src: string, dest: string) {
53
+ mkdirSync(dest, { recursive: true });
54
+ const entries = readdirSync(src);
55
+
56
+ for (const entry of entries) {
57
+ const srcPath = join(src, entry);
58
+ const destPath = join(dest, entry);
59
+
60
+ if (statSync(srcPath).isDirectory()) {
61
+ copyDirSync(srcPath, destPath);
62
+ } else {
63
+ cpSync(srcPath, destPath);
64
+ }
65
+ }
66
+ }
67
+
68
+ function replaceTemplate(content: string, projectName: string): string {
69
+ return content.replace(/{PROJECT_NAME}/g, projectName);
70
+ }
71
+
72
+ function askQuestion(question: string): Promise<boolean> {
73
+ return new Promise((resolve) => {
74
+ const rl = createInterface({
75
+ input: process.stdin,
76
+ output: process.stdout,
77
+ });
78
+
79
+ rl.question(question, (answer) => {
80
+ rl.close();
81
+ const normalized = answer.trim().toLowerCase();
82
+ resolve(normalized === "y" || normalized === "yes" || normalized === "");
83
+ });
84
+ });
85
+ }
86
+
87
+ async function main() {
88
+ printBanner();
89
+
90
+ const args = process.argv.slice(2);
91
+ const projectName = args[0];
92
+
93
+ if (!projectName) {
94
+ printUsage();
95
+ process.exit(1);
96
+ }
97
+
98
+ if (!validateProjectName(projectName)) {
99
+ process.exit(1);
100
+ }
101
+
102
+ const projectPath = resolve(process.cwd(), projectName);
103
+
104
+ if (existsSync(projectPath)) {
105
+ console.error(
106
+ `\x1b[31mError: Directory "${projectName}" already exists\x1b[0m`,
107
+ );
108
+ process.exit(1);
109
+ }
110
+
111
+ console.log(`\x1b[36mCreating Buntok project: ${projectName}\x1b[0m\n`);
112
+
113
+ // Ask about Docker support
114
+ const useDocker = await askQuestion(
115
+ "\x1b[36mDo you want to include Docker support? (Y/n): \x1b[0m",
116
+ );
117
+
118
+ // Create project directory
119
+ mkdirSync(projectPath, { recursive: true });
120
+
121
+ // Copy templates
122
+ console.log("\n\x1b[90m Copying template files...\x1b[0m");
123
+ copyDirSync(TEMPLATES_DIR, projectPath);
124
+
125
+ // Handle Docker files based on user choice
126
+ const dockerFiles = ["Dockerfile", ".dockerignore", "docker-compose.yml"];
127
+ if (!useDocker) {
128
+ // Remove Docker files if user declined
129
+ for (const file of dockerFiles) {
130
+ const filePath = join(projectPath, file);
131
+ if (existsSync(filePath)) {
132
+ unlinkSync(filePath);
133
+ }
134
+ }
135
+ console.log("\x1b[90m Skipped Docker files\x1b[0m");
136
+ } else {
137
+ console.log("\x1b[90m Included Docker support\x1b[0m");
138
+ }
139
+
140
+ // Process template files (replace placeholders)
141
+ const packageJsonPath = join(projectPath, "package.json");
142
+ if (existsSync(packageJsonPath)) {
143
+ const content = readFileSync(packageJsonPath, "utf-8");
144
+ writeFileSync(packageJsonPath, replaceTemplate(content, projectName));
145
+ }
146
+
147
+ const tsConfigPath = join(projectPath, "tsconfig.json");
148
+ if (existsSync(tsConfigPath)) {
149
+ const content = readFileSync(tsConfigPath, "utf-8");
150
+ writeFileSync(tsConfigPath, replaceTemplate(content, projectName));
151
+ }
152
+
153
+ // Run bun install
154
+ console.log("\n\x1b[90m Installing dependencies...\x1b[0m\n");
155
+
156
+ const proc = Bun.spawnSync(["bun", "install"], {
157
+ cwd: projectPath,
158
+ stdio: ["inherit", "inherit", "inherit"],
159
+ });
160
+
161
+ if (proc.exitCode !== 0) {
162
+ console.error("\x1b[31mFailed to install dependencies\x1b[0m");
163
+ process.exit(1);
164
+ }
165
+
166
+ // Success message
167
+ console.log(`
168
+ \x1b[32m✓ Project "${projectName}" created successfully!\x1b[0m
169
+
170
+ \x1b[36mGetting started:\x1b[0m
171
+ cd ${projectName}
172
+ bun run dev
173
+
174
+ \x1b[36mCode generation:\x1b[0m
175
+ bunx buntok create <entity> # Generate all (schema, repo, service, controller)
176
+ bunx buntok create <entity> --schema # Generate only schema
177
+ ${useDocker ? `
178
+ \x1b[36mDocker:\x1b[0m
179
+ docker compose up --build
180
+ ` : ""}
181
+ \x1b[90mHappy coding with Buntok! ⚡\x1b[0m
182
+ `);
183
+ }
184
+
185
+ main();
@@ -0,0 +1,34 @@
1
+ # dependencies (bun install)
2
+ node_modules
3
+
4
+ # output
5
+ out
6
+ dist
7
+ *.tgz
8
+
9
+ # code coverage
10
+ coverage
11
+ *.lcov
12
+
13
+ # logs
14
+ logs
15
+ *.log
16
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17
+
18
+ # dotenv environment variable files
19
+ .env
20
+ .env.development.local
21
+ .env.test.local
22
+ .env.production.local
23
+ .env.local
24
+
25
+ # caches
26
+ .eslintcache
27
+ .cache
28
+ *.tsbuildinfo
29
+
30
+ # IntelliJ based IDEs
31
+ .idea
32
+
33
+ # Finder (MacOS) folder config
34
+ .DS_Store
@@ -0,0 +1,6 @@
1
+ # Database
2
+ DATABASE_URL=postgresql://user:password@localhost:5432/buntok
3
+
4
+ # Server
5
+ PORT=1212
6
+ NODE_ENV=development
@@ -0,0 +1,15 @@
1
+ {
2
+ "editor.formatOnSave": true,
3
+ "editor.defaultFormatter": "biomejs.biome",
4
+ "editor.tabSize": 2,
5
+ "editor.insertSpaces": false,
6
+ "[typescript]": {
7
+ "editor.defaultFormatter": "biomejs.biome"
8
+ },
9
+ "[javascript]": {
10
+ "editor.defaultFormatter": "biomejs.biome"
11
+ },
12
+ "[json]": {
13
+ "editor.defaultFormatter": "biomejs.biome"
14
+ }
15
+ }
@@ -0,0 +1,36 @@
1
+ # Builder
2
+ FROM oven/bun:alpine AS builder
3
+ WORKDIR /app
4
+
5
+ # Copy konfigurasi package dan install dependency
6
+ COPY package.json bun.lockb* ./
7
+ RUN bun install --frozen-lockfile
8
+
9
+ # Copy seluruh source code
10
+ COPY . .
11
+
12
+ # Production Runner
13
+ FROM oven/bun:alpine
14
+ WORKDIR /app
15
+
16
+ # Copy dependency yang sudah di-install dan source code dari builder
17
+ COPY --from=builder /app/node_modules ./node_modules
18
+ COPY --from=builder /app/src ./src
19
+ COPY --from=builder /app/package.json ./
20
+
21
+ # Siapkan folder logs
22
+ RUN mkdir -p /app/logs && chown -R bun:bun /app/logs
23
+
24
+ # Gunakan user non-root untuk keamanan
25
+ USER bun
26
+
27
+ # Expose default port
28
+ EXPOSE 1212
29
+
30
+ # Environment variables
31
+ ENV NODE_ENV=production
32
+ ENV PORT=1212
33
+ ENV LOG_DIR=/app/logs
34
+
35
+ # Jalankan framework
36
+ CMD ["bun", "run", "src/index.ts"]
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/2.5.3/schema.json",
3
+ "vcs": {
4
+ "enabled": true,
5
+ "clientKind": "git",
6
+ "useIgnoreFile": true
7
+ },
8
+ "files": {
9
+ "ignoreUnknown": false
10
+ },
11
+ "formatter": {
12
+ "enabled": true,
13
+ "indentStyle": "tab",
14
+ "indentWidth": 2,
15
+ "lineWidth": 80
16
+ },
17
+ "linter": {
18
+ "enabled": true,
19
+ "rules": {
20
+ "preset": "recommended"
21
+ }
22
+ },
23
+ "javascript": {
24
+ "formatter": {
25
+ "quoteStyle": "double"
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,15 @@
1
+ services:
2
+ app:
3
+ build: .
4
+ ports:
5
+ - "${PORT:-1212}:1212"
6
+ environment:
7
+ - NODE_ENV=production
8
+ - PORT=1212
9
+ - LOG_DIR=/app/logs
10
+ volumes:
11
+ - logs:/app/logs
12
+ restart: unless-stopped
13
+
14
+ volumes:
15
+ logs:
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from "drizzle-kit";
2
+
3
+ export default defineConfig({
4
+ schema: "./src/db/schemas/*",
5
+ out: "./drizzle",
6
+ dialect: "postgresql",
7
+ dbCredentials: {
8
+ url: process.env.DATABASE_URL || "postgresql://localhost:5432/buntok",
9
+ },
10
+ });
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "{PROJECT_NAME}",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "bun --watch src/index.ts",
7
+ "start": "bun run src/index.ts",
8
+ "db:push": "bunx drizzle-kit push",
9
+ "db:generate": "bunx drizzle-kit generate",
10
+ "db:migrate": "bunx drizzle-kit migrate",
11
+ "db:studio": "bunx drizzle-kit studio",
12
+ "check": "bunx @biomejs/biome check --write .",
13
+ "format": "bunx @biomejs/biome format --write .",
14
+ "lint": "bunx @biomejs/biome lint ."
15
+ },
16
+ "dependencies": {
17
+ "buntok": "latest",
18
+ "drizzle-orm": "^0.38.0"
19
+ },
20
+ "devDependencies": {
21
+ "@biomejs/biome": "2.5.3",
22
+ "@types/bun": "latest",
23
+ "drizzle-kit": "^0.30.0",
24
+ "typescript": "^5"
25
+ }
26
+ }
Binary file
@@ -0,0 +1,9 @@
1
+ import { drizzle } from "drizzle-orm/bun-sql";
2
+ import * as schema from "./schemas";
3
+
4
+ // TODO: Update DATABASE_URL in .env file
5
+ // Example: DATABASE_URL=postgresql://user:password@localhost:5432/mydb
6
+
7
+ const connection = Bun.env.DATABASE_URL || "postgresql://localhost:5432/buntok";
8
+
9
+ export const db = drizzle(connection, { schema });
@@ -0,0 +1,11 @@
1
+ import { App } from "buntok";
2
+
3
+ const app = new App();
4
+
5
+ app.get("/", (ctx) => {
6
+ return ctx.json({ message: "Welcome to {PROJECT_NAME}!" });
7
+ });
8
+
9
+ app.listen(3000, () => {
10
+ console.log("Server running on http://localhost:3000");
11
+ });
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": ["ESNext"],
4
+ "target": "ESNext",
5
+ "module": "Preserve",
6
+ "moduleDetection": "force",
7
+ "jsx": "react-jsx",
8
+ "allowJs": true,
9
+ "types": ["bun"],
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "verbatimModuleSyntax": true,
13
+ "noEmit": true,
14
+ "strict": true,
15
+ "skipLibCheck": true
16
+ },
17
+ "include": ["src/**/*"]
18
+ }