bxo 0.0.5-dev.7 โ†’ 0.0.5-dev.71

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 CHANGED
@@ -1,579 +1,225 @@
1
- # ๐ŸฆŠ BXO - A Type-Safe Web Framework for Bun
1
+ # bxo
2
2
 
3
- BXO is a fast, lightweight, and fully type-safe web framework built specifically for Bun runtime. Inspired by Elysia, it provides excellent developer experience with automatic type inference, Zod validation, and a powerful plugin system.
3
+ A fast, lightweight web framework for Bun with built-in Zod validation and lifecycle hooks.
4
4
 
5
- ## โœจ Features
5
+ ## Features
6
6
 
7
- - ๐Ÿš€ **Built for Bun** - Leverages Bun's native HTTP server for maximum performance
8
- - ๐Ÿ”’ **Type-Safe** - Full TypeScript support with automatic type inference
9
- - ๐Ÿ“‹ **Zod Validation** - Built-in request/response validation using Zod schemas
10
- - ๐Ÿ”Œ **Plugin System** - Extensible architecture with lifecycle hooks
11
- - ๐ŸŽฃ **Lifecycle Hooks** - Complete control over server and request/response lifecycle
12
- - ๐Ÿ”„ **Hot Reload** - Automatic server restart on file changes during development
13
- - ๐ŸŽฎ **Server Management** - Programmatic start, stop, and restart capabilities
14
- - ๐Ÿ“Š **Status Monitoring** - Built-in server status and runtime statistics
15
- - ๐Ÿ“ฆ **Zero Dependencies** - Only depends on Zod for validation
16
- - โšก **Fast** - Minimal overhead with efficient routing
7
+ - **Type-safe routing** with Zod schema validation
8
+ - **Lifecycle hooks** for middleware and plugins
9
+ - **Plugin system** for extending functionality
10
+ - **Built-in CORS support** via plugin
11
+ - **Fast performance** leveraging Bun's native HTTP server
17
12
 
18
- ## ๐Ÿš€ Quick Start
19
-
20
- ### Installation
13
+ ## Installation
21
14
 
22
15
  ```bash
23
- bun add zod
16
+ bun install
24
17
  ```
25
18
 
26
- ### Basic Usage
19
+ ## Quick Start
27
20
 
28
21
  ```typescript
29
- import BXO, { z } from './index';
30
-
31
- const app = new BXO()
32
- .get('/', async (ctx) => {
33
- return { message: 'Hello, BXO!' };
34
- })
35
- .start(3000);
36
- ```
22
+ import BXO from "./src/index";
23
+ import { cors } from "./plugins";
37
24
 
38
- ## ๐Ÿ“š Documentation
25
+ const app = new BXO();
39
26
 
40
- ### HTTP Handlers
27
+ // Use CORS plugin
28
+ app.use(cors());
41
29
 
42
- BXO supports all standard HTTP methods with fluent chaining:
30
+ // Define routes
31
+ app.get("/", (ctx) => ctx.json({ message: "Hello World!" }));
43
32
 
44
- ```typescript
45
- const app = new BXO()
46
- // Simple handler
47
- .get('/simple', async (ctx) => {
48
- return { message: 'Hello World' };
49
- })
50
-
51
- // With validation
52
- .post('/users', async (ctx) => {
53
- // ctx.body is fully typed
54
- return { created: ctx.body };
55
- }, {
56
- body: z.object({
57
- name: z.string(),
58
- email: z.string().email()
59
- })
60
- })
61
-
62
- // Path parameters
63
- .get('/users/:id', async (ctx) => {
64
- // ctx.params.id is typed as UUID string
65
- return { user: { id: ctx.params.id } };
66
- }, {
67
- params: z.object({
68
- id: z.string().uuid()
69
- }),
70
- query: z.object({
71
- include: z.string().optional()
72
- })
73
- })
74
-
75
- // All HTTP methods supported
76
- .put('/users/:id', handler)
77
- .delete('/users/:id', handler)
78
- .patch('/users/:id', handler);
33
+ app.start();
79
34
  ```
80
35
 
