@buenojs/bueno 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/.env.example +109 -0
- package/.github/workflows/ci.yml +31 -0
- package/LICENSE +21 -0
- package/README.md +892 -0
- package/architecture.md +652 -0
- package/bun.lock +70 -0
- package/dist/cli/index.js +3233 -0
- package/dist/index.js +9014 -0
- package/package.json +77 -0
- package/src/cache/index.ts +795 -0
- package/src/cli/ARCHITECTURE.md +837 -0
- package/src/cli/bin.ts +10 -0
- package/src/cli/commands/build.ts +425 -0
- package/src/cli/commands/dev.ts +248 -0
- package/src/cli/commands/generate.ts +541 -0
- package/src/cli/commands/help.ts +55 -0
- package/src/cli/commands/index.ts +112 -0
- package/src/cli/commands/migration.ts +355 -0
- package/src/cli/commands/new.ts +804 -0
- package/src/cli/commands/start.ts +208 -0
- package/src/cli/core/args.ts +283 -0
- package/src/cli/core/console.ts +349 -0
- package/src/cli/core/index.ts +60 -0
- package/src/cli/core/prompt.ts +424 -0
- package/src/cli/core/spinner.ts +265 -0
- package/src/cli/index.ts +135 -0
- package/src/cli/templates/deploy.ts +295 -0
- package/src/cli/templates/docker.ts +307 -0
- package/src/cli/templates/index.ts +24 -0
- package/src/cli/utils/fs.ts +428 -0
- package/src/cli/utils/index.ts +8 -0
- package/src/cli/utils/strings.ts +197 -0
- package/src/config/env.ts +408 -0
- package/src/config/index.ts +506 -0
- package/src/config/loader.ts +329 -0
- package/src/config/merge.ts +285 -0
- package/src/config/types.ts +320 -0
- package/src/config/validation.ts +441 -0
- package/src/container/forward-ref.ts +143 -0
- package/src/container/index.ts +386 -0
- package/src/context/index.ts +360 -0
- package/src/database/index.ts +1142 -0
- package/src/database/migrations/index.ts +371 -0
- package/src/database/schema/index.ts +619 -0
- package/src/frontend/api-routes.ts +640 -0
- package/src/frontend/bundler.ts +643 -0
- package/src/frontend/console-client.ts +419 -0
- package/src/frontend/console-stream.ts +587 -0
- package/src/frontend/dev-server.ts +846 -0
- package/src/frontend/file-router.ts +611 -0
- package/src/frontend/frameworks/index.ts +106 -0
- package/src/frontend/frameworks/react.ts +85 -0
- package/src/frontend/frameworks/solid.ts +104 -0
- package/src/frontend/frameworks/svelte.ts +110 -0
- package/src/frontend/frameworks/vue.ts +92 -0
- package/src/frontend/hmr-client.ts +663 -0
- package/src/frontend/hmr.ts +728 -0
- package/src/frontend/index.ts +342 -0
- package/src/frontend/islands.ts +552 -0
- package/src/frontend/isr.ts +555 -0
- package/src/frontend/layout.ts +475 -0
- package/src/frontend/ssr/react.ts +446 -0
- package/src/frontend/ssr/solid.ts +523 -0
- package/src/frontend/ssr/svelte.ts +546 -0
- package/src/frontend/ssr/vue.ts +504 -0
- package/src/frontend/ssr.ts +699 -0
- package/src/frontend/types.ts +2274 -0
- package/src/health/index.ts +604 -0
- package/src/index.ts +410 -0
- package/src/lock/index.ts +587 -0
- package/src/logger/index.ts +444 -0
- package/src/logger/transports/index.ts +969 -0
- package/src/metrics/index.ts +494 -0
- package/src/middleware/built-in.ts +360 -0
- package/src/middleware/index.ts +94 -0
- package/src/modules/filters.ts +458 -0
- package/src/modules/guards.ts +405 -0
- package/src/modules/index.ts +1256 -0
- package/src/modules/interceptors.ts +574 -0
- package/src/modules/lazy.ts +418 -0
- package/src/modules/lifecycle.ts +478 -0
- package/src/modules/metadata.ts +90 -0
- package/src/modules/pipes.ts +626 -0
- package/src/router/index.ts +339 -0
- package/src/router/linear.ts +371 -0
- package/src/router/regex.ts +292 -0
- package/src/router/tree.ts +562 -0
- package/src/rpc/index.ts +1263 -0
- package/src/security/index.ts +436 -0
- package/src/ssg/index.ts +631 -0
- package/src/storage/index.ts +456 -0
- package/src/telemetry/index.ts +1097 -0
- package/src/testing/index.ts +1586 -0
- package/src/types/index.ts +236 -0
- package/src/types/optional-deps.d.ts +219 -0
- package/src/validation/index.ts +276 -0
- package/src/websocket/index.ts +1004 -0
- package/tests/integration/cli.test.ts +1016 -0
- package/tests/integration/fullstack.test.ts +234 -0
- package/tests/unit/cache.test.ts +174 -0
- package/tests/unit/cli-commands.test.ts +892 -0
- package/tests/unit/cli.test.ts +1258 -0
- package/tests/unit/container.test.ts +279 -0
- package/tests/unit/context.test.ts +221 -0
- package/tests/unit/database.test.ts +183 -0
- package/tests/unit/linear-router.test.ts +280 -0
- package/tests/unit/lock.test.ts +336 -0
- package/tests/unit/middleware.test.ts +184 -0
- package/tests/unit/modules.test.ts +142 -0
- package/tests/unit/pubsub.test.ts +257 -0
- package/tests/unit/regex-router.test.ts +265 -0
- package/tests/unit/router.test.ts +373 -0
- package/tests/unit/rpc.test.ts +1248 -0
- package/tests/unit/security.test.ts +174 -0
- package/tests/unit/telemetry.test.ts +371 -0
- package/tests/unit/test-cache.test.ts +110 -0
- package/tests/unit/test-database.test.ts +282 -0
- package/tests/unit/tree-router.test.ts +325 -0
- package/tests/unit/validation.test.ts +794 -0
- package/tsconfig.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,892 @@
|
|
|
1
|
+
# Bueno
|
|
2
|
+
|
|
3
|
+
A Bun-Native Full-Stack Framework
|
|
4
|
+
|
|
5
|
+
[](https://github.com/buenojs/bueno/actions)
|
|
6
|
+
[](https://codecov.io/gh/buenojs/bueno)
|
|
7
|
+
[](https://www.npmjs.com/package/@buenojs/bueno)
|
|
8
|
+
[](https://github.com/buenojs/bueno/blob/main/LICENSE)
|
|
9
|
+
[](https://bun.sh)
|
|
10
|
+
[](https://github.com/buenojs/bueno/graphs/commit-activity)
|
|
11
|
+
[](https://github.com/buenojs/bueno/commits/main)
|
|
12
|
+
|
|
13
|
+
## Why Bueno?
|
|
14
|
+
|
|
15
|
+
Bueno is a **Bun-native** full-stack framework designed from the ground up to leverage Bun's exceptional performance and modern JavaScript capabilities. Bueno embraces Bun's APIs, resulting in:
|
|
16
|
+
|
|
17
|
+
- **Blazing Fast Performance**: Built on Bun's native HTTP server and optimized runtime
|
|
18
|
+
- **Zero Configuration**: Sensible defaults that work out of the box
|
|
19
|
+
- **Full-Stack Integration**: Seamless frontend and backend development
|
|
20
|
+
- **Type Safety**: End-to-end TypeScript with full type inference
|
|
21
|
+
- **Modern DX**: Hot module replacement, fast testing, and intuitive APIs
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
### Quick Start (New Project)
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Create a new project (recommended)
|
|
29
|
+
bunx create-bueno my-app
|
|
30
|
+
cd my-app
|
|
31
|
+
bun install
|
|
32
|
+
bun dev
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Add to Existing Project
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# As a dependency
|
|
39
|
+
bun add @buenojs/bueno
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Global CLI Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Install globally
|
|
46
|
+
bun install -g @buenojs/bueno
|
|
47
|
+
|
|
48
|
+
# Use CLI commands anywhere
|
|
49
|
+
bueno dev
|
|
50
|
+
bueno build
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { createServer, Router } from '@buenojs/bueno';
|
|
57
|
+
|
|
58
|
+
const router = new Router();
|
|
59
|
+
|
|
60
|
+
router.get('/hello', (ctx) => {
|
|
61
|
+
return ctx.json({ message: 'Hello, World!' });
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const server = createServer();
|
|
65
|
+
server.router = router;
|
|
66
|
+
server.listen(3000);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## CLI Commands
|
|
70
|
+
|
|
71
|
+
### `bueno new <name>`
|
|
72
|
+
|
|
73
|
+
Create a new Bueno project.
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
bueno new my-app
|
|
77
|
+
bueno new my-api --template api
|
|
78
|
+
bueno new my-fullstack --template fullstack --framework react
|
|
79
|
+
bueno new my-app --database postgresql --docker
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
| Option | Default | Description |
|
|
83
|
+
|--------|---------|-------------|
|
|
84
|
+
| `--template` | `default` | Project template (`default`, `minimal`, `fullstack`, `api`) |
|
|
85
|
+
| `--framework` | `react` | Frontend framework (`react`, `vue`, `svelte`, `solid`) |
|
|
86
|
+
| `--database` | `sqlite` | Database type (`sqlite`, `postgresql`, `mysql`) |
|
|
87
|
+
| `--docker` | `false` | Generate Docker configuration |
|
|
88
|
+
| `--deploy` | - | Deployment target (`render`, `fly`, `railway`) |
|
|
89
|
+
| `--skip-install` | `false` | Skip dependency installation |
|
|
90
|
+
| `--skip-git` | `false` | Skip git initialization |
|
|
91
|
+
| `--yes` | `false` | Use default options |
|
|
92
|
+
|
|
93
|
+
### `bueno dev`
|
|
94
|
+
|
|
95
|
+
Start the development server with Hot Module Replacement (HMR).
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
bueno dev
|
|
99
|
+
bueno dev --port 4000 --host 0.0.0.0
|
|
100
|
+
bueno dev --no-hmr --open
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
| Option | Default | Description |
|
|
104
|
+
|--------|---------|-------------|
|
|
105
|
+
| `-p, --port` | `3000` | Server port |
|
|
106
|
+
| `-H, --host` | `localhost` | Server host |
|
|
107
|
+
| `--no-hmr` | `false` | Disable Hot Module Replacement |
|
|
108
|
+
| `--no-watch` | `false` | Disable file watching |
|
|
109
|
+
| `-o, --open` | `false` | Open browser automatically |
|
|
110
|
+
| `-c, --config` | `bueno.config.ts` | Configuration file path |
|
|
111
|
+
|
|
112
|
+
### `bueno build`
|
|
113
|
+
|
|
114
|
+
Build your application for production.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
bueno build
|
|
118
|
+
bueno build --target node --outdir ./dist
|
|
119
|
+
bueno build --compile --cross-compile
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
| Option | Default | Description |
|
|
123
|
+
|--------|---------|-------------|
|
|
124
|
+
| `-t, --target` | `bun` | Build target (`bun`, `node`, `standalone`) |
|
|
125
|
+
| `-o, --outdir` | `./dist` | Output directory |
|
|
126
|
+
| `--no-minify` | `false` | Disable minification |
|
|
127
|
+
| `--sourcemap` | `false` | Generate source maps |
|
|
128
|
+
| `--analyze` | `false` | Analyze bundle size |
|
|
129
|
+
| `--compile` | `false` | Compile to executable |
|
|
130
|
+
| `--cross-compile` | `false` | Cross-compile for other platforms |
|
|
131
|
+
| `--executable-name` | `app` | Executable name |
|
|
132
|
+
|
|
133
|
+
### `bueno start`
|
|
134
|
+
|
|
135
|
+
Start the production server.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
bueno start
|
|
139
|
+
bueno start --port 8080 --workers 4
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
| Option | Default | Description |
|
|
143
|
+
|--------|---------|-------------|
|
|
144
|
+
| `-p, --port` | `3000` | Server port |
|
|
145
|
+
| `-H, --host` | `0.0.0.0` | Server host |
|
|
146
|
+
| `-w, --workers` | `1` | Number of worker threads |
|
|
147
|
+
| `-c, --config` | `bueno.config.ts` | Configuration file path |
|
|
148
|
+
|
|
149
|
+
### `bueno generate <type> <name>`
|
|
150
|
+
|
|
151
|
+
Generate code artifacts (alias: `g`).
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
bueno generate controller UserController
|
|
155
|
+
bueno g service AuthService --module auth
|
|
156
|
+
bueno g dto CreateUserDTO --dry-run
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
| Type | Description |
|
|
160
|
+
|------|-------------|
|
|
161
|
+
| `controller` | HTTP controller |
|
|
162
|
+
| `service` | Injectable service |
|
|
163
|
+
| `module` | Feature module |
|
|
164
|
+
| `guard` | Authentication/authorization guard |
|
|
165
|
+
| `interceptor` | Request/response interceptor |
|
|
166
|
+
| `pipe` | Validation/transformation pipe |
|
|
167
|
+
| `filter` | Exception filter |
|
|
168
|
+
| `dto` | Data Transfer Object |
|
|
169
|
+
| `middleware` | Custom middleware |
|
|
170
|
+
| `migration` | Database migration |
|
|
171
|
+
|
|
172
|
+
| Option | Default | Description |
|
|
173
|
+
|--------|---------|-------------|
|
|
174
|
+
| `-m, --module` | - | Parent module for the artifact |
|
|
175
|
+
| `--path` | - | Custom output path |
|
|
176
|
+
| `--dry-run` | `false` | Preview without writing |
|
|
177
|
+
| `--force` | `false` | Overwrite existing files |
|
|
178
|
+
|
|
179
|
+
### `bueno migration <action>`
|
|
180
|
+
|
|
181
|
+
Manage database migrations.
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
bueno migration create add_users_table
|
|
185
|
+
bueno migration up
|
|
186
|
+
bueno migration down --steps 2
|
|
187
|
+
bueno migration reset
|
|
188
|
+
bueno migration status
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
| Action | Description |
|
|
192
|
+
|--------|-------------|
|
|
193
|
+
| `create <name>` | Create a new migration |
|
|
194
|
+
| `up` | Run pending migrations |
|
|
195
|
+
| `down` | Rollback migrations |
|
|
196
|
+
| `reset` | Reset database and re-run all migrations |
|
|
197
|
+
| `refresh` | Reset and re-seed database |
|
|
198
|
+
| `status` | Show migration status |
|
|
199
|
+
|
|
200
|
+
| Option | Default | Description |
|
|
201
|
+
|--------|---------|-------------|
|
|
202
|
+
| `-n, --steps` | `1` | Number of migrations to rollback |
|
|
203
|
+
| `--dry-run` | `false` | Preview without executing |
|
|
204
|
+
|
|
205
|
+
### `bueno help`
|
|
206
|
+
|
|
207
|
+
Display help information.
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
bueno help
|
|
211
|
+
bueno help dev
|
|
212
|
+
bueno generate --help
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Global Options
|
|
216
|
+
|
|
217
|
+
| Option | Description |
|
|
218
|
+
|--------|-------------|
|
|
219
|
+
| `--help, -h` | Show help |
|
|
220
|
+
| `--version, -v` | Show version |
|
|
221
|
+
| `--verbose` | Enable verbose output |
|
|
222
|
+
| `--quiet` | Suppress output |
|
|
223
|
+
| `--no-color` | Disable colored output |
|
|
224
|
+
|
|
225
|
+
## Core Features
|
|
226
|
+
|
|
227
|
+
### HTTP & Routing
|
|
228
|
+
|
|
229
|
+
Bueno provides a powerful and intuitive routing system with full HTTP method support.
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
import { createServer, Router } from '@buenojs/bueno';
|
|
233
|
+
|
|
234
|
+
const router = new Router();
|
|
235
|
+
|
|
236
|
+
// All HTTP methods
|
|
237
|
+
router.get('/users', getUsers);
|
|
238
|
+
router.post('/users', createUser);
|
|
239
|
+
router.put('/users/:id', updateUser);
|
|
240
|
+
router.patch('/users/:id', patchUser);
|
|
241
|
+
router.delete('/users/:id', deleteUser);
|
|
242
|
+
|
|
243
|
+
// Path parameters
|
|
244
|
+
router.get('/users/:id', (ctx) => {
|
|
245
|
+
const { id } = ctx.params;
|
|
246
|
+
return ctx.json({ userId: id });
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Query parameters
|
|
250
|
+
router.get('/search', (ctx) => {
|
|
251
|
+
const { q, page, limit } = ctx.query;
|
|
252
|
+
return ctx.json({ query: q, page, limit });
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Wildcard routes
|
|
256
|
+
router.get('/files/*', (ctx) => {
|
|
257
|
+
const path = ctx.params['*'];
|
|
258
|
+
return ctx.json({ filePath: path });
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// Route groups
|
|
262
|
+
router.group('/api/v1', (api) => {
|
|
263
|
+
api.get('/users', getUsers);
|
|
264
|
+
api.post('/users', createUser);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const server = createServer();
|
|
268
|
+
server.router = router;
|
|
269
|
+
server.listen(3000);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Dependency Injection
|
|
273
|
+
|
|
274
|
+
Built-in IoC container inspired by NestJS for clean, testable code.
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
import { Container, createToken, Injectable, Inject } from '@buenojs/bueno';
|
|
278
|
+
|
|
279
|
+
// Create tokens
|
|
280
|
+
const ILogger = createToken<Logger>('Logger');
|
|
281
|
+
const IUserRepository = createToken<UserRepository>('UserRepository');
|
|
282
|
+
|
|
283
|
+
// Define injectable services
|
|
284
|
+
@Injectable()
|
|
285
|
+
class UserRepository {
|
|
286
|
+
constructor(@Inject(ILogger) private logger: Logger) {}
|
|
287
|
+
|
|
288
|
+
async findById(id: string) {
|
|
289
|
+
this.logger.debug(`Finding user ${id}`);
|
|
290
|
+
// ...
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Register and resolve
|
|
295
|
+
const container = new Container();
|
|
296
|
+
container.register(ILogger, ConsoleLogger);
|
|
297
|
+
container.register(IUserRepository, UserRepository);
|
|
298
|
+
|
|
299
|
+
const repo = container.resolve(IUserRepository);
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Middleware
|
|
303
|
+
|
|
304
|
+
Comprehensive middleware system with built-in utilities and custom middleware support.
|
|
305
|
+
|
|
306
|
+
#### Built-in Middleware
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
import {
|
|
310
|
+
logger,
|
|
311
|
+
cors,
|
|
312
|
+
requestId,
|
|
313
|
+
timing,
|
|
314
|
+
securityHeaders,
|
|
315
|
+
rateLimit,
|
|
316
|
+
compression
|
|
317
|
+
} from '@buenojs/bueno/middleware';
|
|
318
|
+
|
|
319
|
+
const server = createServer();
|
|
320
|
+
|
|
321
|
+
// Add middleware
|
|
322
|
+
server.use(logger());
|
|
323
|
+
server.use(cors({ origin: ['https://example.com'] }));
|
|
324
|
+
server.use(requestId());
|
|
325
|
+
server.use(timing());
|
|
326
|
+
server.use(securityHeaders());
|
|
327
|
+
server.use(rateLimit({ windowMs: 60000, max: 100 }));
|
|
328
|
+
server.use(compression());
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
#### Custom Middleware
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
import { compose, createPipeline } from '@buenojs/bueno/middleware';
|
|
335
|
+
|
|
336
|
+
// Compose multiple middleware
|
|
337
|
+
const apiMiddleware = compose([
|
|
338
|
+
authMiddleware,
|
|
339
|
+
rateLimitMiddleware,
|
|
340
|
+
loggingMiddleware
|
|
341
|
+
]);
|
|
342
|
+
|
|
343
|
+
// Create custom pipeline
|
|
344
|
+
const pipeline = createPipeline()
|
|
345
|
+
.use(authMiddleware)
|
|
346
|
+
.use(validationMiddleware)
|
|
347
|
+
.use(handler);
|
|
348
|
+
|
|
349
|
+
server.use('/api', apiMiddleware);
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Modules System
|
|
353
|
+
|
|
354
|
+
NestJS-inspired modular architecture with decorators.
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
import { Module, Controller, Injectable, Get, Post, Body } from '@buenojs/bueno/modules';
|
|
358
|
+
|
|
359
|
+
@Injectable()
|
|
360
|
+
class UserService {
|
|
361
|
+
private users: User[] = [];
|
|
362
|
+
|
|
363
|
+
findAll() {
|
|
364
|
+
return this.users;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
create(data: CreateUserDTO) {
|
|
368
|
+
const user = { id: crypto.randomUUID(), ...data };
|
|
369
|
+
this.users.push(user);
|
|
370
|
+
return user;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
@Controller('/users')
|
|
375
|
+
class UserController {
|
|
376
|
+
constructor(private userService: UserService) {}
|
|
377
|
+
|
|
378
|
+
@Get()
|
|
379
|
+
findAll() {
|
|
380
|
+
return this.userService.findAll();
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
@Post()
|
|
384
|
+
create(@Body() data: CreateUserDTO) {
|
|
385
|
+
return this.userService.create(data);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
@Module({
|
|
390
|
+
controllers: [UserController],
|
|
391
|
+
providers: [UserService],
|
|
392
|
+
})
|
|
393
|
+
class UserModule {}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Database
|
|
397
|
+
|
|
398
|
+
Multi-database support with migrations and schema builder.
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
import { Database, createConnection, SchemaBuilder } from '@buenojs/bueno/database';
|
|
402
|
+
|
|
403
|
+
// Create connection
|
|
404
|
+
const db = createConnection({
|
|
405
|
+
type: 'postgresql', // 'sqlite' | 'mysql' | 'postgresql'
|
|
406
|
+
host: 'localhost',
|
|
407
|
+
port: 5432,
|
|
408
|
+
database: 'myapp',
|
|
409
|
+
username: 'user',
|
|
410
|
+
password: 'pass',
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
// Query builder
|
|
414
|
+
const users = await db.table('users')
|
|
415
|
+
.where('active', true)
|
|
416
|
+
.orderBy('created_at', 'desc')
|
|
417
|
+
.limit(10)
|
|
418
|
+
.get();
|
|
419
|
+
|
|
420
|
+
// Schema builder
|
|
421
|
+
const schema = new SchemaBuilder(db);
|
|
422
|
+
await schema.createTable('users', (table) => {
|
|
423
|
+
table.uuid('id').primary();
|
|
424
|
+
table.string('email').unique().notNullable();
|
|
425
|
+
table.string('name').notNullable();
|
|
426
|
+
table.timestamp('created_at').default('now()');
|
|
427
|
+
table.index(['email', 'name']);
|
|
428
|
+
});
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### Validation
|
|
432
|
+
|
|
433
|
+
First-class support for popular validation libraries.
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
import { validate } from '@buenojs/bueno/validation';
|
|
437
|
+
import { z } from 'zod'; // Zod
|
|
438
|
+
import * as v from 'valibot'; // Valibot
|
|
439
|
+
import { type } from 'arktype'; // ArkType
|
|
440
|
+
|
|
441
|
+
// Zod schema
|
|
442
|
+
const UserSchema = z.object({
|
|
443
|
+
name: z.string().min(2),
|
|
444
|
+
email: z.string().email(),
|
|
445
|
+
age: z.number().int().positive().optional(),
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
// Validate in route
|
|
449
|
+
router.post('/users', async (ctx) => {
|
|
450
|
+
const body = await ctx.body();
|
|
451
|
+
const user = validate(body, UserSchema);
|
|
452
|
+
// user is fully typed!
|
|
453
|
+
});
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Security
|
|
457
|
+
|
|
458
|
+
Comprehensive security features out of the box.
|
|
459
|
+
|
|
460
|
+
```typescript
|
|
461
|
+
import {
|
|
462
|
+
hashPassword,
|
|
463
|
+
verifyPassword,
|
|
464
|
+
createJWT,
|
|
465
|
+
verifyJWT,
|
|
466
|
+
csrf,
|
|
467
|
+
auth,
|
|
468
|
+
rbac,
|
|
469
|
+
apiKey
|
|
470
|
+
} from '@buenojs/bueno/security';
|
|
471
|
+
|
|
472
|
+
// Password hashing
|
|
473
|
+
const hashedPassword = await hashPassword('user-password');
|
|
474
|
+
const isValid = await verifyPassword(hashedPassword, 'user-password');
|
|
475
|
+
|
|
476
|
+
// JWT
|
|
477
|
+
const token = createJWT({ userId: '123' }, { expiresIn: '1h' });
|
|
478
|
+
const payload = verifyJWT(token);
|
|
479
|
+
|
|
480
|
+
// CSRF protection
|
|
481
|
+
server.use(csrf());
|
|
482
|
+
|
|
483
|
+
// Auth middleware
|
|
484
|
+
server.use(auth({
|
|
485
|
+
strategy: 'jwt',
|
|
486
|
+
secret: process.env.JWT_SECRET
|
|
487
|
+
}));
|
|
488
|
+
|
|
489
|
+
// RBAC
|
|
490
|
+
server.use(rbac({
|
|
491
|
+
roles: ['admin', 'user', 'guest'],
|
|
492
|
+
permissions: {
|
|
493
|
+
admin: ['*'],
|
|
494
|
+
user: ['read', 'write'],
|
|
495
|
+
guest: ['read']
|
|
496
|
+
}
|
|
497
|
+
}));
|
|
498
|
+
|
|
499
|
+
// API Key middleware
|
|
500
|
+
server.use('/api', apiKey({
|
|
501
|
+
header: 'X-API-Key',
|
|
502
|
+
validate: async (key) => await findApiKey(key)
|
|
503
|
+
}));
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### RPC Client
|
|
507
|
+
|
|
508
|
+
Type-safe API client generation for seamless frontend-backend communication.
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
// server/routes.ts
|
|
512
|
+
import { defineRoutes } from '@buenojs/bueno/rpc';
|
|
513
|
+
|
|
514
|
+
export const routes = defineRoutes((r) => ({
|
|
515
|
+
getUsers: r.get('/users').response<User[]>(),
|
|
516
|
+
getUser: r.get('/users/:id').response<User>(),
|
|
517
|
+
createUser: r.post('/users').body<CreateUserDTO>().response<User>(),
|
|
518
|
+
}));
|
|
519
|
+
|
|
520
|
+
// client/api.ts
|
|
521
|
+
import { createClient } from '@buenojs/bueno/rpc';
|
|
522
|
+
import { routes } from '../shared/routes';
|
|
523
|
+
|
|
524
|
+
const api = createClient('http://localhost:3000', routes);
|
|
525
|
+
|
|
526
|
+
// Fully typed!
|
|
527
|
+
const users = await api.getUsers();
|
|
528
|
+
const user = await api.getUser({ id: '123' });
|
|
529
|
+
const newUser = await api.createUser({ name: 'John', email: 'john@example.com' });
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### Caching & Sessions
|
|
533
|
+
|
|
534
|
+
Redis-backed caching and session management.
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
import { Cache, SessionStore, createRedisClient } from '@buenojs/bueno/cache';
|
|
538
|
+
|
|
539
|
+
// Redis cache
|
|
540
|
+
const redis = createRedisClient({ url: 'redis://localhost:6379' });
|
|
541
|
+
const cache = new Cache(redis);
|
|
542
|
+
|
|
543
|
+
await cache.set('user:123', userData, { ttl: 3600 });
|
|
544
|
+
const user = await cache.get<User>('user:123');
|
|
545
|
+
|
|
546
|
+
// Session store
|
|
547
|
+
const sessions = new SessionStore(redis);
|
|
548
|
+
const session = await sessions.create({ userId: '123' });
|
|
549
|
+
const data = await sessions.get(session.id);
|
|
550
|
+
await sessions.destroy(session.id);
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Distributed Locking
|
|
554
|
+
|
|
555
|
+
Coordinate distributed operations with Redis or in-memory locks.
|
|
556
|
+
|
|
557
|
+
```typescript
|
|
558
|
+
import { RedisLock, MemoryLock } from '@buenojs/bueno/lock';
|
|
559
|
+
|
|
560
|
+
// Redis-based distributed lock
|
|
561
|
+
const lock = new RedisLock(redis);
|
|
562
|
+
await lock.acquire('resource:123', { ttl: 5000 });
|
|
563
|
+
try {
|
|
564
|
+
// Critical section
|
|
565
|
+
await processResource();
|
|
566
|
+
} finally {
|
|
567
|
+
await lock.release('resource:123');
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// In-memory lock for single-instance apps
|
|
571
|
+
const memoryLock = new MemoryLock();
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### Static Site Generation (SSG)
|
|
575
|
+
|
|
576
|
+
Generate static sites with markdown support.
|
|
577
|
+
|
|
578
|
+
```typescript
|
|
579
|
+
import { SSG, markdownParser } from '@buenojs/bueno/ssg';
|
|
580
|
+
|
|
581
|
+
const ssg = new SSG({
|
|
582
|
+
contentDir: './content',
|
|
583
|
+
outputDir: './dist',
|
|
584
|
+
templates: './templates',
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
// Parse markdown
|
|
588
|
+
ssg.parser.use(markdownParser());
|
|
589
|
+
|
|
590
|
+
// Generate static pages
|
|
591
|
+
await ssg.build();
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### Storage
|
|
595
|
+
|
|
596
|
+
S3-compatible storage and secrets management.
|
|
597
|
+
|
|
598
|
+
```typescript
|
|
599
|
+
import { Storage, SecretsManager } from '@buenojs/bueno/storage';
|
|
600
|
+
|
|
601
|
+
// S3-compatible storage
|
|
602
|
+
const storage = new Storage({
|
|
603
|
+
provider: 's3',
|
|
604
|
+
bucket: 'my-bucket',
|
|
605
|
+
region: 'us-east-1',
|
|
606
|
+
credentials: {
|
|
607
|
+
accessKeyId: process.env.AWS_ACCESS_KEY,
|
|
608
|
+
secretAccessKey: process.env.AWS_SECRET_KEY,
|
|
609
|
+
},
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
await storage.upload('uploads/file.pdf', fileBuffer);
|
|
613
|
+
const file = await storage.download('uploads/file.pdf');
|
|
614
|
+
|
|
615
|
+
// Secrets management
|
|
616
|
+
const secrets = new SecretsManager({
|
|
617
|
+
provider: 'aws-secrets-manager',
|
|
618
|
+
secretId: 'my-app/secrets',
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
const dbPassword = await secrets.get('DATABASE_PASSWORD');
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
### WebSocket
|
|
625
|
+
|
|
626
|
+
Real-time communication with WebSocket support.
|
|
627
|
+
|
|
628
|
+
```typescript
|
|
629
|
+
import { WebSocketServer, WebSocketClient, PubSub } from '@buenojs/bueno/websocket';
|
|
630
|
+
|
|
631
|
+
// Server
|
|
632
|
+
const wss = new WebSocketServer({ port: 3001 });
|
|
633
|
+
|
|
634
|
+
wss.on('connection', (client) => {
|
|
635
|
+
console.log('Client connected');
|
|
636
|
+
|
|
637
|
+
client.on('message', (data) => {
|
|
638
|
+
// Broadcast to all clients
|
|
639
|
+
wss.broadcast({ type: 'chat', data });
|
|
640
|
+
});
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
// PubSub
|
|
644
|
+
const pubsub = new PubSub(redis);
|
|
645
|
+
pubsub.subscribe('channel:updates', (message) => {
|
|
646
|
+
wss.broadcast(message);
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
// Client
|
|
650
|
+
const ws = new WebSocketClient('ws://localhost:3001');
|
|
651
|
+
ws.on('message', (data) => console.log(data));
|
|
652
|
+
ws.send({ type: 'chat', message: 'Hello!' });
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
### Logging
|
|
656
|
+
|
|
657
|
+
Flexible logging with multiple transports.
|
|
658
|
+
|
|
659
|
+
```typescript
|
|
660
|
+
import { Logger, ConsoleTransport, FileTransport } from '@buenojs/bueno/logger';
|
|
661
|
+
|
|
662
|
+
const logger = new Logger({
|
|
663
|
+
level: 'debug',
|
|
664
|
+
transports: [
|
|
665
|
+
new ConsoleTransport({ colorize: true }),
|
|
666
|
+
new FileTransport({ path: './logs/app.log' }),
|
|
667
|
+
],
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
logger.info('Server started');
|
|
671
|
+
logger.error('Database connection failed', { error: err });
|
|
672
|
+
logger.debug('Request received', { method, path });
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
### Health Checks
|
|
676
|
+
|
|
677
|
+
Built-in health check endpoints for monitoring.
|
|
678
|
+
|
|
679
|
+
```typescript
|
|
680
|
+
import { HealthChecker, DatabaseCheck, CacheCheck, TCPCheck, HTTPCheck } from '@buenojs/bueno/health';
|
|
681
|
+
|
|
682
|
+
const health = new HealthChecker();
|
|
683
|
+
|
|
684
|
+
health.addCheck('database', new DatabaseCheck(db));
|
|
685
|
+
health.addCheck('redis', new CacheCheck(redis));
|
|
686
|
+
health.addCheck('api', new HTTPCheck('https://api.example.com/health'));
|
|
687
|
+
health.addCheck('smtp', new TCPCheck('smtp.example.com', 25));
|
|
688
|
+
|
|
689
|
+
// Health endpoint
|
|
690
|
+
router.get('/health', async (ctx) => {
|
|
691
|
+
const result = await health.check();
|
|
692
|
+
return ctx.json(result, result.healthy ? 200 : 503);
|
|
693
|
+
});
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
### Testing
|
|
697
|
+
|
|
698
|
+
Comprehensive testing utilities for unit and integration tests.
|
|
699
|
+
|
|
700
|
+
```typescript
|
|
701
|
+
import { AppTester, mock, assertions } from '@buenojs/bueno/testing';
|
|
702
|
+
import { describe, it, expect, beforeEach } from 'bun:test';
|
|
703
|
+
|
|
704
|
+
describe('UserController', () => {
|
|
705
|
+
let tester: AppTester;
|
|
706
|
+
|
|
707
|
+
beforeEach(async () => {
|
|
708
|
+
tester = await AppTester.create(AppModule);
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
it('should create user', async () => {
|
|
712
|
+
const response = await tester
|
|
713
|
+
.post('/users')
|
|
714
|
+
.body({ name: 'John', email: 'john@example.com' })
|
|
715
|
+
.execute();
|
|
716
|
+
|
|
717
|
+
expect(response.status).toBe(201);
|
|
718
|
+
expect(response.json()).toMatchObject({
|
|
719
|
+
name: 'John',
|
|
720
|
+
email: 'john@example.com'
|
|
721
|
+
});
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
it('should validate input', async () => {
|
|
725
|
+
const response = await tester
|
|
726
|
+
.post('/users')
|
|
727
|
+
.body({ name: '' }) // Invalid
|
|
728
|
+
.execute();
|
|
729
|
+
|
|
730
|
+
expect(response.status).toBe(400);
|
|
731
|
+
});
|
|
732
|
+
});
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
## Frontend Support
|
|
736
|
+
|
|
737
|
+
Bueno provides first-class support for modern frontend frameworks with SSR, SSG, and Island Architecture.
|
|
738
|
+
|
|
739
|
+
### Supported Frameworks
|
|
740
|
+
|
|
741
|
+
- **React** - Full support with SSR and hydration
|
|
742
|
+
- **Vue** - Server-side rendering with Vue 3
|
|
743
|
+
- **Svelte** - SvelteKit-like experience
|
|
744
|
+
- **Solid** - SolidJS with SSR
|
|
745
|
+
|
|
746
|
+
### Features
|
|
747
|
+
|
|
748
|
+
| Feature | Description |
|
|
749
|
+
|---------|-------------|
|
|
750
|
+
| **SSR** | Server-side rendering for SEO and performance |
|
|
751
|
+
| **SSG** | Static site generation at build time |
|
|
752
|
+
| **ISR** | Incremental Static Regeneration |
|
|
753
|
+
| **Islands** | Interactive components with partial hydration |
|
|
754
|
+
| **File-based Routing** | Automatic route generation from file structure |
|
|
755
|
+
| **HMR** | Hot module replacement for instant updates |
|
|
756
|
+
|
|
757
|
+
### Example
|
|
758
|
+
|
|
759
|
+
```typescript
|
|
760
|
+
// client/pages/index.tsx
|
|
761
|
+
import { definePage } from '@buenojs/bueno/frontend';
|
|
762
|
+
|
|
763
|
+
export default definePage({
|
|
764
|
+
async loader() {
|
|
765
|
+
const posts = await fetch('/api/posts').then(r => r.json());
|
|
766
|
+
return { posts };
|
|
767
|
+
},
|
|
768
|
+
|
|
769
|
+
render({ posts }) {
|
|
770
|
+
return (
|
|
771
|
+
<main>
|
|
772
|
+
<h1>Blog Posts</h1>
|
|
773
|
+
{posts.map(post => (
|
|
774
|
+
<article key={post.id}>
|
|
775
|
+
<h2>{post.title}</h2>
|
|
776
|
+
<p>{post.excerpt}</p>
|
|
777
|
+
</article>
|
|
778
|
+
))}
|
|
779
|
+
</main>
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
## Project Structure
|
|
786
|
+
|
|
787
|
+
```
|
|
788
|
+
my-bueno-app/
|
|
789
|
+
├── server/
|
|
790
|
+
│ ├── main.ts # Application entry point
|
|
791
|
+
│ ├── modules/ # Feature modules
|
|
792
|
+
│ │ ├── user/
|
|
793
|
+
│ │ │ ├── user.module.ts
|
|
794
|
+
│ │ │ ├── user.controller.ts
|
|
795
|
+
│ │ │ ├── user.service.ts
|
|
796
|
+
│ │ │ └── user.dto.ts
|
|
797
|
+
│ │ └── auth/
|
|
798
|
+
│ │ ├── auth.module.ts
|
|
799
|
+
│ │ ├── auth.controller.ts
|
|
800
|
+
│ │ └── auth.guard.ts
|
|
801
|
+
│ ├── common/ # Shared utilities
|
|
802
|
+
│ │ ├── middleware/
|
|
803
|
+
│ │ ├── decorators/
|
|
804
|
+
│ │ └── utils/
|
|
805
|
+
│ ├── config/ # Configuration
|
|
806
|
+
│ │ ├── index.ts
|
|
807
|
+
│ │ └── database.ts
|
|
808
|
+
│ └── database/ # Database files
|
|
809
|
+
│ ├── migrations/
|
|
810
|
+
│ ├── seeds/
|
|
811
|
+
│ └── schema.ts
|
|
812
|
+
├── client/ # Frontend application
|
|
813
|
+
│ ├── pages/ # File-based routes
|
|
814
|
+
│ ├── components/ # UI components
|
|
815
|
+
│ ├── layouts/ # Page layouts
|
|
816
|
+
│ └── main.tsx # Entry point
|
|
817
|
+
├── shared/ # Shared types and utilities
|
|
818
|
+
│ ├── types/
|
|
819
|
+
│ └── routes.ts
|
|
820
|
+
├── tests/ # Test files
|
|
821
|
+
│ ├── unit/
|
|
822
|
+
│ └── integration/
|
|
823
|
+
├── bueno.config.ts # Framework configuration
|
|
824
|
+
├── package.json
|
|
825
|
+
└── tsconfig.json
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
## NPM Scripts
|
|
829
|
+
|
|
830
|
+
| Script | Description |
|
|
831
|
+
|--------|-------------|
|
|
832
|
+
| `bun run dev` | Start development server with watch mode |
|
|
833
|
+
| `bun test` | Run test suite |
|
|
834
|
+
| `bun test --watch` | Run tests in watch mode |
|
|
835
|
+
| `bun test --coverage` | Run tests with coverage |
|
|
836
|
+
| `bun build` | Build for production |
|
|
837
|
+
| `bun run typecheck` | TypeScript type checking |
|
|
838
|
+
|
|
839
|
+
## Framework Comparison
|
|
840
|
+
|
|
841
|
+
Bueno combines the best ideas from popular frameworks while being optimized for Bun:
|
|
842
|
+
|
|
843
|
+
| Feature | Bueno | Hono | Express | NestJS | Next.js |
|
|
844
|
+
|---------|-------|------|---------|--------|---------|
|
|
845
|
+
| **Runtime** | Bun | Multi | Node | Node | Node |
|
|
846
|
+
| **Router** | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
847
|
+
| **DI Container** | ✅ | ❌ | ❌ | ✅ | ❌ |
|
|
848
|
+
| **Decorators** | ✅ | ❌ | ❌ | ✅ | ❌ |
|
|
849
|
+
| **SSR** | ✅ | ❌ | ❌ | ❌ | ✅ |
|
|
850
|
+
| **SSG** | ✅ | ❌ | ❌ | ❌ | ✅ |
|
|
851
|
+
| **Database** | ✅ | ❌ | ❌ | ✅ | ❌ |
|
|
852
|
+
| **WebSocket** | ✅ | ✅ | Plugin | ✅ | ❌ |
|
|
853
|
+
| **Validation** | ✅ | ✅ | Plugin | ✅ | ❌ |
|
|
854
|
+
| **CLI** | ✅ | ❌ | ❌ | ✅ | ✅ |
|
|
855
|
+
|
|
856
|
+
**Migration Notes:**
|
|
857
|
+
- **From Express**: Similar middleware patterns, but with native async/await and TypeScript
|
|
858
|
+
- **From Hono**: Compatible routing API with additional DI and modules system
|
|
859
|
+
- **From NestJS**: Familiar decorators and module structure, but Bun-native performance
|
|
860
|
+
- **From Next.js**: Similar file-based routing and SSR capabilities, but backend-first approach
|
|
861
|
+
|
|
862
|
+
## Contributing
|
|
863
|
+
|
|
864
|
+
We welcome contributions! Please see our [Contributing Guide](https://github.com/buenojs/bueno/blob/main/CONTRIBUTING.md) for details.
|
|
865
|
+
|
|
866
|
+
### Development Setup
|
|
867
|
+
|
|
868
|
+
```bash
|
|
869
|
+
# Clone the repository
|
|
870
|
+
git clone https://github.com/buenojs/bueno.git
|
|
871
|
+
cd bueno
|
|
872
|
+
|
|
873
|
+
# Install dependencies
|
|
874
|
+
bun install
|
|
875
|
+
|
|
876
|
+
# Run tests
|
|
877
|
+
bun test
|
|
878
|
+
|
|
879
|
+
# Start development
|
|
880
|
+
bun dev
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
## Links
|
|
884
|
+
|
|
885
|
+
- **Documentation**: [https://buenojs.dev](https://buenojs.dev)
|
|
886
|
+
- **GitHub**: [https://github.com/buenojs/bueno](https://github.com/buenojs/bueno)
|
|
887
|
+
- **Issues**: [https://github.com/buenojs/bueno/issues](https://github.com/buenojs/bueno/issues)
|
|
888
|
+
- **npm**: [https://www.npmjs.com/package/@buenojs/bueno](https://www.npmjs.com/package/@buenojs/bueno)
|
|
889
|
+
|
|
890
|
+
## License
|
|
891
|
+
|
|
892
|
+
MIT © [Sivaraj D](mailto:sivarajd@gmail.com)
|