@dangao/bun-server 1.7.1 → 1.8.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.
Files changed (159) hide show
  1. package/README.md +129 -21
  2. package/dist/di/decorators.d.ts +37 -0
  3. package/dist/di/decorators.d.ts.map +1 -1
  4. package/dist/di/index.d.ts +1 -1
  5. package/dist/di/index.d.ts.map +1 -1
  6. package/dist/di/module-registry.d.ts +17 -0
  7. package/dist/di/module-registry.d.ts.map +1 -1
  8. package/dist/events/decorators.d.ts +52 -0
  9. package/dist/events/decorators.d.ts.map +1 -0
  10. package/dist/events/event-module.d.ts +97 -0
  11. package/dist/events/event-module.d.ts.map +1 -0
  12. package/dist/events/index.d.ts +5 -0
  13. package/dist/events/index.d.ts.map +1 -0
  14. package/dist/events/service.d.ts +76 -0
  15. package/dist/events/service.d.ts.map +1 -0
  16. package/dist/events/types.d.ts +184 -0
  17. package/dist/events/types.d.ts.map +1 -0
  18. package/dist/index.d.ts +5 -3
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1511 -11
  21. package/dist/security/filter.d.ts +23 -0
  22. package/dist/security/filter.d.ts.map +1 -1
  23. package/dist/security/guards/builtin/auth-guard.d.ts +44 -0
  24. package/dist/security/guards/builtin/auth-guard.d.ts.map +1 -0
  25. package/dist/security/guards/builtin/index.d.ts +3 -0
  26. package/dist/security/guards/builtin/index.d.ts.map +1 -0
  27. package/dist/security/guards/builtin/roles-guard.d.ts +66 -0
  28. package/dist/security/guards/builtin/roles-guard.d.ts.map +1 -0
  29. package/dist/security/guards/decorators.d.ts +50 -0
  30. package/dist/security/guards/decorators.d.ts.map +1 -0
  31. package/dist/security/guards/execution-context.d.ts +56 -0
  32. package/dist/security/guards/execution-context.d.ts.map +1 -0
  33. package/dist/security/guards/guard-registry.d.ts +67 -0
  34. package/dist/security/guards/guard-registry.d.ts.map +1 -0
  35. package/dist/security/guards/index.d.ts +7 -0
  36. package/dist/security/guards/index.d.ts.map +1 -0
  37. package/dist/security/guards/reflector.d.ts +57 -0
  38. package/dist/security/guards/reflector.d.ts.map +1 -0
  39. package/dist/security/guards/types.d.ts +126 -0
  40. package/dist/security/guards/types.d.ts.map +1 -0
  41. package/dist/security/index.d.ts +1 -0
  42. package/dist/security/index.d.ts.map +1 -1
  43. package/dist/security/security-module.d.ts +20 -0
  44. package/dist/security/security-module.d.ts.map +1 -1
  45. package/dist/validation/class-validator.d.ts +108 -0
  46. package/dist/validation/class-validator.d.ts.map +1 -0
  47. package/dist/validation/custom-validator.d.ts +130 -0
  48. package/dist/validation/custom-validator.d.ts.map +1 -0
  49. package/dist/validation/errors.d.ts +22 -2
  50. package/dist/validation/errors.d.ts.map +1 -1
  51. package/dist/validation/index.d.ts +7 -1
  52. package/dist/validation/index.d.ts.map +1 -1
  53. package/dist/validation/rules/array.d.ts +33 -0
  54. package/dist/validation/rules/array.d.ts.map +1 -0
  55. package/dist/validation/rules/common.d.ts +90 -0
  56. package/dist/validation/rules/common.d.ts.map +1 -0
  57. package/dist/validation/rules/conditional.d.ts +30 -0
  58. package/dist/validation/rules/conditional.d.ts.map +1 -0
  59. package/dist/validation/rules/index.d.ts +5 -0
  60. package/dist/validation/rules/index.d.ts.map +1 -0
  61. package/dist/validation/rules/object.d.ts +30 -0
  62. package/dist/validation/rules/object.d.ts.map +1 -0
  63. package/dist/validation/types.d.ts +52 -1
  64. package/dist/validation/types.d.ts.map +1 -1
  65. package/docs/events.md +494 -0
  66. package/docs/guards.md +376 -0
  67. package/docs/guide.md +309 -1
  68. package/docs/request-lifecycle.md +444 -0
  69. package/docs/validation.md +407 -0
  70. package/docs/zh/events.md +494 -0
  71. package/docs/zh/guards.md +376 -0
  72. package/docs/zh/guide.md +309 -1
  73. package/docs/zh/request-lifecycle.md +444 -0
  74. package/docs/zh/validation.md +407 -0
  75. package/package.json +1 -1
  76. package/src/di/decorators.ts +46 -0
  77. package/src/di/index.ts +10 -1
  78. package/src/di/module-registry.ts +39 -0
  79. package/src/events/decorators.ts +103 -0
  80. package/src/events/event-module.ts +272 -0
  81. package/src/events/index.ts +32 -0
  82. package/src/events/service.ts +352 -0
  83. package/src/events/types.ts +223 -0
  84. package/src/index.ts +133 -1
  85. package/src/security/filter.ts +88 -8
  86. package/src/security/guards/builtin/auth-guard.ts +68 -0
  87. package/src/security/guards/builtin/index.ts +3 -0
  88. package/src/security/guards/builtin/roles-guard.ts +165 -0
  89. package/src/security/guards/decorators.ts +124 -0
  90. package/src/security/guards/execution-context.ts +152 -0
  91. package/src/security/guards/guard-registry.ts +164 -0
  92. package/src/security/guards/index.ts +7 -0
  93. package/src/security/guards/reflector.ts +99 -0
  94. package/src/security/guards/types.ts +144 -0
  95. package/src/security/index.ts +1 -0
  96. package/src/security/security-module.ts +72 -2
  97. package/src/validation/class-validator.ts +322 -0
  98. package/src/validation/custom-validator.ts +289 -0
  99. package/src/validation/errors.ts +50 -2
  100. package/src/validation/index.ts +103 -1
  101. package/src/validation/rules/array.ts +118 -0
  102. package/src/validation/rules/common.ts +286 -0
  103. package/src/validation/rules/conditional.ts +52 -0
  104. package/src/validation/rules/index.ts +51 -0
  105. package/src/validation/rules/object.ts +86 -0
  106. package/src/validation/types.ts +61 -1
  107. package/tests/auth/auth-decorators.test.ts +241 -0
  108. package/tests/auth/oauth2-service.test.ts +318 -0
  109. package/tests/cache/cache-decorators-extended.test.ts +272 -0
  110. package/tests/cache/cache-interceptors.test.ts +534 -0
  111. package/tests/cache/cache-service-proxy.test.ts +246 -0
  112. package/tests/cache/memory-cache-store.test.ts +155 -0
  113. package/tests/cache/redis-cache-store.test.ts +199 -0
  114. package/tests/config/config-center-integration.test.ts +334 -0
  115. package/tests/config/config-module-extended.test.ts +165 -0
  116. package/tests/controller/param-binder.test.ts +333 -0
  117. package/tests/di/global-module.test.ts +487 -0
  118. package/tests/error/error-handler.test.ts +166 -57
  119. package/tests/error/i18n-extended.test.ts +105 -0
  120. package/tests/events/event-decorators.test.ts +173 -0
  121. package/tests/events/event-emitter.test.ts +373 -0
  122. package/tests/events/event-listener-scanner.test.ts +114 -0
  123. package/tests/events/event-module.test.ts +204 -0
  124. package/tests/extensions/logger-module.test.ts +158 -0
  125. package/tests/files/file-storage.test.ts +136 -0
  126. package/tests/interceptor/base-interceptor.test.ts +605 -0
  127. package/tests/interceptor/builtin/cache-interceptor.test.ts +233 -86
  128. package/tests/interceptor/builtin/log-interceptor.test.ts +469 -0
  129. package/tests/interceptor/builtin/permission-interceptor.test.ts +219 -120
  130. package/tests/interceptor/interceptor-chain.test.ts +241 -189
  131. package/tests/interceptor/interceptor-metadata.test.ts +221 -0
  132. package/tests/microservice/circuit-breaker.test.ts +221 -0
  133. package/tests/microservice/service-client-decorators.test.ts +86 -0
  134. package/tests/microservice/service-client-interceptors.test.ts +274 -0
  135. package/tests/microservice/service-registry-decorators.test.ts +147 -0
  136. package/tests/microservice/tracer.test.ts +213 -0
  137. package/tests/microservice/tracing-collectors.test.ts +168 -0
  138. package/tests/middleware/builtin/middleware-builtin-extended.test.ts +237 -0
  139. package/tests/middleware/builtin/rate-limit.test.ts +257 -0
  140. package/tests/middleware/middleware-decorators.test.ts +222 -0
  141. package/tests/middleware/middleware-pipeline.test.ts +160 -0
  142. package/tests/queue/queue-decorators.test.ts +139 -0
  143. package/tests/queue/queue-service.test.ts +191 -0
  144. package/tests/request/body-parser-extended.test.ts +291 -0
  145. package/tests/request/request-wrapper.test.ts +319 -0
  146. package/tests/router/router-decorators.test.ts +260 -0
  147. package/tests/router/router-extended.test.ts +298 -0
  148. package/tests/security/guards/guards-integration.test.ts +371 -0
  149. package/tests/security/guards/guards.test.ts +775 -0
  150. package/tests/security/guards/reflector.test.ts +188 -0
  151. package/tests/security/security-filter.test.ts +182 -0
  152. package/tests/security/security-module-extended.test.ts +133 -0
  153. package/tests/security/security-module.test.ts +2 -2
  154. package/tests/session/memory-session-store.test.ts +172 -0
  155. package/tests/session/session-decorators.test.ts +163 -0
  156. package/tests/swagger/ui.test.ts +212 -0
  157. package/tests/validation/class-validator.test.ts +349 -0
  158. package/tests/validation/custom-validator.test.ts +335 -0
  159. package/tests/validation/rules.test.ts +543 -0