81
- ### Context Object
82
-
83
- The context object (`ctx`) provides access to request data and response configuration:
84
-
85
- ```typescript
86
- interface Context<TConfig> {
87
- params: InferredParamsType; // Path parameters
88
- query: InferredQueryType; // Query string parameters
89
- body: InferredBodyType; // Request body
90
- headers: InferredHeadersType; // Request headers
91
- request: Request; // Original Request object
92
- set: { // Response configuration
93
- status?: number;
94
- headers?: Record<string, string>;
95
- };
96
- user?: any; // Added by auth plugin
97
- [key: string]: any; // Extended by plugins
98
- }
99
- ```
36
+ ## Lifecycle Hooks
100
37
 
101
- ### Validation Configuration
38
+ BXO provides powerful lifecycle hooks that allow you to intercept and modify requests and responses at different stages:
102
39
 
103
- Each route can specify validation schemas for different parts of the request:
40
+ ### beforeRequest
41
+ Runs before any route processing. Can modify the request or return a response to short-circuit processing.
104
42
 
105
43
  ```typescript
106
- const config = {
107
- params: z.object({ id: z.string().uuid() }),
108
- query: z.object({
109
- page: z.coerce.number().default(1),
110
- limit: z.coerce.number().max(100).default(10)
111
- }),
112
- body: z.object({
113
- name: z.string().min(1),
114
- email: z.string().email()
115
- }),
116
- headers: z.object({
117
- 'content-type': z.literal('application/json')
118
- })
119
- };
120
-
121
- app.post('/api/users/:id', async (ctx) => {
122
- // All properties are fully typed based on schemas
123
- const { id } = ctx.params; // string (UUID)
124
- const { page, limit } = ctx.query; // number, number
125
- const { name, email } = ctx.body; // string, string
126
- }, config);
44
+ app.beforeRequest(async (req) => {
45
+ console.log(`${req.method} ${req.url}`);
46
+ return req; // Continue with request
47
+ });
127
48
  ```
128
49
 
129
- ## ๐Ÿ”Œ Plugin System
130
-
131
- BXO has a powerful plugin system with lifecycle hooks. Plugins are separate modules imported from `./plugins`.
132
-
133
- ### Available Plugins
134
-
135
- #### CORS Plugin
50
+ ### afterRequest
51
+ Runs after route processing but before the response is sent. Can modify the final response.
136
52
 
137
53
  ```typescript
138
- import { cors } from './plugins';
139
-
140
- app.use(cors({
141
- origin: ['http://localhost:3000', 'https://example.com'],
142
- methods: ['GET', 'POST', 'PUT', 'DELETE'],
143
- allowedHeaders: ['Content-Type', 'Authorization'],
144
- credentials: true,
145
- maxAge: 86400
146
- }));
54
+ app.afterRequest(async (req, res) => {
55
+ res.headers.set("X-Response-Time", Date.now().toString());
56
+ return res;
57
+ });
147
58
  ```
148
59
 
149
- #### Logger Plugin
60
+ ### beforeResponse
61
+ Runs after the route handler but before response headers are merged. Useful for modifying response metadata.
150
62
 
151
63
  ```typescript
152
- import { logger } from './plugins';
153
-
154
- app.use(logger({
155
- format: 'simple', // 'simple' | 'detailed' | 'json'
156
- includeBody: false, // Log request/response bodies
157
- includeHeaders: false // Log headers
158
- }));
64
+ app.beforeResponse(async (res) => {
65
+ res.headers.set("X-Custom-Header", "value");
66
+ return res;
67
+ });
159
68
  ```
160
69
 
161
- #### Authentication Plugin
70
+ ### onError
71
+ Runs when an error occurs during request processing. Can return a custom error response.
162
72
 
163
73
  ```typescript
164
- import { auth, createJWT } from './plugins';
165
-
166
- app.use(auth({
167
- type: 'jwt', // 'jwt' | 'bearer' | 'apikey'
168
- secret: 'your-secret-key',
169
- exclude: ['/login', '/health'], // Skip auth for these paths
170
- verify: async (token, ctx) => {
171
- // Custom token verification
172
- return { user: 'data' };
173
- }
174
- }));
175
-
176
- // Create JWT tokens
177
- const token = createJWT(
178
- { userId: 123, role: 'admin' },
179
- 'secret',
180
- 3600 // expires in 1 hour
181
- );
74
+ app.onError(async (error, req) => {
75
+ console.error(`Error: ${error.message}`);
76
+ return new Response("Internal Server Error", { status: 500 });
77
+ });
182
78
  ```
183
79
 
184
- #### Rate Limiting Plugin
80
+ ## Plugins
185
81
 
