create-buntok 0.1.3 → 0.2.1
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 +1 -1
- package/src/index.ts +31 -41
- package/templates/.vscode/settings.json +1 -0
- package/templates/README.md +76 -0
- package/templates/biome.json +10 -4
- package/templates/package.json +2 -1
- package/templates/src/controllers/home.controller.ts +9 -0
- package/templates/src/index.ts +22 -4
- package/templates/tsconfig.json +14 -3
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
-
cpSync,
|
|
5
4
|
existsSync,
|
|
6
|
-
mkdirSync,
|
|
7
|
-
readFileSync,
|
|
8
|
-
readdirSync,
|
|
9
|
-
statSync,
|
|
10
|
-
unlinkSync,
|
|
11
|
-
writeFileSync,
|
|
12
5
|
} from "node:fs";
|
|
6
|
+
import fs from "node:fs/promises";
|
|
13
7
|
import { join, resolve } from "node:path";
|
|
14
8
|
import { createInterface } from "node:readline";
|
|
15
9
|
|
|
@@ -49,22 +43,6 @@ function validateProjectName(name: string): boolean {
|
|
|
49
43
|
return true;
|
|
50
44
|
}
|
|
51
45
|
|
|
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
46
|
function replaceTemplate(content: string, projectName: string): string {
|
|
69
47
|
return content.replace(/{PROJECT_NAME}/g, projectName);
|
|
70
48
|
}
|
|
@@ -115,12 +93,12 @@ async function main() {
|
|
|
115
93
|
"\x1b[36mDo you want to include Docker support? (Y/n): \x1b[0m",
|
|
116
94
|
);
|
|
117
95
|
|
|
118
|
-
// Create project directory
|
|
119
|
-
mkdirSync(projectPath, { recursive: true });
|
|
120
|
-
|
|
121
|
-
// Copy templates
|
|
96
|
+
// Create project directory and copy templates asynchronously
|
|
122
97
|
console.log("\n\x1b[90m Copying template files...\x1b[0m");
|
|
123
|
-
|
|
98
|
+
await fs.mkdir(projectPath, { recursive: true });
|
|
99
|
+
|
|
100
|
+
// Use native recursive copy for maximum performance
|
|
101
|
+
await fs.cp(TEMPLATES_DIR, projectPath, { recursive: true });
|
|
124
102
|
|
|
125
103
|
// Handle Docker files based on user choice
|
|
126
104
|
const dockerFiles = ["Dockerfile", ".dockerignore", "docker-compose.yml"];
|
|
@@ -129,7 +107,7 @@ async function main() {
|
|
|
129
107
|
for (const file of dockerFiles) {
|
|
130
108
|
const filePath = join(projectPath, file);
|
|
131
109
|
if (existsSync(filePath)) {
|
|
132
|
-
|
|
110
|
+
await fs.unlink(filePath);
|
|
133
111
|
}
|
|
134
112
|
}
|
|
135
113
|
console.log("\x1b[90m Skipped Docker files\x1b[0m");
|
|
@@ -137,18 +115,18 @@ async function main() {
|
|
|
137
115
|
console.log("\x1b[90m Included Docker support\x1b[0m");
|
|
138
116
|
}
|
|
139
117
|
|
|
140
|
-
// Process template files (replace placeholders)
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
118
|
+
// Process template files (replace placeholders) concurrently
|
|
119
|
+
const filesToProcess = ["package.json", "tsconfig.json"];
|
|
120
|
+
|
|
121
|
+
await Promise.all(
|
|
122
|
+
filesToProcess.map(async (file) => {
|
|
123
|
+
const filePath = join(projectPath, file);
|
|
124
|
+
if (existsSync(filePath)) {
|
|
125
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
126
|
+
await fs.writeFile(filePath, replaceTemplate(content, projectName));
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
);
|
|
152
130
|
|
|
153
131
|
// Run bun install
|
|
154
132
|
console.log("\n\x1b[90m Installing dependencies...\x1b[0m\n");
|
|
@@ -163,6 +141,18 @@ async function main() {
|
|
|
163
141
|
process.exit(1);
|
|
164
142
|
}
|
|
165
143
|
|
|
144
|
+
// Initialize Git repository
|
|
145
|
+
console.log("\n\x1b[90m Initializing git repository...\x1b[0m");
|
|
146
|
+
const gitProc = Bun.spawnSync(["git", "init"], {
|
|
147
|
+
cwd: projectPath,
|
|
148
|
+
stdio: ["ignore", "ignore", "ignore"], // Hide git output for cleaner terminal
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
if (gitProc.exitCode === 0) {
|
|
152
|
+
// Add all files to initial commit staging to be ready
|
|
153
|
+
Bun.spawnSync(["git", "add", "."], { cwd: projectPath, stdio: ["ignore", "ignore", "ignore"] });
|
|
154
|
+
}
|
|
155
|
+
|
|
166
156
|
// Success message
|
|
167
157
|
console.log(`
|
|
168
158
|
\x1b[32m✓ Project "${projectName}" created successfully!\x1b[0m
|
package/templates/README.md
CHANGED
|
@@ -27,6 +27,14 @@ src/
|
|
|
27
27
|
└── index.ts # Entry point
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
| Feature | Description |
|
|
31
|
+
|------|-------------|
|
|
32
|
+
| 📦 **Code Generation** | CLI tool for generating schema, repo, service, controller |
|
|
33
|
+
| 🧠 **Cache System** | Built-in driver-based Cache manager |
|
|
34
|
+
| 🔄 **Queue System** | Built-in driver-based background Queues |
|
|
35
|
+
| ⏱️ **Task Scheduler** | Native CRON job support via `@CronJob` |
|
|
36
|
+
| 🛡️ **Auth Guards** | Granular access control via `@UseGuard` |
|
|
37
|
+
|
|
30
38
|
## Code Generation
|
|
31
39
|
|
|
32
40
|
Generate CRUD files for an entity:
|
|
@@ -133,6 +141,74 @@ api.get("/users", getUsers);
|
|
|
133
141
|
api.post("/users", createUser);
|
|
134
142
|
```
|
|
135
143
|
|
|
144
|
+
### Controllers (Decorators)
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
import { Controller, Get } from "buntok";
|
|
148
|
+
|
|
149
|
+
@Controller("/users")
|
|
150
|
+
export class UserController {
|
|
151
|
+
@Get("/")
|
|
152
|
+
getAll(ctx: Context) {
|
|
153
|
+
return ctx.json([{ id: 1 }]);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
app.registerController(UserController);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### WebSockets
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
app.ws("/chat", {
|
|
164
|
+
open: (ws) => {
|
|
165
|
+
// Treat user ID as a room
|
|
166
|
+
ws.subscribe("user_123");
|
|
167
|
+
},
|
|
168
|
+
message: (ws, msg) => {
|
|
169
|
+
// Parse JSON for events
|
|
170
|
+
const payload = JSON.parse(String(msg));
|
|
171
|
+
if (payload.event === "typing") { /* ... */ }
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Note on Frontend Clients:**
|
|
177
|
+
Buntok uses **Raw WebSockets (RFC 6455)** natively.
|
|
178
|
+
⚠️ **Do NOT use `socket.io-client`** to connect to Buntok.
|
|
179
|
+
✅ **Recommended clients for React/Next.js:** `react-use-websocket`, `partysocket`, or native `WebSocket`.
|
|
180
|
+
|
|
181
|
+
**Broadcasting Events from API/Jobs:**
|
|
182
|
+
You can access the Bun Server instance natively via `app.server` to publish messages from anywhere in your backend!
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// Broadcast to a specific user
|
|
186
|
+
app.post("/api/checkout", (ctx) => {
|
|
187
|
+
app.server?.publish("user_123", JSON.stringify({
|
|
188
|
+
event: "order_done", data: {}
|
|
189
|
+
}));
|
|
190
|
+
return ctx.success();
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Server-Sent Events (SSE)
|
|
195
|
+
|
|
196
|
+
Lightweight alternative to WebSockets for Server-to-Client one-way streams.
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
app.get("/stream", (ctx) => {
|
|
200
|
+
return ctx.sse((stream) => {
|
|
201
|
+
stream.sendEvent("connected", { status: "ok" });
|
|
202
|
+
|
|
203
|
+
const timer = setInterval(() => {
|
|
204
|
+
stream.sendEvent("ping", { time: Date.now() });
|
|
205
|
+
}, 1000);
|
|
206
|
+
|
|
207
|
+
stream.onClose(() => clearInterval(timer));
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
136
212
|
### Middleware
|
|
137
213
|
|
|
138
214
|
```ts
|
package/templates/biome.json
CHANGED
|
@@ -6,23 +6,29 @@
|
|
|
6
6
|
"useIgnoreFile": true
|
|
7
7
|
},
|
|
8
8
|
"files": {
|
|
9
|
-
"ignoreUnknown":
|
|
9
|
+
"ignoreUnknown": true,
|
|
10
|
+
"ignore": ["node_modules", "dist", ".buntok", "coverage"]
|
|
10
11
|
},
|
|
11
12
|
"formatter": {
|
|
12
13
|
"enabled": true,
|
|
13
14
|
"indentStyle": "tab",
|
|
14
15
|
"indentWidth": 2,
|
|
15
|
-
"lineWidth":
|
|
16
|
+
"lineWidth": 100,
|
|
17
|
+
"lineEnding": "lf"
|
|
16
18
|
},
|
|
17
19
|
"linter": {
|
|
18
20
|
"enabled": true,
|
|
19
21
|
"rules": {
|
|
20
|
-
"preset": "recommended"
|
|
22
|
+
"preset": "recommended",
|
|
23
|
+
"suspicious": {
|
|
24
|
+
"noExplicitAny": "off"
|
|
25
|
+
}
|
|
21
26
|
}
|
|
22
27
|
},
|
|
23
28
|
"javascript": {
|
|
24
29
|
"formatter": {
|
|
25
|
-
"quoteStyle": "double"
|
|
30
|
+
"quoteStyle": "double",
|
|
31
|
+
"trailingCommas": "all"
|
|
26
32
|
}
|
|
27
33
|
}
|
|
28
34
|
}
|
package/templates/package.json
CHANGED
package/templates/src/index.ts
CHANGED
|
@@ -1,7 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
App,
|
|
3
|
+
Cache,
|
|
4
|
+
MemoryCacheDriver,
|
|
5
|
+
Queue,
|
|
6
|
+
MemoryQueueDriver,
|
|
7
|
+
setDefaultSchedulerDriver,
|
|
8
|
+
MemorySchedulerDriver
|
|
9
|
+
} from "buntok";
|
|
10
|
+
|
|
11
|
+
import { HomeController } from "./controllers/home.controller";
|
|
12
|
+
|
|
13
|
+
// 1. Set global default scheduler driver
|
|
14
|
+
setDefaultSchedulerDriver(new MemorySchedulerDriver());
|
|
2
15
|
|
|
3
16
|
const app = new App();
|
|
4
17
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
18
|
+
// 2. Register Cache and Queue into DI
|
|
19
|
+
app.set("cache", new Cache(new MemoryCacheDriver()));
|
|
20
|
+
app.set("queue", new Queue(new MemoryQueueDriver("main")));
|
|
21
|
+
|
|
22
|
+
// 3. Register Controllers
|
|
23
|
+
app.registerController(HomeController);
|
|
24
|
+
|
|
25
|
+
export default app;
|
package/templates/tsconfig.json
CHANGED
|
@@ -6,17 +6,28 @@
|
|
|
6
6
|
"moduleDetection": "force",
|
|
7
7
|
"jsx": "react-jsx",
|
|
8
8
|
"allowJs": true,
|
|
9
|
-
"types": ["bun"],
|
|
9
|
+
"types": ["bun", "node"],
|
|
10
10
|
"moduleResolution": "bundler",
|
|
11
11
|
"allowImportingTsExtensions": true,
|
|
12
12
|
"verbatimModuleSyntax": true,
|
|
13
13
|
"noEmit": true,
|
|
14
|
+
|
|
15
|
+
/* Strictness Options for TS 7+ */
|
|
14
16
|
"strict": true,
|
|
17
|
+
"noUncheckedIndexedAccess": true,
|
|
18
|
+
"exactOptionalPropertyTypes": true,
|
|
19
|
+
"noImplicitOverride": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"isolatedModules": true,
|
|
15
22
|
"skipLibCheck": true,
|
|
16
|
-
|
|
23
|
+
|
|
24
|
+
/* Buntok Decorator Config */
|
|
25
|
+
"experimentalDecorators": true,
|
|
26
|
+
"emitDecoratorMetadata": true,
|
|
17
27
|
"paths": {
|
|
18
28
|
"@/*": ["./src/*"]
|
|
19
29
|
}
|
|
20
30
|
},
|
|
21
|
-
"include": ["src/**/*"]
|
|
31
|
+
"include": ["src/**/*", "drizzle.config.ts"],
|
|
32
|
+
"exclude": ["node_modules", "dist"]
|
|
22
33
|
}
|