@@ -0,0 +1,407 @@
1
+ # Validation System
2
+
3
+ Bun Server Framework provides a powerful validation system for validating request parameters, DTOs, and complex data structures.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Basic Validation](#basic-validation)
8
+ - [Validation Rules](#validation-rules)
9
+ - [Object Rules](#object-rules)
10
+ - [Array Rules](#array-rules)
11
+ - [Common Rules](#common-rules)
12
+ - [Conditional Rules](#conditional-rules)
13
+ - [Class-Level Validation](#class-level-validation)
14
+ - [Nested Object Validation](#nested-object-validation)
15
+ - [Custom Validators](#custom-validators)
16
+ - [Built-in Extended Validators](#built-in-extended-validators)
17
+ - [Error Handling](#error-handling)
18
+
19
+ ## Basic Validation
20
+
21
+ Use the `@Validate()` decorator on controller method parameters:
22
+
23
+ ```typescript
24
+ import { Controller, GET, Query, Validate, IsString, IsEmail, IsOptional, MinLength } from '@dangao/bun-server';
25
+
26
+ @Controller('/api/users')
27
+ class UserController {
28
+ @GET('/search')
29
+ public search(
30
+ @Query('email') @Validate(IsEmail()) email: string,
31
+ @Query('name') @Validate(IsOptional(), IsString(), MinLength(2)) name?: string,
32
+ ) {
33
+ return { email, name };
34
+ }
35
+ }
36
+ ```
37
+
38
+ ## Validation Rules
39
+
40
+ ### Object Rules
41
+
42
+ ```typescript
43
+ import { IsObject, IsNotEmpty, IsNotEmptyObject, ValidateNested } from '@dangao/bun-server';
44
+
45
+ // Validate value is an object
46
+ IsObject()
47
+
48
+ // Validate value is not empty (null, undefined, empty string, empty array, empty object)
49
+ IsNotEmpty()
50
+
51
+ // Validate value is a non-empty object
52
+ IsNotEmptyObject()
53
+
54
+ // Mark property for nested validation
55
+ ValidateNested({ each?: boolean }) // each: true for array elements
56
+ ```
57
+
58
+ ### Array Rules
59
+
60
+ ```typescript
61
+ import {
62
+ IsArray, ArrayMinSize, ArrayMaxSize, ArrayUnique,
63
+ ArrayContains, ArrayNotContains, ArrayNotEmpty
64
+ } from '@dangao/bun-server';
65
+
66
+ // Validate value is an array
67
+ IsArray()
68
+
69
+ // Validate array minimum length
70
+ ArrayMinSize(2)
71
+
72
+ // Validate array maximum length
73
+ ArrayMaxSize(10)
74
+
75
+ // Validate array elements are unique
76
+ ArrayUnique()
77
+
78
+ // Validate array contains specific values
79
+ ArrayContains([1, 2])
80
+
81
+ // Validate array does not contain specific values
82
+ ArrayNotContains(['banned'])
83
+
84
+ // Validate array is not empty
85
+ ArrayNotEmpty()
86
+ ```
87
+
88
+ ### Common Rules
89
+
90
+ ```typescript
91
+ import {
92
+ IsString, IsNumber, IsBoolean, IsInt, IsPositive, IsNegative,
93
+ Min, Max, IsDate, IsUUID, Length, MaxLength, MinLength,
94
+ Matches, IsIn, IsNotIn, IsUrl, IsJSON, IsEmail,
95
+ Equals, NotEquals, IsDefined, IsAlphanumeric, IsAlpha, IsNumberString
96
+ } from '@dangao/bun-server';
97
+
98
+ // Type validation
99
+ IsString()
100
+ IsNumber()
101
+ IsBoolean()
102
+ IsInt()
103
+ IsDate()
104
+
105
+ // Number validation
106
+ IsPositive()
107
+ IsNegative()
108
+ Min(0)
109
+ Max(100)
110
+
111
+ // String validation
112
+ IsEmail()
113
+ IsUUID('4') // '3', '4', '5', or 'all'
114
+ Length(2, 10)
115
+ MinLength(2)
116
+ MaxLength(10)
117
+ Matches(/^[a-z]+$/)
118
+ IsUrl()
119
+ IsJSON()
120
+ IsAlphanumeric()
121
+ IsAlpha()
122
+ IsNumberString()
123
+
124
+ // Value validation
125
+ IsIn(['a', 'b', 'c'])
126
+ IsNotIn(['x', 'y', 'z'])
127
+ Equals('expected')
128
+ NotEquals('forbidden')
129
+ IsDefined()
130
+ ```
131
+
132
+ ### Conditional Rules
133
+
134
+ ```typescript
135
+ import { ValidateIf, Transform } from '@dangao/bun-server';
136
+
137
+ // Conditional validation - only validate when condition is true
138
+ ValidateIf((value, obj) => obj.type === 'premium')
139
+
140
+ // Transform value before validation
141
+ Transform((value) => String(value).trim())
142
+ Transform((value) => Number(value))
143
+ ```
144
+
145
+ Example usage:
146
+
147
+ ```typescript
148
+ @ValidateClass()
149
+ class UpdateUserDto {
150
+ @Property(ValidateIf((_, obj) => obj.type === 'premium'), IsEmail())
151
+ premiumEmail?: string;
152
+
153
+ @Property(Transform((v) => String(v).trim()), IsString(), MinLength(1))
154
+ name: string;
155
+
156
+ @Property(Transform((v) => Number(v)), IsInt(), Min(0))
157
+ age: number;
158
+ }
159
+ ```
160
+
161
+ ## Class-Level Validation
162
+
163
+ For DTO classes, use `@ValidateClass()` and `@Property()` decorators:
164
+
165
+ ```typescript
166
+ import { ValidateClass, Property, IsString, IsEmail, IsOptional, IsInt, Min, Max, MinLength } from '@dangao/bun-server';
167
+
168
+ @ValidateClass()
169
+ class CreateUserDto {
170
+ @Property(IsString(), MinLength(2))
171
+ name: string;
172
+
173
+ @Property(IsEmail())
174
+ email: string;
175
+
176
+ @Property(IsOptional(), IsInt(), Min(0), Max(150))
177
+ age?: number;
178
+ }
179
+ ```
180
+
181
+ Validate objects manually:
182
+
183
+ ```typescript
184
+ import { validateObject, validateObjectSync, ValidationError } from '@dangao/bun-server';
185
+
186
+ // Throws ValidationError on failure
187
+ try {
188
+ validateObject(data, CreateUserDto);
189
+ } catch (error) {
190
+ if (error instanceof ValidationError) {
191
+ console.log(error.issues);
192
+ }
193
+ }
194
+
195
+ // Returns validation result without throwing
196
+ const result = validateObjectSync(data, CreateUserDto);
197
+ if (!result.valid) {
198
+ console.log(result.issues);
199
+ }
200
+ ```
201
+
202
+ ## Nested Object Validation
203
+
204
+ For nested objects and arrays:
205
+
206
+ ```typescript
207
+ import { ValidateClass, Property, NestedProperty, ArrayNestedProperty, IsString, IsNumber, Min, IsArray, ArrayMinSize } from '@dangao/bun-server';
208
+
209
+ @ValidateClass()
210
+ class AddressDto {
211
+ @Property(IsString())
212
+ city: string;
213
+
214
+ @Property(IsString())
215
+ street: string;
216
+ }
217
+
218
+ @ValidateClass()
219
+ class ItemDto {
220
+ @Property(IsString())
221
+ name: string;
222
+
223
+ @Property(IsNumber(), Min(0))
224
+ price: number;
225
+ }
226
+
227
+ @ValidateClass()
228
+ class CreateOrderDto {
229
+ @Property(IsString())
230
+ userId: string;
231
+
232
+ // Nested object validation
233
+ @NestedProperty(AddressDto)
234
+ shippingAddress: AddressDto;
235
+
236
+ // Array of nested objects validation
237
+ @Property(IsArray(), ArrayMinSize(1))
238
+ @ArrayNestedProperty(ItemDto)
239
+ items: ItemDto[];
240
+ }
241
+ ```
242
+
243
+ ## Custom Validators
244
+
245
+ ### Simple Custom Validator
246
+
247
+ ```typescript
248
+ import { createSimpleValidator } from '@dangao/bun-server';
249
+
250
+ const IsEven = createSimpleValidator(
251
+ 'isEven',
252
+ (value) => typeof value === 'number' && value % 2 === 0,
253
+ 'Must be an even number'
254
+ );
255
+
256
+ // Usage
257
+ @Property(IsEven())
258
+ count: number;
259
+ ```
260
+
261
+ ### Parameterized Custom Validator
262
+
263
+ ```typescript
264
+ import { createCustomValidator } from '@dangao/bun-server';
265
+
266
+ const IsDivisibleBy = createCustomValidator(
267
+ 'isDivisibleBy',
268
+ (value: unknown, divisor: number) => typeof value === 'number' && value % divisor === 0,
269
+ (divisor: number) => `Must be divisible by ${divisor}`
270
+ );
271
+
272
+ // Usage
273
+ @Property(IsDivisibleBy(5)())
274
+ value: number;
275
+ ```
276
+
277
+ ### Regex Custom Validator
278
+
279
+ ```typescript
280
+ import { createRegexValidator } from '@dangao/bun-server';
281
+
282
+ const IsSlug = createRegexValidator(
283
+ 'isSlug',
284
+ /^[a-z0-9]+(?:-[a-z0-9]+)*$/,
285
+ 'Must be a valid slug format'
286
+ );
287
+
288
+ // Usage
289
+ @Property(IsSlug())
290
+ slug: string;
291
+ ```
292
+
293
+ ## Built-in Extended Validators
294
+
295
+ The framework provides several pre-built validators for common use cases:
296
+
297
+ ```typescript
298
+ import {
299
+ IsPhoneNumber, // Chinese phone number
300
+ IsIdCard, // Chinese ID card
301
+ IsIPv4, // IPv4 address
302
+ IsPort, // Port number (0-65535)
303
+ IsPostalCode, // Chinese postal code
304
+ IsCreditCard, // Credit card (Luhn algorithm)
305
+ IsHexColor, // Hex color (#fff or #ffffff)
306
+ IsMacAddress, // MAC address
307
+ IsSemVer, // Semantic version
308
+ IsDivisibleBy, // Divisible by number
309
+ IsBetween, // Number in range
310
+ Contains, // String contains substring
311
+ NotContains, // String does not contain substring
312
+ } from '@dangao/bun-server';
313
+
314
+ // Usage examples
315
+ @Property(IsPhoneNumber())
316
+ phone: string;
317
+
318
+ @Property(IsIPv4())
319
+ ip: string;
320
+
321
+ @Property(IsBetween(1, 100)())
322
+ percentage: number;
323
+
324
+ @Property(Contains('http')())
325
+ url: string;
326
+ ```
327
+
328
+ ## Error Handling
329
+
330
+ ### ValidationError
331
+
332
+ When validation fails, a `ValidationError` is thrown:
333
+
334
+ ```typescript
335
+ import { ValidationError, ValidationIssue } from '@dangao/bun-server';
336
+
337
+ try {
338
+ validateObject(data, MyDto);
339
+ } catch (error) {
340
+ if (error instanceof ValidationError) {
341
+ // Access validation issues
342
+ console.log(error.issues);
343
+
344
+ // Get flattened errors (useful for nested objects)
345
+ console.log(error.getFlattened());
346
+
347
+ // Convert to JSON
348
+ console.log(error.toJSON());
349
+ }
350
+ }
351
+ ```
352
+
353
+ ### ValidationIssue Structure
354
+
355
+ ```typescript
356
+ interface ValidationIssue {
357
+ index?: number; // Parameter index (for parameter validation)
358
+ property?: string; // Property path (e.g., 'user.address.city')
359
+ rule: string; // Failed rule name
360
+ message: string; // Error message
361
+ value?: unknown; // The value that failed validation
362
+ children?: ValidationIssue[]; // Nested errors
363
+ }
364
+ ```
365
+
366
+ ### Controller Integration
367
+
368
+ Validation errors are automatically caught and returned as 400 Bad Request responses:
369
+
370
+ ```typescript
371
+ @Controller('/api/users')
372
+ class UserController {
373
+ @POST('/')
374
+ public async createUser(@Body() @Validate(IsObject()) body: unknown) {
375
+ const dto = body as CreateUserDto;
376
+ validateObject(dto, CreateUserDto);
377
+ // ... create user
378
+ }
379
+ }
380
+ ```
381
+
382
+ ## Best Practices
383
+
384
+ 1. **Use DTOs for complex validation**: For request bodies with multiple fields, use `@ValidateClass()` decorated DTOs.
385
+
386
+ 2. **Combine rules**: Chain multiple rules for comprehensive validation:
387
+ ```typescript
388
+ @Property(IsString(), MinLength(2), MaxLength(50), Matches(/^[a-zA-Z\s]+$/))
389
+ name: string;
390
+ ```
391
+
392
+ 3. **Use IsOptional() first**: Always place `IsOptional()` at the beginning of the rule chain:
393
+ ```typescript
394
+ @Property(IsOptional(), IsString(), MinLength(2))
395
+ nickname?: string;
396
+ ```
397
+
398
+ 4. **Transform before validate**: Use `Transform()` to normalize data before validation:
399
+ ```typescript
400
+ @Property(Transform((v) => String(v).toLowerCase().trim()), IsEmail())
401
+ email: string;
402
+ ```
403
+
404
+ 5. **Custom error messages**: Provide clear, user-friendly error messages:
405
+ ```typescript
406
+ IsEmail({ message: 'Please enter a valid email address' })
407
+ ```