186
- ```typescript
187
- import { rateLimit } from './plugins';
188
-
189
- app.use(rateLimit({
190
- max: 100, // Max requests
191
- window: 60, // Time window in seconds
192
- exclude: ['/health'], // Skip rate limiting for these paths
193
- keyGenerator: (ctx) => { // Custom key generation
194
- return ctx.request.headers.get('x-api-key') || 'default';
195
- },
196
- message: 'Too many requests',
197
- statusCode: 429
198
- }));
199
- ```
82
+ ### CORS Plugin
200
83
 
201
- ### Creating Custom Plugins
84
+ The CORS plugin provides comprehensive Cross-Origin Resource Sharing support:
202
85
 
203
86
  ```typescript
204
- const customPlugin = {
205
- name: 'custom',
206
- onRequest: async (ctx) => {
207
- console.log('Before request processing');
208
- ctx.startTime = Date.now();
209
- },
210
- onResponse: async (ctx, response) => {
211
- console.log(`Request took ${Date.now() - ctx.startTime}ms`);
212
- return response;
213
- },
214
- onError: async (ctx, error) => {
215
- console.error('Request failed:', error.message);
216
- return { error: 'Custom error response' };
217
- }
218
- };
87
+ import { cors } from "./plugins";
219
88
 
220
- app.use(customPlugin);
89
+ app.use(cors({
90
+ origin: ["http://localhost:3000", "https://myapp.com"],
91
+ methods: ["GET", "POST", "PUT", "DELETE"],
92
+ credentials: true
93
+ }));
221
94
  ```
222
95
 
223
- ## ๐ŸŽฃ Lifecycle Hooks
224
-
225
- BXO provides comprehensive lifecycle hooks with a consistent before/after pattern for both server and request lifecycle:
96
+ ### OpenAPI Plugin
226
97
 
227
- ### Server Lifecycle Hooks
98
+ The OpenAPI plugin automatically generates OpenAPI 3.0 documentation with support for tags, security schemes, and comprehensive route metadata:
228
99
 
229
100
  ```typescript
230
- app
231
- .onBeforeStart(() => {
232
- console.log('๐Ÿ”ง Preparing to start server...');
233
- })
234
- .onAfterStart(() => {
235
- console.log('โœ… Server fully started and ready!');
236
- })
237
- .onBeforeStop(() => {
238
- console.log('๐Ÿ”ง Preparing to stop server...');
239
- })
240
- .onAfterStop(() => {
241
- console.log('โœ… Server fully stopped!');
242
- })
243
- .onBeforeRestart(() => {
244
- console.log('๐Ÿ”ง Preparing to restart server...');
245
- })
246
- .onAfterRestart(() => {
247
- console.log('โœ… Server restart completed!');
248
- });
249
- ```
250
-
251
- ### Request Lifecycle Hooks
101
+ import { openapi } from "./plugins";
252
102
 
253
- ```typescript
254
- app
255
- .onRequest((ctx) => {
256
- console.log(`๐Ÿ“จ ${ctx.request.method} ${ctx.request.url}`);
257
- })
258
- .onResponse((ctx, response) => {
259
- console.log(`๐Ÿ“ค Response sent`);
260
- return response; // Can modify response
261
- })
262
- .onError((ctx, error) => {
263
- console.error(`๐Ÿ’ฅ Error:`, error.message);
264
- return { error: 'Something went wrong' }; // Can provide custom error response
265
- });
103
+ app.use(openapi({
104
+ path: "/docs", // Swagger UI endpoint
105
+ jsonPath: "/openapi.json", // OpenAPI JSON endpoint
106
+ defaultTags: ["API"], // Default tags for routes
107
+ securitySchemes: { // Define security schemes
108
+ bearerAuth: {
109
+ type: "http",
110
+ scheme: "bearer",
111
+ bearerFormat: "JWT",
112
+ description: "JWT token for authentication"
113
+ },
114
+ apiKeyAuth: {
115
+ type: "apiKey",
116
+ in: "header",
117
+ name: "X-API-Key",
118
+ description: "API key for authentication"
119
+ }
120
+ },
121
+ globalSecurity: [ // Global security requirements
122
+ { bearerAuth: [] },
123
+ { apiKeyAuth: [] }
124
+ ],
125
+ openapiConfig: { // Additional OpenAPI config
126
+ info: {
127
+ title: "My API",
128
+ version: "1.0.0",
129
+ description: "API description"
130
+ }
131
+ }
132
+ }));
266
133
  ```
