bxo 0.0.5-dev.52 โ†’ 0.0.5-dev.54

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bxo",
3
3
  "module": "index.ts",
4
- "version": "0.0.5-dev.52",
4
+ "version": "0.0.5-dev.54",
5
5
  "description": "A simple and lightweight web framework for Bun",
6
6
  "type": "module",
7
7
  "exports": {
package/src/core/bxo.ts CHANGED
@@ -80,6 +80,7 @@ export default class BXO {
80
80
  // It's a middleware plugin
81
81
  this.middleware.push(plugin);
82
82
  }
83
+ this.updateRequestHandler();
83
84
  return this;
84
85
  }
85
86
 
@@ -189,8 +190,8 @@ export default class BXO {
189
190
  // Update the request handler with current routes and configuration
190
191
  private updateRequestHandler(): void {
191
192
  this.requestHandler = new RequestHandler(
192
- this._routes,
193
- this._wsRoutes,
193
+ this.getAllRoutes(),
194
+ this.getAllWSRoutes(),
194
195
  this.plugins,
195
196
  this.middleware,
196
197
  this.hooks,
@@ -90,22 +90,13 @@ export async function parseRequestBody(request: Request): Promise<any> {
90
90
  }
91
91
  } else if (contentType?.includes('multipart/form-data') || contentType?.includes('application/x-www-form-urlencoded')) {
92
92
  const formData = await request.formData();
93
- // Convert FormData to a structured object that preserves file information
93
+ // Convert FormData to a structured object
94
94
  const formBody: Record<string, any> = {};
95
95
 
96
96
  for (const [key, value] of formData.entries()) {
97
97
  if (value instanceof File) {
98
- // Handle file uploads
99
- formBody[key] = {
100
- type: 'file',
101
- name: value.name,
102
- size: value.size,
103
- lastModified: value.lastModified,
104
- file: value, // Keep the actual File object for access
105
- // Add convenience properties
106
- filename: value.name,
107
- mimetype: value.type || 'application/octet-stream'
108
- };
98
+ // Return File instances directly
99
+ formBody[key] = value;
109
100
  } else {
110
101
  // Handle regular form fields
111
102
  formBody[key] = value;
@@ -186,21 +177,13 @@ export function createRedirectResponse(
186
177
  }
187
178
 
188
179
  // Check if a value is a file upload
189
- export function isFileUpload(value: any): value is {
190
- type: 'file';
191
- file: File;
192
- name: string;
193
- size: number;
194
- lastModified: number;
195
- filename: string;
196
- mimetype: string;
197
- } {
198
- return value && typeof value === 'object' && value.type === 'file' && value.file instanceof File;
180
+ export function isFileUpload(value: any): value is File {
181
+ return value instanceof File;
199
182
  }
200
183
 
201
184
  // Extract File object from upload value
202
185
  export function getFileFromUpload(value: any): File | null {
203
- return isFileUpload(value) ? value.file : null;
186
+ return isFileUpload(value) ? value : null;
204
187
  }
205
188
 
206
189
  // Get file metadata without the File object
@@ -209,7 +192,7 @@ export function getFileInfo(value: any): { name: string; size: number; mimetype:
209
192
  return {
210
193
  name: value.name,
211
194
  size: value.size,
212
- mimetype: value.mimetype,
195
+ mimetype: value.type || 'application/octet-stream',
213
196
  lastModified: value.lastModified
214
197
  };
215
198
  }
@@ -240,7 +223,7 @@ export function getFileUploads(formData: Record<string, any>): Record<string, Fi
240
223
  const files: Record<string, File> = {};
241
224
  for (const [key, value] of Object.entries(formData)) {
242
225
  if (isFileUpload(value)) {
243
- files[key] = value.file;
226
+ files[key] = value;
244
227
  }
245
228
  }
246
229
  return files;
@@ -202,34 +202,17 @@ describe('Utility Functions', () => {
202
202
 
203
203
  describe('File Upload Utilities', () => {
204
204
  it('should identify file uploads correctly', () => {
205
- const fileUpload = {
206
- type: 'file',
207
- name: 'test.jpg',
208
- size: 1024,
209
- lastModified: 1234567890,
210
- file: new File(['test'], 'test.jpg'),
211
- filename: 'test.jpg',
212
- mimetype: 'image/jpeg'
213
- };
205
+ const file = new File(['test'], 'test.jpg', { type: 'image/jpeg' });
214
206
 
215
- expect(isFileUpload(fileUpload)).toBe(true);
207
+ expect(isFileUpload(file)).toBe(true);
216
208
  expect(isFileUpload('not a file')).toBe(false);
217
209
  expect(isFileUpload({ type: 'text' })).toBe(false);
218
210
  });
219
211
 
220
212
  it('should extract file from upload', () => {
221
- const file = new File(['test'], 'test.jpg');
222
- const fileUpload = {
223
- type: 'file',
224
- name: 'test.jpg',
225
- size: 1024,
226
- lastModified: 1234567890,
227
- file,
228
- filename: 'test.jpg',
229
- mimetype: 'image/jpeg'
230
- };
213
+ const file = new File(['test'], 'test.jpg', { type: 'image/jpeg' });
231
214
 
232
- const result = getFileFromUpload(fileUpload);
215
+ const result = getFileFromUpload(file);
233
216
  expect(result).toBe(file);
234
217
  });
235
218
 
@@ -239,22 +222,14 @@ describe('Utility Functions', () => {
239
222
  });
240
223
 
241
224
  it('should get file info', () => {
242
- const fileUpload = {
243
- type: 'file',
244
- name: 'test.jpg',
245
- size: 1024,
246
- lastModified: 1234567890,
247
- file: new File(['test'], 'test.jpg'),
248
- filename: 'test.jpg',
249
- mimetype: 'image/jpeg'
250
- };
225
+ const file = new File(['test'], 'test.jpg', { type: 'image/jpeg' });
251
226
 
252
- const result = getFileInfo(fileUpload);
227
+ const result = getFileInfo(file);
253
228
  expect(result).toEqual({
254
229
  name: 'test.jpg',
255
- size: 1024,
230
+ size: 4,
256
231
  mimetype: 'image/jpeg',
257
- lastModified: 1234567890
232
+ lastModified: expect.any(Number)
258
233
  });
259
234
  });
260
235
 
@@ -264,17 +239,10 @@ describe('Utility Functions', () => {
264
239
  });
265
240
 
266
241
  it('should get all file uploads from form data', () => {
242
+ const file = new File(['test'], 'avatar.jpg', { type: 'image/jpeg' });
267
243
  const formData = {
268
244
  name: 'john',
269
- avatar: {
270
- type: 'file',
271
- name: 'avatar.jpg',
272
- size: 1024,
273
- lastModified: 1234567890,
274
- file: new File(['test'], 'avatar.jpg'),
275
- filename: 'avatar.jpg',
276
- mimetype: 'image/jpeg'
277
- },
245
+ avatar: file,
278
246
  email: 'john@example.com'
279
247
  };
280
248
 
@@ -285,17 +253,10 @@ describe('Utility Functions', () => {
285
253
  });
286
254
 
287
255
  it('should get all non-file fields from form data', () => {
256
+ const file = new File(['test'], 'avatar.jpg', { type: 'image/jpeg' });
288
257
  const formData = {
289
258
  name: 'john',
290
- avatar: {
291
- type: 'file',
292
- name: 'avatar.jpg',
293
- size: 1024,
294
- lastModified: 1234567890,
295
- file: new File(['test'], 'avatar.jpg'),
296
- filename: 'avatar.jpg',
297
- mimetype: 'image/jpeg'
298
- },
259
+ avatar: file,
299
260
  email: 'john@example.com'
300
261
  };
301
262
 
@@ -1,209 +0,0 @@
1
- # BXO Framework - Refactored Structure
2
-
3
- The BXO framework has been completely refactored to be more modular, maintainable, and easier to understand. The functionality remains exactly the same, but the code is now organized into logical modules.
4
-
5
- ## ๐Ÿ—๏ธ New Directory Structure
6
-
7
- ```
8
- src/
9
- โ”œโ”€โ”€ core/ # Core BXO class and main logic
10
- โ”œโ”€โ”€ types/ # TypeScript type definitions
11
- โ”œโ”€โ”€ utils/ # Utility functions and helpers
12
- โ”œโ”€โ”€ handlers/ # Request handling logic
13
- โ”œโ”€โ”€ plugins/ # Plugin system (existing)
14
- โ”œโ”€โ”€ middleware/ # Middleware system (existing)
15
- โ””โ”€โ”€ index.ts # Main export file
16
- ```
17
-
18
- ## ๐Ÿ“ Module Breakdown
19
-
20
- ### `src/types/index.ts`
21
- - All TypeScript interfaces and types
22
- - Zod schema type utilities
23
- - Context, Route, and Plugin interfaces
24
- - File upload type definitions
25
-
26
- ### `src/utils/index.ts`
27
- - Core utility functions for parsing requests
28
- - Validation helpers
29
- - Cookie handling utilities
30
- - File upload utilities
31
-
32
- ### `src/utils/route-matcher.ts`
33
- - Route matching logic for HTTP routes
34
- - WebSocket route matching
35
- - Wildcard and parameter handling
36
-
37
- ### `src/utils/context-factory.ts`
38
- - Context object creation
39
- - Validation integration
40
- - Cookie management
41
-
42
- ### `src/utils/response-handler.ts`
43
- - Response processing and formatting
44
- - Error response creation
45
- - File and Bun.file handling
46
-
47
- ### `src/utils/helpers.ts`
48
- - Helper functions (error, file, redirect)
49
- - Cookie options utilities
50
-
51
- ### `src/handlers/request-handler.ts`
52
- - Main request processing logic
53
- - Middleware and hook execution
54
- - WebSocket upgrade handling
55
- - Error handling
56
-
57
- ### `src/core/bxo.ts`
58
- - Main BXO class
59
- - Route registration methods
60
- - Server lifecycle management
61
- - Plugin system integration
62
-
63
- ## ๐Ÿ”„ Migration Guide
64
-
65
- ### Before (Old Structure)
66
- ```typescript
67
- import BXO from './index';
68
-
69
- const app = new BXO();
70
- app.get('/', () => 'Hello World');
71
- ```
72
-
73
- ### After (New Structure)
74
- ```typescript
75
- import BXO from './index'; // Still works exactly the same!
76
-
77
- const app = new BXO();
78
- app.get('/', () => 'Hello World');
79
- ```
80
-
81
- **No changes needed in your existing code!** The API is completely backward compatible.
82
-
83
- ## โœจ Benefits of Refactoring
84
-
85
- ### 1. **Better Separation of Concerns**
86
- - Each module has a single responsibility
87
- - Easier to understand what each part does
88
- - Clear boundaries between different functionalities
89
-
90
- ### 2. **Improved Maintainability**
91
- - Smaller, focused files are easier to modify
92
- - Changes to one feature don't affect others
93
- - Better testability with isolated modules
94
-
95
- ### 3. **Enhanced Readability**
96
- - Code is organized logically
97
- - Related functionality is grouped together
98
- - Easier to find specific features
99
-
100
- ### 4. **Better Type Safety**
101
- - Types are centralized and well-defined
102
- - Easier to maintain type consistency
103
- - Better IntelliSense support
104
-
105
- ### 5. **Easier Testing**
106
- - Individual modules can be tested in isolation
107
- - Mocking is simpler with clear interfaces
108
- - Unit tests are more focused
109
-
110
- ## ๐Ÿงช Testing the Refactored Structure
111
-
112
- Run the test file to verify everything works:
113
-
114
- ```bash
115
- bun run test-refactored.ts
116
- ```
117
-
118
- ## ๐Ÿ“š Usage Examples
119
-
120
- ### Basic Usage (Unchanged)
121
- ```typescript
122
- import BXO, { z } from './index';
123
-
124
- const app = new BXO();
125
-
126
- app.get('/', () => 'Hello World');
127
-
128
- app.post('/users', async (ctx) => {
129
- return { message: 'User created' };
130
- }, {
131
- body: z.object({
132
- name: z.string(),
133
- email: z.string().email()
134
- })
135
- });
136
-
137
- app.start(3000);
138
- ```
139
-
140
- ### File Uploads (Unchanged)
141
- ```typescript
142
- import { isFileUpload, saveUploadedFile } from './index';
143
-
144
- app.post('/upload', async (ctx) => {
145
- if (ctx.body.avatar && isFileUpload(ctx.body.avatar)) {
146
- await saveUploadedFile(ctx.body.avatar, './uploads/avatar.jpg');
147
- }
148
- return { message: 'Upload successful' };
149
- });
150
- ```
151
-
152
- ### WebSockets (Unchanged)
153
- ```typescript
154
- app.ws('/chat', {
155
- onOpen: (ws) => console.log('Connected'),
156
- onMessage: (ws, message) => ws.send(`Echo: ${message}`)
157
- });
158
- ```
159
-
160
- ## ๐Ÿ”ง Development
161
-
162
- ### Adding New Features
163
- 1. **New utility functions**: Add to `src/utils/`
164
- 2. **New types**: Add to `src/types/`
165
- 3. **New handlers**: Add to `src/handlers/`
166
- 4. **New core features**: Add to `src/core/`
167
-
168
- ### Modifying Existing Features
169
- - **Route matching**: Edit `src/utils/route-matcher.ts`
170
- - **Request parsing**: Edit `src/utils/index.ts`
171
- - **Response handling**: Edit `src/utils/response-handler.ts`
172
- - **Context creation**: Edit `src/utils/context-factory.ts`
173
-
174
- ## ๐Ÿ“ฆ Build and Distribution
175
-
176
- The main `index.ts` file now simply re-exports everything from the new structure:
177
-
178
- ```typescript
179
- // Re-export everything from the refactored source
180
- export * from './src/index';
181
- ```
182
-
183
- This means:
184
- - โœ… **Zero breaking changes** for existing users
185
- - โœ… **Same import syntax** as before
186
- - โœ… **All functionality preserved**
187
- - โœ… **Better internal organization**
188
-
189
- ## ๐ŸŽฏ Future Improvements
190
-
191
- With this new structure, we can now easily:
192
-
193
- 1. **Add new modules** without cluttering the main file
194
- 2. **Implement better testing** with isolated components
195
- 3. **Add new features** in dedicated modules
196
- 4. **Improve performance** by optimizing specific modules
197
- 5. **Better documentation** with focused module descriptions
198
-
199
- ## ๐Ÿค Contributing
200
-
201
- When contributing to the framework:
202
-
203
- 1. **Identify the right module** for your changes
204
- 2. **Keep modules focused** on their specific responsibility
205
- 3. **Update types** if adding new interfaces
206
- 4. **Add tests** for new functionality
207
- 5. **Update documentation** for new features
208
-
209
- The refactored structure makes it much easier to contribute and maintain the codebase!