bxo 0.0.4 → 0.0.5-dev.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/index.ts +66 -4
- package/package.json +1 -1
package/index.ts
CHANGED
@@ -9,6 +9,7 @@ interface RouteConfig {
|
|
9
9
|
query?: z.ZodSchema<any>;
|
10
10
|
body?: z.ZodSchema<any>;
|
11
11
|
headers?: z.ZodSchema<any>;
|
12
|
+
response?: z.ZodSchema<any>;
|
12
13
|
}
|
13
14
|
|
14
15
|
// Context type that's fully typed based on the route configuration
|
@@ -59,6 +60,7 @@ export default class BXO {
|
|
59
60
|
private isRunning: boolean = false;
|
60
61
|
private hotReloadEnabled: boolean = false;
|
61
62
|
private watchedFiles: Set<string> = new Set();
|
63
|
+
private watchedExclude: Set<string> = new Set();
|
62
64
|
|
63
65
|
constructor() { }
|
64
66
|
|
@@ -338,6 +340,20 @@ export default class BXO {
|
|
338
340
|
}
|
339
341
|
}
|
340
342
|
|
343
|
+
// Validate response against schema if provided
|
344
|
+
if (route.config?.response && !(response instanceof Response)) {
|
345
|
+
try {
|
346
|
+
response = this.validateData(route.config.response, response);
|
347
|
+
} catch (validationError) {
|
348
|
+
// Response validation failed
|
349
|
+
const errorMessage = validationError instanceof Error ? validationError.message : 'Response validation failed';
|
350
|
+
return new Response(JSON.stringify({ error: `Response validation error: ${errorMessage}` }), {
|
351
|
+
status: 500,
|
352
|
+
headers: { 'Content-Type': 'application/json' }
|
353
|
+
});
|
354
|
+
}
|
355
|
+
}
|
356
|
+
|
341
357
|
// Convert response to Response object
|
342
358
|
if (response instanceof Response) {
|
343
359
|
return response;
|
@@ -394,12 +410,49 @@ export default class BXO {
|
|
394
410
|
}
|
395
411
|
|
396
412
|
// Hot reload functionality
|
397
|
-
enableHotReload(watchPaths: string[] = ['./']): this {
|
413
|
+
enableHotReload(watchPaths: string[] = ['./'], excludePatterns: string[] = []): this {
|
398
414
|
this.hotReloadEnabled = true;
|
399
415
|
watchPaths.forEach(path => this.watchedFiles.add(path));
|
416
|
+
excludePatterns.forEach(pattern => this.watchedExclude.add(pattern));
|
400
417
|
return this;
|
401
418
|
}
|
402
419
|
|
420
|
+
private shouldExcludeFile(filename: string): boolean {
|
421
|
+
for (const pattern of this.watchedExclude) {
|
422
|
+
// Handle exact match
|
423
|
+
if (pattern === filename) {
|
424
|
+
return true;
|
425
|
+
}
|
426
|
+
|
427
|
+
// Handle directory patterns (e.g., "node_modules/", "dist/")
|
428
|
+
if (pattern.endsWith('/')) {
|
429
|
+
if (filename.startsWith(pattern) || filename.includes(`/${pattern}`)) {
|
430
|
+
return true;
|
431
|
+
}
|
432
|
+
}
|
433
|
+
|
434
|
+
// Handle wildcard patterns (e.g., "*.log", "temp*")
|
435
|
+
if (pattern.includes('*')) {
|
436
|
+
const regex = new RegExp(pattern.replace(/\*/g, '.*'));
|
437
|
+
if (regex.test(filename)) {
|
438
|
+
return true;
|
439
|
+
}
|
440
|
+
}
|
441
|
+
|
442
|
+
// Handle file extension patterns (e.g., ".log", ".tmp")
|
443
|
+
if (pattern.startsWith('.') && filename.endsWith(pattern)) {
|
444
|
+
return true;
|
445
|
+
}
|
446
|
+
|
447
|
+
// Handle substring matches for directories
|
448
|
+
if (filename.includes(pattern)) {
|
449
|
+
return true;
|
450
|
+
}
|
451
|
+
}
|
452
|
+
|
453
|
+
return false;
|
454
|
+
}
|
455
|
+
|
403
456
|
private async setupFileWatcher(port: number, hostname: string): Promise<void> {
|
404
457
|
if (!this.hotReloadEnabled) return;
|
405
458
|
|
@@ -409,11 +462,19 @@ export default class BXO {
|
|
409
462
|
try {
|
410
463
|
fs.watch(watchPath, { recursive: true }, async (eventType: string, filename: string) => {
|
411
464
|
if (filename && (filename.endsWith('.ts') || filename.endsWith('.js'))) {
|
465
|
+
// Check if file should be excluded
|
466
|
+
if (this.shouldExcludeFile(filename)) {
|
467
|
+
return;
|
468
|
+
}
|
469
|
+
|
412
470
|
console.log(`🔄 File changed: ${filename}, restarting server...`);
|
413
471
|
await this.restart(port, hostname);
|
414
472
|
}
|
415
473
|
});
|
416
474
|
console.log(`👀 Watching ${watchPath} for changes...`);
|
475
|
+
if (this.watchedExclude.size > 0) {
|
476
|
+
console.log(`🚫 Excluding patterns: ${Array.from(this.watchedExclude).join(', ')}`);
|
477
|
+
}
|
417
478
|
} catch (error) {
|
418
479
|
console.warn(`⚠️ Could not watch ${watchPath}:`, error);
|
419
480
|
}
|
@@ -535,11 +596,12 @@ export default class BXO {
|
|
535
596
|
return this.isRunning;
|
536
597
|
}
|
537
598
|
|
538
|
-
getServerInfo(): { running: boolean; hotReload: boolean; watchedFiles: string[] } {
|
599
|
+
getServerInfo(): { running: boolean; hotReload: boolean; watchedFiles: string[]; excludePatterns: string[] } {
|
539
600
|
return {
|
540
601
|
running: this.isRunning,
|
541
602
|
hotReload: this.hotReloadEnabled,
|
542
|
-
watchedFiles: Array.from(this.watchedFiles)
|
603
|
+
watchedFiles: Array.from(this.watchedFiles),
|
604
|
+
excludePatterns: Array.from(this.watchedExclude)
|
543
605
|
};
|
544
606
|
}
|
545
607
|
}
|
@@ -552,4 +614,4 @@ const error = (error: Error, status: number = 500) => {
|
|
552
614
|
export { z, error };
|
553
615
|
|
554
616
|
// Export types for external use
|
555
|
-
export type { RouteConfig };
|
617
|
+
export type { RouteConfig, Handler };
|