267
134
 
268
- ## ๐Ÿ”„ Hot Reload & Server Management
135
+ #### Route Metadata
269
136
 
270
- BXO includes built-in hot reload and comprehensive server management capabilities:
271
-
272
- ### Hot Reload
137
+ Routes can include detailed metadata for better OpenAPI documentation:
273
138
 
274
139
  ```typescript
275
- const app = new BXO();
276
-
277
- // Enable hot reload - server will restart when files change
278
- app.enableHotReload(['./']); // Watch current directory
279
-
280
- // Hot reload will automatically restart the server when:
281
- // - Any .ts or .js file changes in watched directories
282
- // - Server lifecycle hooks are properly executed during restart
140
+ app.get("/users/:id", (ctx) => {
141
+ const id = ctx.params.id
142
+ return { user: { id, name: "John Doe" } }
143
+ }, {
144
+ detail: {
145
+ tags: ["Users"], // Route tags for grouping
146
+ summary: "Get user by ID", // Operation summary
147
+ description: "Retrieve user details", // Detailed description
148
+ security: [{ bearerAuth: [] }], // Route-specific security
149
+ params: { // Parameter documentation
150
+ id: z.string().describe("User ID")
151
+ }
152
+ }
153
+ })
283
154
  ```
284
155
 
285
- ### Server Management
156
+ #### Supported Metadata Fields
286
157
 
287
- ```typescript
288
- const app = new BXO();
289
-
290
- // Start server
291
- await app.start(3000, 'localhost');
292
-
293
- // Check if server is running
294
- if (app.isServerRunning()) {
295
- console.log('Server is running!');
296
- }
297
-
298
- // Get server information
299
- const info = app.getServerInfo();
300
- console.log(info); // { running: true, hotReload: true, watchedFiles: ['./'] }
301
-
302
- // Restart server programmatically
303
- await app.restart(3000, 'localhost');
158
+ - `tags`: Array of tags for grouping operations
159
+ - `summary`: Short description of the operation
160
+ - `description`: Detailed description of the operation
161
+ - `security`: Security requirements for the route
162
+ - `params`: Path parameter schemas and descriptions
163
+ - `query`: Query parameter schemas
164
+ - `hidden`: Set to `true` to exclude from OpenAPI docs
304
165
 
305
- // Stop server gracefully
306
- await app.stop();
307
-
308
- // Backward compatibility - listen() still works
309
- await app.listen(3000); // Same as app.start(3000)
310
- ```
166
+ ### Creating Custom Plugins
311
167
 
312
- ### Development vs Production
168
+ Plugins are just BXO instances with lifecycle hooks:
313
169
 
