@dangao/bun-server 1.8.1 → 1.8.2
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/docs/api.md +194 -81
- package/docs/extensions.md +53 -0
- package/docs/guide.md +243 -1
- package/docs/microservice-config-center.md +73 -74
- package/docs/microservice-nacos.md +89 -90
- package/docs/microservice-service-registry.md +85 -86
- package/docs/microservice.md +142 -137
- package/docs/request-lifecycle.md +45 -4
- package/docs/symbol-interface-pattern.md +106 -106
- package/docs/zh/api.md +458 -18
- package/docs/zh/extensions.md +53 -0
- package/docs/zh/guide.md +251 -4
- package/docs/zh/microservice-config-center.md +258 -0
- package/docs/zh/microservice-nacos.md +346 -0
- package/docs/zh/microservice-service-registry.md +306 -0
- package/docs/zh/microservice.md +680 -0
- package/docs/zh/request-lifecycle.md +43 -5
- package/package.json +1 -1
package/docs/api.md
CHANGED
|
@@ -8,7 +8,9 @@ Framework for quick reference.
|
|
|
8
8
|
| API | Description |
|
|
9
9
|
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
10
10
|
| `Application(options?)` | Main application class, supports `use` for global middleware, `registerController`/`registerWebSocketGateway` for components, and `listen/stop` for lifecycle management |
|
|
11
|
+
| `BunServer(options?)` | Low-level server wrapper, provides direct access to Bun's server API |
|
|
11
12
|
| `Context` | Unified request context, wraps `Request` and provides methods like `getQuery/getParam/getBody/setHeader/setStatus/createResponse` |
|
|
13
|
+
| `ContextService` | Service for accessing request context in services, provides `getContext()` method |
|
|
12
14
|
| `ResponseBuilder` | Provides convenient response builders: `json/text/html/empty/redirect/error/file` |
|
|
13
15
|
| `RouteRegistry` / `Router` | Can directly register functional routes or get the underlying `Router` for manual control |
|
|
14
16
|
|
|
@@ -17,7 +19,7 @@ Framework for quick reference.
|
|
|
17
19
|
- `@Controller(path)`: Declare controller prefix.
|
|
18
20
|
- `@GET/@POST/@PUT/@PATCH/@DELETE(path)`: Declare HTTP methods.
|
|
19
21
|
- Parameter decorators:
|
|
20
|
-
`@Body() / @Query(key) / @Param(key) / @Header(key) / @
|
|
22
|
+
`@Body() / @Query(key) / @QueryMap() / @Param(key) / @Header(key) / @HeaderMap() / @Context()`.
|
|
21
23
|
- `ControllerRegistry` automatically parses decorators and registers routes.
|
|
22
24
|
|
|
23
25
|
**Example**:
|
|
@@ -191,6 +193,7 @@ For detailed information, please refer to
|
|
|
191
193
|
- `Middleware` type: `(context, next) => Response`.
|
|
192
194
|
- `MiddlewarePipeline`: `use`, `run`, `hasMiddlewares`, `clear`.
|
|
193
195
|
- `@UseMiddleware(...middlewares)`: Applied to controller classes or methods.
|
|
196
|
+
- `@RateLimit(options)`: Rate limiting decorator for controllers or methods.
|
|
194
197
|
- Built-in middleware:
|
|
195
198
|
- `createLoggerMiddleware`
|
|
196
199
|
- `createRequestLoggingMiddleware`
|
|
@@ -198,6 +201,7 @@ For detailed information, please refer to
|
|
|
198
201
|
- `createErrorHandlingMiddleware`
|
|
199
202
|
- `createFileUploadMiddleware`
|
|
200
203
|
- `createStaticFileMiddleware`
|
|
204
|
+
- `createRateLimitMiddleware`
|
|
201
205
|
|
|
202
206
|
## Validation
|
|
203
207
|
|
|
@@ -227,8 +231,15 @@ For detailed information, please refer to
|
|
|
227
231
|
## Request Utilities
|
|
228
232
|
|
|
229
233
|
- `BodyParser`: `parse(request)`, automatically caches parsed results.
|
|
230
|
-
- `FileHandler`: Parses `multipart/form-data`, returns structured file objects.
|
|
231
234
|
- `RequestWrapper`: Lightweight wrapper for compatibility scenarios.
|
|
235
|
+
- `ResponseBuilder`: Provides convenient response builders.
|
|
236
|
+
|
|
237
|
+
## File Handling
|
|
238
|
+
|
|
239
|
+
- `FileStorage`: File storage service for managing uploaded files.
|
|
240
|
+
- `createFileUploadMiddleware(options?)`: Middleware for handling file uploads.
|
|
241
|
+
- `createStaticFileMiddleware(root, options?)`: Middleware for serving static files.
|
|
242
|
+
- `UploadedFileInfo`: Type definition for uploaded file information.
|
|
232
243
|
|
|
233
244
|
## Database Module
|
|
234
245
|
|
|
@@ -485,14 +496,40 @@ class OrderService {
|
|
|
485
496
|
}
|
|
486
497
|
```
|
|
487
498
|
|
|
499
|
+
## Config Module
|
|
500
|
+
|
|
501
|
+
- `ConfigModule.forRoot(options)`: Configure configuration management
|
|
502
|
+
- `ConfigService`: `get()`, `set()`, `has()`, `getOrThrow()`
|
|
503
|
+
- `CONFIG_SERVICE_TOKEN`: Token for dependency injection
|
|
504
|
+
|
|
505
|
+
**Example**:
|
|
506
|
+
|
|
507
|
+
```typescript
|
|
508
|
+
ConfigModule.forRoot({
|
|
509
|
+
defaultConfig: { app: { name: "MyApp", port: 3000 } },
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
@Injectable()
|
|
513
|
+
class AppService {
|
|
514
|
+
public constructor(
|
|
515
|
+
@Inject(CONFIG_SERVICE_TOKEN) private readonly config: ConfigService,
|
|
516
|
+
) {}
|
|
517
|
+
|
|
518
|
+
public getPort() {
|
|
519
|
+
return this.config.get<number>("app.port");
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
```
|
|
523
|
+
|
|
488
524
|
## Security Module
|
|
489
525
|
|
|
490
526
|
- `SecurityModule.forRoot(options)`: Configure security and authentication
|
|
491
|
-
- `@Auth(options?)`: Require authentication/authorization
|
|
492
527
|
- `SecurityContextHolder`: Access current security context
|
|
493
528
|
- `AuthenticationManager`: Manage authentication
|
|
494
529
|
- `JwtAuthenticationProvider`: JWT authentication provider
|
|
495
530
|
- `OAuth2AuthenticationProvider`: OAuth2 authentication provider
|
|
531
|
+
- `createSecurityFilter()`: Create security filter middleware
|
|
532
|
+
- `RoleBasedAccessDecisionManager`: Role-based access control
|
|
496
533
|
|
|
497
534
|
**Example**:
|
|
498
535
|
|
|
@@ -507,96 +544,172 @@ SecurityModule.forRoot({
|
|
|
507
544
|
@Controller("/api/users")
|
|
508
545
|
class UserController {
|
|
509
546
|
@GET("/profile")
|
|
510
|
-
|
|
547
|
+
public getProfile() {
|
|
548
|
+
const context = SecurityContextHolder.getContext();
|
|
549
|
+
return context.getPrincipal();
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
## Guards System
|
|
555
|
+
|
|
556
|
+
- `@UseGuards(...guards)`: Apply guards to controllers or methods
|
|
557
|
+
- `@Roles(...roles)`: Require specific roles
|
|
558
|
+
- `AuthGuard`: Require authentication
|
|
559
|
+
- `OptionalAuthGuard`: Optional authentication
|
|
560
|
+
- `RolesGuard`: Role-based authorization guard
|
|
561
|
+
- `createRolesGuard(options)`: Create custom roles guard
|
|
562
|
+
- `GuardRegistry`: Central registry for guards
|
|
563
|
+
- `ExecutionContext`: Execution context for guards
|
|
564
|
+
- `Reflector`: Metadata reflection utility
|
|
565
|
+
|
|
566
|
+
**Example**:
|
|
567
|
+
|
|
568
|
+
```typescript
|
|
569
|
+
@Controller("/api/users")
|
|
570
|
+
class UserController {
|
|
571
|
+
@GET("/profile")
|
|
572
|
+
@UseGuards(AuthGuard)
|
|
511
573
|
public getProfile() {
|
|
512
574
|
const context = SecurityContextHolder.getContext();
|
|
513
575
|
return context.getPrincipal();
|
|
514
576
|
}
|
|
515
577
|
|
|
516
578
|
@GET("/admin")
|
|
517
|
-
@
|
|
579
|
+
@UseGuards(AuthGuard, RolesGuard)
|
|
580
|
+
@Roles("admin")
|
|
518
581
|
public getAdmin() {
|
|
519
582
|
return { message: "Admin access" };
|
|
520
583
|
}
|
|
521
584
|
}
|
|
522
585
|
```
|
|
523
586
|
|
|
524
|
-
##
|
|
587
|
+
## Events Module
|
|
588
|
+
|
|
589
|
+
- `EventModule.forRoot(options?)`: Configure event system
|
|
590
|
+
- `EventEmitterService`: Event emitter service
|
|
591
|
+
- `@OnEvent(event, options?)`: Register event listener method
|
|
592
|
+
- `EventListenerScanner`: Scans and registers event listeners
|
|
593
|
+
- `EVENT_EMITTER_TOKEN`: Token for dependency injection
|
|
525
594
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
Context,
|
|
546
|
-
Controller,
|
|
547
|
-
createCorsMiddleware,
|
|
548
|
-
createErrorHandlingMiddleware,
|
|
549
|
-
createLoggerMiddleware,
|
|
550
|
-
Cron,
|
|
551
|
-
DATABASE_SERVICE_TOKEN,
|
|
552
|
-
DatabaseModule,
|
|
553
|
-
// Database
|
|
554
|
-
DatabaseService,
|
|
555
|
-
DELETE,
|
|
556
|
-
Entity,
|
|
557
|
-
GET,
|
|
558
|
-
HealthModule,
|
|
559
|
-
// Errors
|
|
560
|
-
HttpException,
|
|
561
|
-
Inject,
|
|
562
|
-
// Dependency Injection
|
|
563
|
-
Injectable,
|
|
564
|
-
IsEmail,
|
|
565
|
-
IsNumber,
|
|
566
|
-
IsString,
|
|
567
|
-
LoggerModule,
|
|
568
|
-
MetricsModule,
|
|
569
|
-
Module,
|
|
570
|
-
NotFoundException,
|
|
571
|
-
OnMessage,
|
|
572
|
-
PATCH,
|
|
573
|
-
// Testing
|
|
574
|
-
PerformanceHarness,
|
|
575
|
-
POST,
|
|
576
|
-
PrimaryKey,
|
|
577
|
-
PUT,
|
|
578
|
-
Queue,
|
|
579
|
-
QUEUE_SERVICE_TOKEN,
|
|
580
|
-
QueueModule,
|
|
581
|
-
// Queue
|
|
582
|
-
QueueService,
|
|
583
|
-
Repository,
|
|
584
|
-
SecurityContextHolder,
|
|
585
|
-
SecurityModule,
|
|
586
|
-
Session,
|
|
587
|
-
SESSION_SERVICE_TOKEN,
|
|
588
|
-
SessionModule,
|
|
589
|
-
// Session
|
|
590
|
-
SessionService,
|
|
591
|
-
SwaggerModule,
|
|
592
|
-
Transactional,
|
|
593
|
-
// Middleware
|
|
594
|
-
UseMiddleware,
|
|
595
|
-
// Validation
|
|
596
|
-
Validate,
|
|
597
|
-
// WebSocket
|
|
598
|
-
WebSocketGateway,
|
|
599
|
-
} from "@dangao/bun-server";
|
|
595
|
+
**Example**:
|
|
596
|
+
|
|
597
|
+
```typescript
|
|
598
|
+
EventModule.forRoot({
|
|
599
|
+
wildcard: true,
|
|
600
|
+
maxListeners: 20,
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
@Injectable()
|
|
604
|
+
class NotificationService {
|
|
605
|
+
public constructor(
|
|
606
|
+
@Inject(EVENT_EMITTER_TOKEN) private readonly eventEmitter: EventEmitter,
|
|
607
|
+
) {}
|
|
608
|
+
|
|
609
|
+
@OnEvent('user.created')
|
|
610
|
+
public async handleUserCreated(data: { userId: string }) {
|
|
611
|
+
// Send notification
|
|
612
|
+
}
|
|
613
|
+
}
|
|
600
614
|
```
|
|
601
615
|
|
|
602
|
-
|
|
616
|
+
## Microservice Modules
|
|
617
|
+
|
|
618
|
+
### Config Center Module
|
|
619
|
+
|
|
620
|
+
- `ConfigCenterModule.forRoot(options)`: Configure config center (Nacos, Consul, etc.)
|
|
621
|
+
- `CONFIG_CENTER_TOKEN`: Token for dependency injection
|
|
622
|
+
- `NacosConfigCenter`: Nacos implementation
|
|
623
|
+
|
|
624
|
+
**Example**:
|
|
625
|
+
|
|
626
|
+
```typescript
|
|
627
|
+
ConfigCenterModule.forRoot({
|
|
628
|
+
provider: 'nacos',
|
|
629
|
+
nacos: {
|
|
630
|
+
client: {
|
|
631
|
+
serverList: 'localhost:8848',
|
|
632
|
+
namespace: 'public',
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
});
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### Service Registry Module
|
|
639
|
+
|
|
640
|
+
- `ServiceRegistryModule.forRoot(options)`: Configure service registry (Nacos, Consul, etc.)
|
|
641
|
+
- `SERVICE_REGISTRY_TOKEN`: Token for dependency injection
|
|
642
|
+
- `NacosServiceRegistry`: Nacos implementation
|
|
643
|
+
- `@RegisterService(options)`: Register service instance
|
|
644
|
+
- `@DiscoverService(serviceName)`: Discover service instances
|
|
645
|
+
|
|
646
|
+
**Example**:
|
|
647
|
+
|
|
648
|
+
```typescript
|
|
649
|
+
ServiceRegistryModule.forRoot({
|
|
650
|
+
provider: 'nacos',
|
|
651
|
+
nacos: {
|
|
652
|
+
client: {
|
|
653
|
+
serverList: 'localhost:8848',
|
|
654
|
+
},
|
|
655
|
+
},
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
@Injectable()
|
|
659
|
+
class MyService {
|
|
660
|
+
@RegisterService({
|
|
661
|
+
serviceName: 'my-service',
|
|
662
|
+
ip: '127.0.0.1',
|
|
663
|
+
port: 3000,
|
|
664
|
+
})
|
|
665
|
+
public start() {
|
|
666
|
+
// Service registered
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
### Service Client
|
|
672
|
+
|
|
673
|
+
- `ServiceClient`: Service-to-service communication client
|
|
674
|
+
- `@ServiceClient(serviceName, options?)`: Inject service client
|
|
675
|
+
- `@ServiceCall(method, path, options?)`: Declare service call
|
|
676
|
+
- Load balancers: `RandomLoadBalancer`, `RoundRobinLoadBalancer`, `WeightedRoundRobinLoadBalancer`, `ConsistentHashLoadBalancer`, `LeastActiveLoadBalancer`
|
|
677
|
+
- Interceptors: `TraceIdRequestInterceptor`, `UserInfoRequestInterceptor`, `RequestLogInterceptor`, etc.
|
|
678
|
+
|
|
679
|
+
**Example**:
|
|
680
|
+
|
|
681
|
+
```typescript
|
|
682
|
+
@Injectable()
|
|
683
|
+
class OrderService {
|
|
684
|
+
@ServiceClient('user-service')
|
|
685
|
+
private readonly userClient!: ServiceClient;
|
|
686
|
+
|
|
687
|
+
@ServiceCall('GET', '/users/:id')
|
|
688
|
+
public async getUser(id: string) {
|
|
689
|
+
return await this.userClient.call('GET', `/users/${id}`);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
### Governance
|
|
695
|
+
|
|
696
|
+
- `CircuitBreaker`: Circuit breaker pattern implementation
|
|
697
|
+
- `RateLimiter`: Rate limiting for service calls
|
|
698
|
+
- `RetryStrategyImpl`: Retry strategy implementation
|
|
699
|
+
|
|
700
|
+
### Tracing
|
|
701
|
+
|
|
702
|
+
- `Tracer`: Distributed tracing
|
|
703
|
+
- `ConsoleTraceCollector`: Console-based trace collector
|
|
704
|
+
- `MemoryTraceCollector`: In-memory trace collector
|
|
705
|
+
- `SpanStatus`, `SpanKind`: Span types
|
|
706
|
+
|
|
707
|
+
### Monitoring
|
|
708
|
+
|
|
709
|
+
- `ServiceMetricsCollector`: Service call metrics collection
|
|
710
|
+
- `ServiceCallMetrics`: Metrics data structure
|
|
711
|
+
- `ServiceInstanceHealth`: Health check data
|
|
712
|
+
|
|
713
|
+
## Export Entry
|
|
714
|
+
|
|
715
|
+
All above APIs can be exported from `src/index.ts`. See the full export list in `src/index.ts` for complete API reference.
|
package/docs/extensions.md
CHANGED
|
@@ -81,10 +81,12 @@ import {
|
|
|
81
81
|
createErrorHandlingMiddleware, // Error handling
|
|
82
82
|
createFileUploadMiddleware, // File upload
|
|
83
83
|
createStaticFileMiddleware, // Static file serving
|
|
84
|
+
createRateLimitMiddleware, // Rate limiting
|
|
84
85
|
} from '@dangao/bun-server';
|
|
85
86
|
|
|
86
87
|
app.use(createLoggerMiddleware({ prefix: '[App]' }));
|
|
87
88
|
app.use(createCorsMiddleware({ origin: 'https://example.com' }));
|
|
89
|
+
app.use(createRateLimitMiddleware({ windowMs: 60000, max: 100 }));
|
|
88
90
|
app.use(createStaticFileMiddleware({ root: './public', prefix: '/assets' }));
|
|
89
91
|
```
|
|
90
92
|
|
|
@@ -378,6 +380,57 @@ class UserController {
|
|
|
378
380
|
- **Validation hook**: `validate(config)` can integrate class-validator style validation
|
|
379
381
|
- **Non-intrusive**: Examples (`basic-app.ts` / `full-app.ts` / `multi-module-app.ts` / `auth-app.ts`) use `ConfigModule` to manage ports, logger prefixes, etc.
|
|
380
382
|
|
|
383
|
+
#### EventModule (Event System)
|
|
384
|
+
|
|
385
|
+
EventModule provides a powerful event-driven architecture:
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
import {
|
|
389
|
+
EventModule,
|
|
390
|
+
OnEvent,
|
|
391
|
+
EVENT_EMITTER_TOKEN,
|
|
392
|
+
Injectable,
|
|
393
|
+
Inject,
|
|
394
|
+
Module,
|
|
395
|
+
} from '@dangao/bun-server';
|
|
396
|
+
import type { EventEmitter } from '@dangao/bun-server';
|
|
397
|
+
|
|
398
|
+
// Configure Event module
|
|
399
|
+
EventModule.forRoot({
|
|
400
|
+
wildcard: true,
|
|
401
|
+
maxListeners: 20,
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
@Injectable()
|
|
405
|
+
class NotificationService {
|
|
406
|
+
@OnEvent('user.created')
|
|
407
|
+
public handleUserCreated(payload: { userId: string }) {
|
|
408
|
+
console.log('User created:', payload);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
@Module({
|
|
413
|
+
imports: [EventModule],
|
|
414
|
+
providers: [NotificationService],
|
|
415
|
+
})
|
|
416
|
+
class AppModule {}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
#### Other Official Modules
|
|
420
|
+
|
|
421
|
+
The framework also provides:
|
|
422
|
+
|
|
423
|
+
- **CacheModule**: Caching with `@Cacheable`, `@CacheEvict`, `@CachePut` decorators
|
|
424
|
+
- **QueueModule**: Job queue with `@Queue` and `@Cron` decorators
|
|
425
|
+
- **SessionModule**: Session management with `@Session` decorator
|
|
426
|
+
- **HealthModule**: Health checks with `/health` and `/ready` endpoints
|
|
427
|
+
- **MetricsModule**: Metrics collection with Prometheus support
|
|
428
|
+
- **DatabaseModule**: Database connection and ORM integration
|
|
429
|
+
- **ConfigCenterModule**: Configuration center (Nacos, Consul, etc.)
|
|
430
|
+
- **ServiceRegistryModule**: Service registry and discovery (Nacos, Consul, etc.)
|
|
431
|
+
|
|
432
|
+
For detailed documentation on these modules, see the [API Overview](./api.md).
|
|
433
|
+
|
|
381
434
|
### Complete Example
|
|
382
435
|
|
|
383
436
|
```typescript
|
package/docs/guide.md
CHANGED
|
@@ -25,6 +25,50 @@ app.listen();
|
|
|
25
25
|
> Tip: Default port is 3000, can be adjusted via `app.listen(customPort)` or
|
|
26
26
|
> `new Application({ port })`.
|
|
27
27
|
|
|
28
|
+
### Using BunServer (Low-level API)
|
|
29
|
+
|
|
30
|
+
For advanced use cases, you can use `BunServer` directly:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { BunServer } from "@dangao/bun-server";
|
|
34
|
+
|
|
35
|
+
const server = new BunServer({
|
|
36
|
+
port: 3000,
|
|
37
|
+
fetch: async (request) => {
|
|
38
|
+
// Custom request handling
|
|
39
|
+
return new Response("Hello World");
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
server.listen();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Accessing Request Context in Services
|
|
47
|
+
|
|
48
|
+
Use `ContextService` to access the current request context in services:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import {
|
|
52
|
+
ContextService,
|
|
53
|
+
CONTEXT_SERVICE_TOKEN,
|
|
54
|
+
Inject,
|
|
55
|
+
Injectable,
|
|
56
|
+
} from "@dangao/bun-server";
|
|
57
|
+
|
|
58
|
+
@Injectable()
|
|
59
|
+
class UserService {
|
|
60
|
+
public constructor(
|
|
61
|
+
@Inject(CONTEXT_SERVICE_TOKEN) private readonly contextService: ContextService,
|
|
62
|
+
) {}
|
|
63
|
+
|
|
64
|
+
public getCurrentUser() {
|
|
65
|
+
const ctx = this.contextService.getContext();
|
|
66
|
+
const userId = ctx.getHeader("x-user-id");
|
|
67
|
+
return { userId };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
28
72
|
## 2. Register Controllers and Dependencies
|
|
29
73
|
|
|
30
74
|
```ts
|
|
@@ -61,12 +105,68 @@ app.registerController(UserController);
|
|
|
61
105
|
app.listen();
|
|
62
106
|
```
|
|
63
107
|
|
|
108
|
+
### Advanced Parameter Binding
|
|
109
|
+
|
|
110
|
+
Bun Server supports advanced parameter binding decorators:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import {
|
|
114
|
+
Body,
|
|
115
|
+
Context,
|
|
116
|
+
Controller,
|
|
117
|
+
GET,
|
|
118
|
+
Header,
|
|
119
|
+
HeaderMap,
|
|
120
|
+
Param,
|
|
121
|
+
Query,
|
|
122
|
+
QueryMap,
|
|
123
|
+
} from "@dangao/bun-server";
|
|
124
|
+
|
|
125
|
+
@Controller("/api/users")
|
|
126
|
+
class UserController {
|
|
127
|
+
// Get single query parameter
|
|
128
|
+
@GET("/search")
|
|
129
|
+
public search(@Query("q") query: string) {
|
|
130
|
+
return { query };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Get all query parameters as an object
|
|
134
|
+
@GET("/filter")
|
|
135
|
+
public filter(@QueryMap() params: Record<string, string>) {
|
|
136
|
+
return { filters: params };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Get single header
|
|
140
|
+
@GET("/profile")
|
|
141
|
+
public getProfile(@Header("authorization") token: string) {
|
|
142
|
+
return { token };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Get all headers as an object
|
|
146
|
+
@GET("/headers")
|
|
147
|
+
public getHeaders(@HeaderMap() headers: Record<string, string>) {
|
|
148
|
+
return { headers };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Get full context object
|
|
152
|
+
@GET("/context")
|
|
153
|
+
public getContext(@Context() ctx: Context) {
|
|
154
|
+
return {
|
|
155
|
+
method: ctx.getMethod(),
|
|
156
|
+
path: ctx.getPath(),
|
|
157
|
+
query: ctx.getQuery(),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
64
163
|
## 3. Using Middleware
|
|
65
164
|
|
|
66
165
|
```ts
|
|
67
166
|
import {
|
|
68
167
|
createCorsMiddleware,
|
|
69
168
|
createLoggerMiddleware,
|
|
169
|
+
createRateLimitMiddleware,
|
|
70
170
|
} from "@dangao/bun-server";
|
|
71
171
|
|
|
72
172
|
const app = new Application({ port: 3000 });
|
|
@@ -75,6 +175,14 @@ const app = new Application({ port: 3000 });
|
|
|
75
175
|
app.use(createLoggerMiddleware({ prefix: "[App]" }));
|
|
76
176
|
app.use(createCorsMiddleware({ origin: "*" }));
|
|
77
177
|
|
|
178
|
+
// Rate limiting middleware
|
|
179
|
+
app.use(
|
|
180
|
+
createRateLimitMiddleware({
|
|
181
|
+
windowMs: 60000, // 1 minute
|
|
182
|
+
max: 100, // 100 requests per window
|
|
183
|
+
}),
|
|
184
|
+
);
|
|
185
|
+
|
|
78
186
|
// Custom middleware
|
|
79
187
|
app.use(async (ctx, next) => {
|
|
80
188
|
console.log("Before request");
|
|
@@ -84,6 +192,29 @@ app.use(async (ctx, next) => {
|
|
|
84
192
|
});
|
|
85
193
|
```
|
|
86
194
|
|
|
195
|
+
### Rate Limiting Decorator
|
|
196
|
+
|
|
197
|
+
You can also use the `@RateLimit()` decorator on controllers or methods:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
import { Controller, GET, RateLimit } from "@dangao/bun-server";
|
|
201
|
+
|
|
202
|
+
@Controller("/api")
|
|
203
|
+
@RateLimit({ windowMs: 60000, max: 10 }) // Applied to all methods
|
|
204
|
+
class ApiController {
|
|
205
|
+
@GET("/public")
|
|
206
|
+
public publicEndpoint() {
|
|
207
|
+
return { message: "Public" };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@GET("/limited")
|
|
211
|
+
@RateLimit({ windowMs: 60000, max: 5 }) // Override controller limit
|
|
212
|
+
public limitedEndpoint() {
|
|
213
|
+
return { message: "Limited" };
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
87
218
|
## 4. Parameter Validation
|
|
88
219
|
|
|
89
220
|
```ts
|
|
@@ -125,6 +256,7 @@ app.listen();
|
|
|
125
256
|
import {
|
|
126
257
|
createFileUploadMiddleware,
|
|
127
258
|
createStaticFileMiddleware,
|
|
259
|
+
FileStorage,
|
|
128
260
|
} from "@dangao/bun-server";
|
|
129
261
|
|
|
130
262
|
const app = new Application({ port: 3000 });
|
|
@@ -134,6 +266,22 @@ app.use(createFileUploadMiddleware({ maxSize: 5 * 1024 * 1024 }));
|
|
|
134
266
|
|
|
135
267
|
// Static files
|
|
136
268
|
app.use(createStaticFileMiddleware({ root: "./public", prefix: "/assets" }));
|
|
269
|
+
|
|
270
|
+
// Using FileStorage service
|
|
271
|
+
@Injectable()
|
|
272
|
+
class FileService {
|
|
273
|
+
public constructor(
|
|
274
|
+
@Inject(FileStorage) private readonly fileStorage: FileStorage,
|
|
275
|
+
) {}
|
|
276
|
+
|
|
277
|
+
public async saveFile(file: File): Promise<string> {
|
|
278
|
+
const path = await this.fileStorage.save(file, {
|
|
279
|
+
directory: "./uploads",
|
|
280
|
+
filename: `file-${Date.now()}`,
|
|
281
|
+
});
|
|
282
|
+
return path;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
137
285
|
```
|
|
138
286
|
|
|
139
287
|
## 7. Error Handling and Custom Filters
|
|
@@ -928,7 +1076,101 @@ class AppService {
|
|
|
928
1076
|
}
|
|
929
1077
|
```
|
|
930
1078
|
|
|
931
|
-
## 19.
|
|
1079
|
+
## 19. Microservice Support
|
|
1080
|
+
|
|
1081
|
+
Bun Server provides comprehensive microservice architecture support, including configuration center, service registry, service client, governance, and observability.
|
|
1082
|
+
|
|
1083
|
+
### Configuration Center
|
|
1084
|
+
|
|
1085
|
+
```ts
|
|
1086
|
+
import {
|
|
1087
|
+
ConfigCenterModule,
|
|
1088
|
+
CONFIG_CENTER_TOKEN,
|
|
1089
|
+
Inject,
|
|
1090
|
+
Injectable,
|
|
1091
|
+
} from "@dangao/bun-server";
|
|
1092
|
+
import type { ConfigCenter } from "@dangao/bun-server";
|
|
1093
|
+
|
|
1094
|
+
ConfigCenterModule.forRoot({
|
|
1095
|
+
provider: "nacos",
|
|
1096
|
+
nacos: {
|
|
1097
|
+
client: {
|
|
1098
|
+
serverList: ["http://localhost:8848"],
|
|
1099
|
+
namespace: "public",
|
|
1100
|
+
},
|
|
1101
|
+
},
|
|
1102
|
+
});
|
|
1103
|
+
|
|
1104
|
+
@Injectable()
|
|
1105
|
+
class ConfigService {
|
|
1106
|
+
public constructor(
|
|
1107
|
+
@Inject(CONFIG_CENTER_TOKEN) private readonly configCenter: ConfigCenter,
|
|
1108
|
+
) {}
|
|
1109
|
+
|
|
1110
|
+
public async getConfig() {
|
|
1111
|
+
const config = await this.configCenter.getConfig(
|
|
1112
|
+
"my-config",
|
|
1113
|
+
"DEFAULT_GROUP",
|
|
1114
|
+
);
|
|
1115
|
+
return JSON.parse(config.content);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
```
|
|
1119
|
+
|
|
1120
|
+
### Service Registry
|
|
1121
|
+
|
|
1122
|
+
```ts
|
|
1123
|
+
import {
|
|
1124
|
+
RegisterService,
|
|
1125
|
+
ServiceRegistryModule,
|
|
1126
|
+
} from "@dangao/bun-server";
|
|
1127
|
+
|
|
1128
|
+
ServiceRegistryModule.forRoot({
|
|
1129
|
+
provider: "nacos",
|
|
1130
|
+
nacos: {
|
|
1131
|
+
client: {
|
|
1132
|
+
serverList: ["http://localhost:8848"],
|
|
1133
|
+
},
|
|
1134
|
+
},
|
|
1135
|
+
});
|
|
1136
|
+
|
|
1137
|
+
@Injectable()
|
|
1138
|
+
class MyService {
|
|
1139
|
+
@RegisterService({
|
|
1140
|
+
serviceName: "my-service",
|
|
1141
|
+
ip: "127.0.0.1",
|
|
1142
|
+
port: 3000,
|
|
1143
|
+
})
|
|
1144
|
+
public start() {
|
|
1145
|
+
// Service registered
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
```
|
|
1149
|
+
|
|
1150
|
+
### Service Client
|
|
1151
|
+
|
|
1152
|
+
```ts
|
|
1153
|
+
import {
|
|
1154
|
+
ServiceClient,
|
|
1155
|
+
ServiceCall,
|
|
1156
|
+
Injectable,
|
|
1157
|
+
} from "@dangao/bun-server";
|
|
1158
|
+
|
|
1159
|
+
@Injectable()
|
|
1160
|
+
class OrderService {
|
|
1161
|
+
@ServiceClient("user-service")
|
|
1162
|
+
private readonly userClient!: ServiceClient;
|
|
1163
|
+
|
|
1164
|
+
@ServiceCall("GET", "/users/:id")
|
|
1165
|
+
public async getUser(id: string) {
|
|
1166
|
+
return await this.userClient.call("GET", `/users/${id}`);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
```
|
|
1170
|
+
|
|
1171
|
+
For detailed documentation, see [Microservice Architecture](./microservice.md).
|
|
1172
|
+
|
|
1173
|
+
## 20. Testing Recommendations
|
|
932
1174
|
|
|
933
1175
|
- Use `tests/utils/test-port.ts` to get auto-incrementing ports, avoiding local
|
|
934
1176
|
conflicts.
|