314
170
  ```typescript
315
- const app = new BXO();
316
-
317
- if (process.env.NODE_ENV === 'development') {
318
- // Enable hot reload in development
319
- app.enableHotReload(['./src', './routes']);
320
- }
321
-
322
- // Add server management endpoints for development
323
- if (process.env.NODE_ENV === 'development') {
324
- app.post('/dev/restart', async (ctx) => {
325
- setTimeout(() => app.restart(3000), 100);
326
- return { message: 'Server restart initiated' };
327
- });
171
+ function loggingPlugin() {
172
+ const plugin = new BXO();
328
173
 
329
- app.get('/dev/status', async (ctx) => {
330
- return {
331
- ...app.getServerInfo(),
332
- uptime: process.uptime(),
333
- memory: process.memoryUsage()
334
- };
174
+ plugin.beforeRequest(async (req) => {
175
+ console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
176
+ return req;
335
177
  });
336
- }
337
- ```
338
-
339
- ## ๐ŸŒŸ Complete Example
340
-
341
- ```typescript
342
- import BXO, { z } from './index';
343
- import { cors, logger, auth, rateLimit, createJWT } from './plugins';
344
-
345
- const app = new BXO();
346
-
347
- // Enable hot reload for development
348
- app.enableHotReload(['./']);
349
-
350
- // Add plugins
351
- app
352
- .use(logger({ format: 'simple' }))
353
- .use(cors({
354
- origin: ['http://localhost:3000'],
355
- credentials: true
356
- }))
357
- .use(rateLimit({
358
- max: 100,
359
- window: 60,
360
- exclude: ['/health']
361
- }))
362
- .use(auth({
363
- type: 'jwt',
364
- secret: 'your-secret-key',
365
- exclude: ['/', '/login', '/health']
366
- }));
367
-
368
- // Comprehensive lifecycle hooks
369
- app
370
- .onBeforeStart(() => console.log('๐Ÿ”ง Preparing server startup...'))
371
- .onAfterStart(() => console.log('โœ… Server ready!'))
372
- .onBeforeRestart(() => console.log('๐Ÿ”„ Restarting server...'))
373
- .onAfterRestart(() => console.log('โœ… Server restarted!'))
374
- .onError((ctx, error) => ({
375
- error: 'Internal server error',
376
- timestamp: new Date().toISOString()
377
- }));
378
-
379
- // Routes
380
- app
381
- .get('/health', async () => ({
382
- status: 'ok',
383
- timestamp: new Date().toISOString(),
384
- server: app.getServerInfo()
385
- }))
386
-
387
- .post('/login', async (ctx) => {
388
- const { username, password } = ctx.body;
389
-
390
- if (username === 'admin' && password === 'password') {
391
- const token = createJWT(
392
- { username, role: 'admin' },
393
- 'your-secret-key'
394
- );
395
- return { token, user: { username, role: 'admin' } };
396
- }
397
-
398
- ctx.set.status = 401;
399
- return { error: 'Invalid credentials' };
400
- }, {
401
- body: z.object({
402
- username: z.string(),
403
- password: z.string()
404
- })
405
- })
406
-
407
- .get('/users/:id', async (ctx) => {
408
- return {
409
- user: {
410
- id: ctx.params.id,
411
- include: ctx.query.include
412
- }
413
- };
414
- }, {
415
- params: z.object({ id: z.string().uuid() }),
416
- query: z.object({ include: z.string().optional() })
417
- })
418
178
 
419
- .post('/users', async (ctx) => {
420
- return { created: ctx.body };
421
- }, {
422
- body: z.object({
423
- name: z.string(),
424
- email: z.string().email()
425
- })
426
- })
427
-
428
- .get('/protected', async (ctx) => {
429
- // ctx.user available from auth plugin
430
- return {
431
- message: 'Protected resource',
432
- user: ctx.user
433
- };
434
- })
435
-
436
- // Server management endpoints
437
- .post('/restart', async (ctx) => {
438
- setTimeout(() => app.restart(3000), 100);
439
- return { message: 'Server restart initiated' };
440
- })
441
-
442
- .get('/status', async (ctx) => {
443
- return {
444
- ...app.getServerInfo(),
445
- uptime: process.uptime(),
446
- memory: process.memoryUsage()
447
- };
448
- });
179
+ return plugin;
180
+ }
449
181
 
450
- // Start server with hot reload
451
- app.start(3000);
182
+ app.use(loggingPlugin());
452
183
  ```
453
184
 
454
- ## ๐Ÿงช Testing Endpoints
455
-
456
- With the example server running, test these endpoints:
185
+ ## Route Validation
457
186
 
458
- ```bash
459
- # Health check
460
- curl http://localhost:3000/health
461
-
462
- # Login to get token
463
- curl -X POST http://localhost:3000/login \
464
- -H "Content-Type: application/json" \
465
- -d '{"username": "admin", "password": "password"}'
466
-
467
- # Create user
468
- curl -X POST http://localhost:3000/users \
469
- -H "Content-Type: application/json" \
470
- -d '{"name": "John Doe", "email": "john@example.com"}'
471
-
472
- # Get user with validation
473
- curl "http://localhost:3000/users/123e4567-e89b-12d3-a456-426614174000?include=profile"
474
-
475
- # Access protected route (use token from login)
476
- curl http://localhost:3000/protected \
477
- -H "Authorization: Bearer YOUR_JWT_TOKEN"
478
-
479
- # Check server status
480
- curl http://localhost:3000/status
481
-
482
- # Restart server programmatically
483
- curl -X POST http://localhost:3000/restart
484
- ```
485
-
486
- ## ๐Ÿ“– API Reference
487
-
488
- ### BXO Class Methods
489
-
490
- #### HTTP Methods
491
- - `get(path, handler, config?)` - Handle GET requests
492
- - `post(path, handler, config?)` - Handle POST requests
493
- - `put(path, handler, config?)` - Handle PUT requests
494
- - `delete(path, handler, config?)` - Handle DELETE requests
495
- - `patch(path, handler, config?)` - Handle PATCH requests
496
-
497
- #### Plugins & Hooks
498
- - `use(plugin)` - Add a plugin
499
- - `onBeforeStart(handler)` - Before server start hook
500
- - `onAfterStart(handler)` - After server start hook
501
- - `onBeforeStop(handler)` - Before server stop hook
502
- - `onAfterStop(handler)` - After server stop hook
503
- - `onBeforeRestart(handler)` - Before server restart hook
504
- - `onAfterRestart(handler)` - After server restart hook
505
- - `onRequest(handler)` - Global request hook
506
- - `onResponse(handler)` - Global response hook
507
- - `onError(handler)` - Global error hook
508
-
509
- #### Server Management
510
- - `start(port?, hostname?)` - Start the server
511
- - `stop()` - Stop the server gracefully
512
- - `restart(port?, hostname?)` - Restart the server
513
- - `listen(port?, hostname?)` - Start the server (backward compatibility)
514
- - `isServerRunning()` - Check if server is running
515
- - `getServerInfo()` - Get server status information
516
-
517
- #### Hot Reload
518
- - `enableHotReload(watchPaths?)` - Enable hot reload with file watching
519
-
520
- ### Route Configuration
187
+ Define Zod schemas for request validation:
521
188
 
522
189
  ```typescript
523
- interface RouteConfig {
524
- params?: z.ZodSchema<any>; // Path parameter validation
525
- query?: z.ZodSchema<any>; // Query string validation
526
- body?: z.ZodSchema<any>; // Request body validation
527
- headers?: z.ZodSchema<any>; // Header validation
528
- }
529
- ```
190
+ import { z } from "bxo";
530
191
 
531
- ### Plugin Interface
192
+ const UserSchema = z.object({
193
+ name: z.string().min(1),
194
+ email: z.string().email()
195
+ });
532
196
 
533
- ```typescript
534
- interface Plugin {
535
- name?: string;
536
- onRequest?: (ctx: Context) => Promise<void> | void;
537
- onResponse?: (ctx: Context, response: any) => Promise<any> | any;
538
- onError?: (ctx: Context, error: Error) => Promise<any> | any;
539
- }
197
+ app.post("/users", async (ctx) => {
198
+ const user = ctx.body; // Already validated by UserSchema
199
+ return ctx.json({ id: 1, ...user });
200
+ }, {
201
+ body: UserSchema
202
+ });
540
203
  ```
541
204
 
542
- ## ๐Ÿ› ๏ธ Development
543
-
544
- ### Running the Example
205
+ ## Running
545
206
 
546
207
  ```bash
547
- # Run with hot reload enabled
548
- bun run example.ts
549
-
550
- # The server will automatically restart when you edit any .ts/.js files!
208
+ bun run ./src/index.ts
551
209
  ```
552
210
 
553
- ### Project Structure
211
+ Or run the CORS example:
554
212
 
213
+ ```bash
214
+ bun run ./example/cors-example.ts
555
215
  ```
556
- bxo/
557
- โ”œโ”€โ”€ index.ts # Main BXO framework
558
- โ”œโ”€โ”€ plugins/
559
- โ”‚ โ”œโ”€โ”€ index.ts # Plugin exports
560
- โ”‚ โ”œโ”€โ”€ cors.ts # CORS plugin
561
- โ”‚ โ”œโ”€โ”€ logger.ts # Logger plugin
562
- โ”‚ โ”œโ”€โ”€ auth.ts # Authentication plugin
563
- โ”‚ โ””โ”€โ”€ ratelimit.ts # Rate limiting plugin
564
- โ”œโ”€โ”€ example.ts # Usage example
565
- โ”œโ”€โ”€ package.json
566
- โ””โ”€โ”€ README.md
567
- ```
568
-
569
- ## ๐Ÿค Contributing
570
-
571
- BXO is designed to be simple and extensible. Contributions are welcome!
572
216
 
573
- ## ๐Ÿ“„ License
217
+ ## Examples
574
218
 
575
- MIT License - feel free to use BXO in your projects!
219
+ Check out the `example/` directory for more usage examples:
576
220
 
577
- ---
221
+ - `cors-example.ts` - Demonstrates CORS plugin and lifecycle hooks
222
+ - `openapi-example.ts` - Demonstrates OpenAPI plugin with tags and security
223
+ - `index.ts` - Basic routing example
578
224
 
579
- Built with โค๏ธ for the Bun ecosystem
225
+ This project was created using `bun init` in bun v1.2.3. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.