wynkjs 1.0.3 → 1.0.6

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 (63) hide show
  1. package/README.md +528 -348
  2. package/dist/cors.d.ts +28 -0
  3. package/dist/cors.d.ts.map +1 -0
  4. package/dist/cors.js +121 -0
  5. package/dist/database.d.ts +1 -1
  6. package/dist/database.js +1 -1
  7. package/dist/decorators/exception.advanced.d.ts +286 -18
  8. package/dist/decorators/exception.advanced.d.ts.map +1 -1
  9. package/dist/decorators/exception.advanced.js +410 -17
  10. package/dist/decorators/exception.decorators.d.ts +93 -2
  11. package/dist/decorators/exception.decorators.d.ts.map +1 -1
  12. package/dist/decorators/exception.decorators.js +140 -8
  13. package/dist/decorators/formatter.decorators.d.ts +93 -0
  14. package/dist/decorators/formatter.decorators.d.ts.map +1 -0
  15. package/dist/decorators/formatter.decorators.js +131 -0
  16. package/dist/decorators/guard.decorators.d.ts +2 -2
  17. package/dist/decorators/guard.decorators.d.ts.map +1 -1
  18. package/dist/decorators/guard.decorators.js +11 -5
  19. package/dist/decorators/http.decorators.d.ts +10 -4
  20. package/dist/decorators/http.decorators.d.ts.map +1 -1
  21. package/dist/decorators/http.decorators.js +9 -2
  22. package/dist/decorators/interceptor.advanced.d.ts +9 -9
  23. package/dist/decorators/interceptor.advanced.d.ts.map +1 -1
  24. package/dist/decorators/interceptor.advanced.js +7 -7
  25. package/dist/decorators/interceptor.decorators.d.ts +9 -7
  26. package/dist/decorators/interceptor.decorators.d.ts.map +1 -1
  27. package/dist/decorators/interceptor.decorators.js +29 -18
  28. package/dist/decorators/param.decorators.d.ts +2 -2
  29. package/dist/decorators/param.decorators.js +1 -1
  30. package/dist/decorators/pipe.decorators.d.ts +4 -4
  31. package/dist/decorators/pipe.decorators.d.ts.map +1 -1
  32. package/dist/decorators/pipe.decorators.js +4 -4
  33. package/dist/dto.js +1 -1
  34. package/dist/factory.d.ts +30 -2
  35. package/dist/factory.d.ts.map +1 -1
  36. package/dist/factory.js +210 -186
  37. package/dist/filters/exception.filters.d.ts +124 -0
  38. package/dist/filters/exception.filters.d.ts.map +1 -0
  39. package/dist/filters/exception.filters.js +208 -0
  40. package/dist/global-prefix.d.ts +49 -0
  41. package/dist/global-prefix.d.ts.map +1 -0
  42. package/dist/global-prefix.js +155 -0
  43. package/dist/index.d.ts +7 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +6 -1
  46. package/dist/interfaces/interceptor.interface.d.ts +15 -0
  47. package/dist/interfaces/interceptor.interface.d.ts.map +1 -0
  48. package/dist/interfaces/interceptor.interface.js +1 -0
  49. package/dist/optimized-handler.d.ts +31 -0
  50. package/dist/optimized-handler.d.ts.map +1 -0
  51. package/dist/optimized-handler.js +180 -0
  52. package/dist/pipes/validation.pipe.d.ts +12 -12
  53. package/dist/pipes/validation.pipe.d.ts.map +1 -1
  54. package/dist/pipes/validation.pipe.js +43 -15
  55. package/dist/schema-registry.d.ts +51 -0
  56. package/dist/schema-registry.d.ts.map +1 -0
  57. package/dist/schema-registry.js +134 -0
  58. package/dist/testing/index.d.ts +2 -2
  59. package/dist/testing/index.js +2 -2
  60. package/dist/ultra-optimized-handler.d.ts +51 -0
  61. package/dist/ultra-optimized-handler.d.ts.map +1 -0
  62. package/dist/ultra-optimized-handler.js +302 -0
  63. package/package.json +17 -10
package/README.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  <div align="center">
4
4
 
5
- **A high-performance TypeScript framework built on Elysia for Bun with NestJS-style decorators**
5
+ **A high-performance TypeScript first framework built for Bun with Elegant Decorator-Based Architecture**
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/wynkjs.svg)](https://www.npmjs.com/package/wynkjs)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
9
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
10
10
  [![Bun](https://img.shields.io/badge/Bun-1.0+-black.svg)](https://bun.sh/)
11
11
 
12
- _20x faster than Express, easier than NestJS, built for Bun_ ⚡
12
+ _10x faster than Express/NestJs, built for modern TypeScript development for Bun_ ⚡
13
13
 
14
14
  [Quick Start](#-quick-start) • [CLI Tools](#️-cli-tools) • [Features](#-features--examples) • [Documentation](#-documentation)
15
15
 
@@ -19,32 +19,18 @@ _20x faster than Express, easier than NestJS, built for Bun_ ⚡
19
19
 
20
20
  ## About
21
21
 
22
- WynkJS is a modern, TypeScript-first web framework that brings NestJS-style decorators to the blazing-fast Elysia runtime built for **Bun**. It's a lightweight NestJS alternative with familiar concepts—controllers, dependency injection, guards, pipes, interceptors, and exception filters—designed for building high‑performance REST APIs and backends on **Bun**. WynkJS embraces ESM, ships first-class types, and keeps things simple so you can move fast without the bloat.
22
+ WynkJS is a modern, TypeScript-first web framework alternative to NestJs that brings Elegant Decorator-Based Architecture to the blazing-fast Elysia runtime built for **Bun**. It features familiar concepts—**Controllers, Dependency Injection, Guards, Pipes, Interceptors, and Exception Filters**—designed for building high‑performance REST APIs and backends on **Bun**. WynkJS embraces ESM, ships first-class types, and keeps things simple so you can move fast without the bloat.
23
23
 
24
- **🚀 Get Started in 30 Seconds:**
25
-
26
- ```bash
27
- bunx create-wynkjs # Create new project
28
- cd my-wynkjs-app # Navigate to project
29
- bun run dev # Start server with hot reload
30
- ```
31
-
32
- Then generate your first API module:
33
-
34
- ```bash
35
- wynkjs g m product # Generate complete CRUD module
36
- ```
37
-
38
- Keywords: NestJS alternative, Elysia framework, Bun framework, TypeScript decorators, dependency injection (DI), guards, pipes, interceptors, exception filters, fast web framework, REST API, backend.
24
+ Keywords: Bun framework, Fast web server, TypeScript decorators, dependency injection (DI), guards, pipes, interceptors, exception filters, fast web framework, REST API, backend, modern TypeScript.
39
25
 
40
26
  ---
41
27
 
42
28
  ## ✨ Why WynkJS?
43
29
 
44
- WynkJS combines the **speed of Elysia** with the **elegant decorator syntax of NestJS**, giving you the best of both worlds:
30
+ WynkJS combines the **speed of Elysia** with an **Elegant Decorator-Based Architecture**, giving you the best of both worlds:
45
31
 
46
- - 🚀 **20x Faster** - Built on Elysia, one of the fastest web frameworks for Bun
47
- - 🎨 **Decorator-Based** - Familiar NestJS-style decorators
32
+ - 🚀 **10x Faster** - One of the fastest web frameworks for Bun
33
+ - 🎨 **Decorator-Based** - Clean, intuitive decorator syntax for TypeScript
48
34
  - 💉 **Dependency Injection** - Built-in DI (no need to import reflect-metadata!)
49
35
  - 🔒 **TypeScript First** - TypeScript is mandatory, not optional. Full type safety and IntelliSense support
50
36
  - 🎯 **Simple & Clean** - Easy to learn, powerful to use
@@ -54,60 +40,98 @@ WynkJS combines the **speed of Elysia** with the **elegant decorator syntax of N
54
40
 
55
41
  ---
56
42
 
57
- ## 📦 Installation
58
-
59
- **Requirements:** Bun 1.0 or higher
43
+ ## 🚀 Get Started in 30 Seconds:
60
44
 
61
- ### Quick Start (Recommended)
45
+ ### 📦 create-wynkjs - Project Scaffolding
62
46
 
63
- Create a new WynkJS project with all best practices:
47
+ Quickly scaffold a new WynkJS project with best practices:
64
48
 
65
49
  ```bash
50
+ # Create a new project
66
51
  bunx create-wynkjs
67
52
  # or
68
53
  npx create-wynkjs
69
54
  ```
70
55
 
71
- This will scaffold a complete **TypeScript** project with:
72
-
73
- - ✅ TypeScript (strict mode, decorators enabled)
74
- - ✅ ESLint + Prettier (optional)
75
- - ✅ Hot reload with `bun --watch`
76
- - ✅ Example code (controllers, services, DTOs)
77
- - ✅ Git hooks (optional)
56
+ **What you get:**
78
57
 
79
- ### Manual Installation
58
+ - **TypeScript** - Strict mode with decorators enabled (mandatory)
59
+ - ✅ **ESLint** - Code linting with TypeScript rules (optional)
60
+ - ✅ **Prettier** - Code formatting (optional)
61
+ - ✅ **Husky** - Git hooks for pre-commit checks (optional)
62
+ - ✅ **Hot Reload** - `bun --watch` for instant feedback
63
+ - ✅ **Working Example** - Complete CRUD controller, service, and DTOs
80
64
 
81
- Add to an existing project:
65
+ **Generated Project Structure:**
82
66
 
83
- ```bash
84
- bun add wynkjs elysia
67
+ ```
68
+ my-wynkjs-app/
69
+ ├── src/
70
+ │ ├── modules/
71
+ │ │ └── user/
72
+ │ │ ├── user.controller.ts
73
+ │ │ ├── user.service.ts
74
+ │ │ └── user.dto.ts
75
+ │ └── index.ts
76
+ ├── .eslintrc.json
77
+ ├── .prettierrc
78
+ ├── tsconfig.json
79
+ └── package.json
85
80
  ```
86
81
 
87
- **Note**: WynkJS is built specifically for **Bun**. It leverages Elysia's performance optimizations that are designed for Bun runtime. ✨
82
+ **Available Scripts:**
88
83
 
89
- ---
84
+ - `bun run dev` - Development with hot reload
85
+ - `bun run start` - Production server
86
+ - `bun run build` - Build TypeScript
87
+ - `bun run lint` - Run ESLint
88
+ - `bun run format` - Format with Prettier
89
+
90
+ [Learn more about create-wynkjs](./packages/create-wynkjs/README.md)
90
91
 
91
- ## 🚀 Quick Start
92
+ **Example:**
93
+
94
+ ```bash
95
+ bunx create-wynkjs
96
+ # Choose project name: my-api
97
+ # Add ESLint? Yes
98
+ # Add Prettier? Yes
99
+ # Add Husky? No
100
+
101
+ cd my-api
102
+ bun run dev
103
+ # 🚀 Server running on http://localhost:3000
104
+ ```
92
105
 
93
- ### 1. Create Your DTOs (Data Transfer Objects)
106
+ ### 1. Find Your DTOs (Data Transfer Objects)
94
107
 
95
108
  ```typescript
96
109
  // user.dto.ts
97
110
  import { DTO, CommonDTO } from "wynkjs";
98
111
 
99
112
  export const CreateUserDTO = DTO.Strict({
100
- name: DTO.Optional(DTO.String({ minLength: 2, maxLength: 50 })),
113
+ name: DTO.Optional(
114
+ DTO.String({
115
+ maxLength: 50,
116
+ error: "Name must be between 2 and 50 characters",
117
+ })
118
+ ),
101
119
  email: CommonDTO.Email({
102
120
  description: "User email address",
121
+ error: "Please provide a valid email address",
103
122
  }),
104
123
  mobile: DTO.Optional(
105
124
  DTO.String({
106
125
  pattern: "^[6-9]{1}[0-9]{9}$",
107
- errorMessage: "Invalid mobile number",
126
+ error: "Invalid mobile number format",
127
+ })
128
+ ),
129
+ age: DTO.Optional(
130
+ DTO.Number({
131
+ minimum: 18,
132
+ error: "Age must be at least 18 years",
108
133
  })
109
134
  ),
110
- age: DTO.Optional(DTO.Number({ minimum: 18 })),
111
135
  });
112
136
 
113
137
  export interface CreateUserType {
@@ -126,7 +150,7 @@ export interface ParamIdType {
126
150
  }
127
151
  ```
128
152
 
129
- ### 2. Create a Service with Dependency Injection
153
+ ### 2. Find Your Service with Dependency Injection
130
154
 
131
155
  ```typescript
132
156
  // email.service.ts
@@ -141,7 +165,7 @@ export class EmailService {
141
165
  }
142
166
  ```
143
167
 
144
- ### 3. Create Your Controller
168
+ ### 3. Find Your Controller
145
169
 
146
170
  ```typescript
147
171
  // user.controller.ts
@@ -221,9 +245,9 @@ console.log("🚀 Server running on http://localhost:3000");
221
245
  ### 5. Run Your Server
222
246
 
223
247
  ```bash
224
- bun run index.ts
248
+ bun run start
225
249
  # or with --watch for hot reload
226
- bun --watch index.ts
250
+ bun run dev
227
251
  ```
228
252
 
229
253
  ### 6. Test Your API
@@ -254,25 +278,56 @@ That's it! 🎉
254
278
 
255
279
  ### HTTP Methods
256
280
 
281
+ All HTTP method decorators support both **string** and **object** formats:
282
+
257
283
  ```typescript
258
- @Get(path?: string) // GET request
259
- @Post(path?: string) // POST request
260
- @Put(path?: string) // PUT request
261
- @Patch(path?: string) // PATCH request
262
- @Delete(path?: string) // DELETE request
263
- @Options(path?: string) // OPTIONS request
264
- @Head(path?: string) // HEAD request
284
+ // Simple string format
285
+ @Get(path?: string)
286
+ @Post(path?: string)
287
+ @Put(path?: string)
288
+ @Patch(path?: string)
289
+ @Delete(path?: string)
290
+ @Options(path?: string)
291
+ @Head(path?: string)
292
+
293
+ // Object format with validation
294
+ @Get({ path?: string, params?: Schema, query?: Schema })
295
+ @Post({ path?: string, body?: Schema, params?: Schema, query?: Schema })
296
+ @Put({ path?: string, body?: Schema, params?: Schema, query?: Schema })
297
+ @Patch({ path?: string, body?: Schema, params?: Schema, query?: Schema })
298
+ @Delete({ path?: string, params?: Schema, query?: Schema })
299
+ ```
300
+
301
+ **Examples:**
302
+
303
+ ```typescript
304
+ // Simple string path
305
+ @Get("/users")
306
+ async findAll() { }
307
+
308
+ // Object with body validation
309
+ @Post({ path: "/users", body: CreateUserDTO })
310
+ async create(@Body() body: CreateUserType) { }
311
+
312
+ // Object with multiple validations
313
+ @Post({
314
+ path: "/:id1/:id2",
315
+ body: CreateUserDTO,
316
+ params: MultiParamDto,
317
+ query: UserQueryDto
318
+ })
319
+ async create(@Body() body, @Param("id1") id1, @Query() query) { }
265
320
  ```
266
321
 
267
322
  ### Parameter Decorators
268
323
 
269
324
  ```typescript
270
- @Param(key?: string) // Route parameters
271
- @Body() // Request body
272
- @Query(key?: string) // Query parameters
273
- @Headers(key?: string) // Request headers
274
- @Req() // Full request object
275
- @Res() // Full response object
325
+ @Param(key?: string) // Route parameters (single or all)
326
+ @Body() // Request body (validated by decorator schema)
327
+ @Query(key?: string) // Query parameters (single or all)
328
+ @Headers(key?: string) // Request headers (single or all)
329
+ @Req() // Full Elysia request object
330
+ @Res() // Full Elysia response object
276
331
  ```
277
332
 
278
333
  ### Route Options
@@ -299,40 +354,6 @@ That's it! 🎉
299
354
 
300
355
  WynkJS provides powerful CLI tools to speed up your development workflow:
301
356
 
302
- ### 📦 create-wynkjs - Project Scaffolding
303
-
304
- Quickly scaffold a new WynkJS project with best practices:
305
-
306
- ```bash
307
- # Create a new project
308
- bunx create-wynkjs
309
- # or
310
- npx create-wynkjs
311
- ```
312
-
313
- **What you get:**
314
-
315
- - ✅ **TypeScript** - Strict mode with decorators enabled (mandatory)
316
- - ✅ **ESLint** - Code linting with TypeScript rules (optional)
317
- - ✅ **Prettier** - Code formatting (optional)
318
- - ✅ **Husky** - Git hooks for pre-commit checks (optional)
319
- - ✅ **Hot Reload** - `bun --watch` for instant feedback
320
- - ✅ **Working Example** - Complete CRUD controller, service, and DTOs
321
-
322
- **Example:**
323
-
324
- ```bash
325
- bunx create-wynkjs
326
- # Choose project name: my-api
327
- # Add ESLint? Yes
328
- # Add Prettier? Yes
329
- # Add Husky? No
330
-
331
- cd my-api
332
- bun run dev
333
- # 🚀 Server running on http://localhost:3000
334
- ```
335
-
336
357
  ### ⚡ wynkjs-cli - Code Generator
337
358
 
338
359
  Generate modules, controllers, services, and DTOs instantly:
@@ -349,26 +370,26 @@ bun add -D wynkjs-cli
349
370
 
350
371
  ```bash
351
372
  # Generate complete CRUD module (controller + service + DTO)
352
- wynkjs generate module product
353
- # or short: wynkjs g m product
373
+ wynkjs-cli generate module product
374
+ # or short: wynkjs-cli g m product
354
375
 
355
376
  # Generate controller only (all HTTP methods)
356
- wynkjs generate controller user
357
- # or short: wynkjs g c user
377
+ wynkjs-cli generate controller user
378
+ # or short: wynkjs-cli g c user
358
379
 
359
380
  # Generate service only (all CRUD methods)
360
- wynkjs generate service order
361
- # or short: wynkjs g s order
381
+ wynkjs-cli generate service order
382
+ # or short: wynkjs-cli g s order
362
383
 
363
384
  # Generate DTO only (Create, Update, ID DTOs)
364
- wynkjs generate dto payment
365
- # or short: wynkjs g d payment
385
+ wynkjs-cli generate dto payment
386
+ # or short: wynkjs-cli g d payment
366
387
  ```
367
388
 
368
389
  **What it generates:**
369
390
 
370
391
  ```bash
371
- wynkjs g m product
392
+ wynkjs-cli g m product
372
393
  # Creates:
373
394
  # src/modules/product/
374
395
  # ├── product.controller.ts # Full CRUD controller
@@ -450,6 +471,45 @@ Create `wynkjs.config.json` in your project root:
450
471
 
451
472
  ## 🎯 Features & Examples
452
473
 
474
+ ### 🌐 Built-in CORS Support
475
+
476
+ WynkJS includes built-in CORS support - no additional packages needed!
477
+
478
+ ```typescript
479
+ import { WynkFactory, CorsOptions } from "wynkjs";
480
+
481
+ // Simple: Allow all origins (development)
482
+ const app = WynkFactory.create({
483
+ controllers: [UserController],
484
+ cors: true,
485
+ });
486
+
487
+ // Advanced: Custom CORS with specific origins (production)
488
+ const corsOptions: CorsOptions = {
489
+ origin: ["https://yourdomain.com", "https://app.yourdomain.com"],
490
+ credentials: true,
491
+ methods: ["GET", "POST", "PUT", "DELETE"],
492
+ allowedHeaders: ["Content-Type", "Authorization"],
493
+ maxAge: 86400, // 24 hours
494
+ };
495
+
496
+ const app = WynkFactory.create({
497
+ controllers: [UserController],
498
+ cors: corsOptions,
499
+ });
500
+
501
+ // Dynamic origin validation (NestJS-style)
502
+ const corsOptions: CorsOptions = {
503
+ origin: (origin: string) => {
504
+ const allowedOrigins = ["https://yourdomain.com"];
505
+ return allowedOrigins.includes(origin);
506
+ },
507
+ credentials: true,
508
+ };
509
+ ```
510
+
511
+ See [CORS.md](./CORS.md) for complete documentation.
512
+
453
513
  ### 🔒 Authentication with Guards
454
514
 
455
515
  ```typescript
@@ -561,7 +621,65 @@ export class UserController {
561
621
 
562
622
  - Capital: `Injectable`, `Inject`, `Singleton`, `AutoInjectable`, `Container`
563
623
 
564
- ### 🗃️ Database Integration (Drizzle ORM)
624
+ ### Provider System
625
+
626
+ WynkJS providers are singleton services that initialize when your app starts. Perfect for database connections, configuration, and external services:
627
+
628
+ ```typescript
629
+ import { Injectable, singleton } from "wynkjs";
630
+ import { drizzle } from "drizzle-orm/bun-sqlite";
631
+ import { Database } from "bun:sqlite";
632
+
633
+ @Injectable()
634
+ @singleton()
635
+ export class DatabaseService {
636
+ public db: any;
637
+ private sqlite: Database;
638
+
639
+ // Called automatically when app starts
640
+ async onModuleInit() {
641
+ console.log("🔌 Connecting to database...");
642
+ this.sqlite = new Database("mydb.sqlite", { create: true });
643
+ this.db = drizzle(this.sqlite);
644
+ console.log("✅ Database connected");
645
+ }
646
+
647
+ getDb() {
648
+ return this.db;
649
+ }
650
+ }
651
+
652
+ // Register provider in factory
653
+ const app = WynkFactory.create({
654
+ providers: [DatabaseService], // ✅ Initialized on startup
655
+ controllers: [UserController],
656
+ });
657
+
658
+ // Use in controllers/services
659
+ @Injectable()
660
+ @Controller("/users")
661
+ export class UserController {
662
+ constructor(private dbService: DatabaseService) {}
663
+
664
+ @Get("/")
665
+ async findAll() {
666
+ const db = this.dbService.getDb();
667
+ return await db.select().from(userTable);
668
+ }
669
+ }
670
+ ```
671
+
672
+ **Benefits:**
673
+
674
+ - ✅ **Automatic Initialization**: Providers init before routes are registered
675
+ - ✅ **Error Handling**: App won't start if provider fails to initialize
676
+ - ✅ **Tight Coupling**: Only registered providers are available
677
+ - ✅ **Lifecycle Hooks**: `onModuleInit()` for setup, `onModuleDestroy()` for cleanup
678
+ - ✅ **Type Safety**: Full TypeScript support with DI
679
+
680
+ **See [docs-wynkjs/PROVIDERS.md](./docs-wynkjs/PROVIDERS.md) for complete guide**
681
+
682
+ ### �🗃️ Database Integration (Drizzle ORM)
565
683
 
566
684
  ```typescript
567
685
  import { drizzle } from "drizzle-orm/bun-sqlite";
@@ -592,25 +710,38 @@ export class UserService {
592
710
 
593
711
  ### 📝 Request Validation
594
712
 
595
- WynkJS provides automatic request validation with **full IntelliSense support** and customizable error formats:
713
+ WynkJS provides automatic request validation with **full IntelliSense support**, **custom error messages**, and customizable error formats:
596
714
 
597
715
  ```typescript
598
716
  // user.dto.ts
599
717
  import { DTO, CommonDTO } from "wynkjs";
600
718
 
601
719
  // ✨ Full IntelliSense when typing DTO.String(), DTO.Number(), etc!
720
+ // ✨ Add custom error messages with the `error` property
602
721
  export const CreateUserDTO = DTO.Strict({
603
- name: DTO.Optional(DTO.String({ minLength: 2, maxLength: 50 })),
722
+ name: DTO.Optional(
723
+ DTO.String({
724
+ minLength: 2,
725
+ maxLength: 50,
726
+ error: "Name must be between 2 and 50 characters",
727
+ })
728
+ ),
604
729
  email: CommonDTO.Email({
605
730
  description: "User email address",
731
+ error: "Please provide a valid email address",
606
732
  }),
607
733
  mobile: DTO.Optional(
608
734
  DTO.String({
609
735
  pattern: "^[6-9]{1}[0-9]{9}$",
610
- errorMessage: "Invalid mobile number",
736
+ error: "Invalid mobile number format",
737
+ })
738
+ ),
739
+ age: DTO.Optional(
740
+ DTO.Number({
741
+ minimum: 18,
742
+ error: "Age must be at least 18 years",
611
743
  })
612
744
  ),
613
- age: DTO.Optional(DTO.Number({ minimum: 18 })),
614
745
  });
615
746
 
616
747
  export interface CreateUserType {
@@ -621,8 +752,19 @@ export interface CreateUserType {
621
752
  }
622
753
 
623
754
  export const UserUpdateDTO = DTO.Strict({
624
- email: DTO.Optional(DTO.String({ format: "email", minLength: 5 })),
625
- age: DTO.Optional(DTO.Number({ minimum: 18 })),
755
+ email: DTO.Optional(
756
+ DTO.String({
757
+ format: "email",
758
+ minLength: 5,
759
+ error: "Email must be valid and at least 5 characters",
760
+ })
761
+ ),
762
+ age: DTO.Optional(
763
+ DTO.Number({
764
+ minimum: 18,
765
+ error: "Age must be at least 18 years",
766
+ })
767
+ ),
626
768
  });
627
769
 
628
770
  export interface UserUpdateType {
@@ -659,45 +801,147 @@ export class UserController {
659
801
 
660
802
  **Customize validation error format:**
661
803
 
804
+ WynkJS provides three built-in **formatters** for validation errors:
805
+
662
806
  ```typescript
663
- import { WynkFactory, FormatErrorFormatter } from "wynkjs";
807
+ import {
808
+ WynkFactory,
809
+ FormatErrorFormatter, // Object-based { field: ["messages"] }
810
+ SimpleErrorFormatter, // Simple array ["message1", "message2"]
811
+ DetailedErrorFormatter, // Detailed with field info
812
+ } from "wynkjs";
664
813
 
665
814
  const app = WynkFactory.create({
666
815
  controllers: [UserController],
667
816
  // Choose your validation error format
668
- validationErrorFormatter: new FormatErrorFormatter(), // NestJS-style (recommended)
669
- // validationErrorFormatter: new SimpleErrorFormatter(), // Simple array
670
- // validationErrorFormatter: new DetailedErrorFormatter(), // Detailed with paths
817
+ validationErrorFormatter: new DetailedErrorFormatter(), // Recommended
671
818
  });
819
+ ```
672
820
 
673
- @Controller("/users")
674
- export class UserController {
675
- @Post({
676
- path: "/",
677
- body: CreateUserDTO,
678
- })
679
- async create(@Body() body: any) {
680
- // Body is automatically validated!
681
- return { message: "User created", data: body };
682
- }
683
- }
821
+ **Available formatters:**
684
822
 
685
- // Choose your validation error format
686
- const app = WynkFactory.create({
687
- controllers: [UserController],
688
- // Option 1: Default format (recommended)
689
- // validationErrorFormatter: new FormatErrorFormatter(), // NestJS-style
690
- // Option 2: Simple array format
691
- // validationErrorFormatter: new SimpleErrorFormatter(),
692
- // Option 3: Detailed format with field info
693
- // validationErrorFormatter: new DetailedErrorFormatter(),
823
+ 1. **FormatErrorFormatter** (Object-based):
824
+
825
+ ```json
826
+ {
827
+ "statusCode": 400,
828
+ "message": "Validation failed",
829
+ "errors": {
830
+ "email": ["Invalid email address"],
831
+ "age": ["Must be at least 18"]
832
+ }
833
+ }
834
+ ```
835
+
836
+ 2. **SimpleErrorFormatter** (Simple array):
837
+
838
+ ```json
839
+ {
840
+ "statusCode": 400,
841
+ "message": "Validation failed",
842
+ "errors": ["Invalid email address", "Must be at least 18"]
843
+ }
844
+ ```
845
+
846
+ 3. **DetailedErrorFormatter** (Detailed):
847
+ ```json
848
+ {
849
+ "statusCode": 400,
850
+ "message": "Validation failed",
851
+ "errors": [
852
+ {
853
+ "field": "email",
854
+ "message": "Invalid email address",
855
+ "value": "invalid-email"
856
+ }
857
+ ]
858
+ }
859
+ ```
860
+
861
+ **Note:** Formatters are for **validation errors only** (from DTO validation). For runtime exception handling, use **exception filters** - see [Exception Handling](#-exception-handling) section.
862
+
863
+ **See [docs-wynkjs/VALIDATION_FORMATTERS.md](./docs-wynkjs/VALIDATION_FORMATTERS.md) for all available error formats**
864
+
865
+ ### ✨ Custom Validation Error Messages
866
+
867
+ WynkJS supports custom error messages at the DTO level using the `error` or `errorMessage` property. This allows you to provide user-friendly error messages instead of the default TypeBox validation messages:
868
+
869
+ ```typescript
870
+ // user.dto.ts
871
+ import { DTO, CommonDTO } from "wynkjs";
872
+
873
+ export const CreateUserDTO = DTO.Strict({
874
+ name: DTO.String({
875
+ minLength: 2,
876
+ maxLength: 50,
877
+ error: "Name must be between 2 and 50 characters", // ✨ Custom message
878
+ }),
879
+ email: CommonDTO.Email({
880
+ error: "Invalid email address", // ✨ Custom message
881
+ }),
882
+ mobile: DTO.String({
883
+ pattern: "^[6-9]{1}[0-9]{9}$",
884
+ error: "Invalid mobile number", // ✨ Custom message
885
+ }),
886
+ age: DTO.Number({
887
+ minimum: 18,
888
+ error: "You must be at least 18 years old", // ✨ Custom message
889
+ }),
694
890
  });
695
891
  ```
696
892
 
697
- **See [VALIDATION_FORMATTERS.md](./docs-wynkjs/VALIDATION_FORMATTERS.md) for all available error formats**
893
+ **Example response with invalid data:**
894
+
895
+ ```bash
896
+ curl -X POST http://localhost:3000/users \
897
+ -H "Content-Type: application/json" \
898
+ -d '{"name":"A","email":"invalid","mobile":"1234567890","age":15}'
899
+ ```
900
+
901
+ **Response:**
902
+
903
+ ```json
904
+ {
905
+ "statusCode": 400,
906
+ "message": "Validation failed",
907
+ "errors": [
908
+ { "field": "name", "message": "Name must be between 2 and 50 characters" },
909
+ { "field": "email", "message": "Invalid email address" },
910
+ { "field": "mobile", "message": "Invalid mobile number" },
911
+ { "field": "age", "message": "You must be at least 18 years old" }
912
+ ]
913
+ }
914
+ ```
915
+
916
+ **Without custom messages, you would get generic TypeBox messages:**
917
+
918
+ ```json
919
+ {
920
+ "errors": [
921
+ {
922
+ "field": "name",
923
+ "message": "Expected string length greater or equal to 2"
924
+ },
925
+ { "field": "email", "message": "Expected string to match email format" },
926
+ {
927
+ "field": "mobile",
928
+ "message": "Expected string to match '^[6-9]{1}[0-9]{9}$'"
929
+ },
930
+ { "field": "age", "message": "Expected number greater or equal to 18" }
931
+ ]
932
+ }
933
+ ```
934
+
935
+ **Note:** You can use either `error` or `errorMessage` property - both work the same way.
698
936
 
699
937
  ### 🚫 Exception Handling
700
938
 
939
+ WynkJS provides a powerful exception handling system with **formatters** for validation errors and **filters** for runtime exceptions.
940
+
941
+ #### Exception Classes
942
+
943
+ Throw HTTP exceptions anywhere in your code:
944
+
701
945
  ```typescript
702
946
  import { Controller, Get, Param, NotFoundException } from "wynkjs";
703
947
 
@@ -721,7 +965,101 @@ export class UserController {
721
965
  - `UnauthorizedException` - 401
722
966
  - `ForbiddenException` - 403
723
967
  - `NotFoundException` - 404
968
+ - `ConflictException` - 409
724
969
  - `InternalServerErrorException` - 500
970
+ - And many more...
971
+
972
+ #### Validation Error Formatting
973
+
974
+ Format validation errors using **formatters** (passed to factory options):
975
+
976
+ ```typescript
977
+ import { WynkFactory, DetailedErrorFormatter } from "wynkjs";
978
+
979
+ const app = WynkFactory.create({
980
+ controllers: [UserController],
981
+ validationErrorFormatter: new DetailedErrorFormatter(), // ✅ For validation
982
+ });
983
+ ```
984
+
985
+ **Available formatters:**
986
+
987
+ - `FormatErrorFormatter` - Object format `{ field: ["messages"] }`
988
+ - `SimpleErrorFormatter` - Simple array `["message1", "message2"]`
989
+ - `DetailedErrorFormatter` - Detailed with field info
990
+
991
+ #### Global Exception Filters
992
+
993
+ Handle runtime exceptions using **global filters**:
994
+
995
+ ```typescript
996
+ import {
997
+ WynkFactory,
998
+ DatabaseExceptionFilter,
999
+ NotFoundExceptionFilter,
1000
+ GlobalExceptionFilter,
1001
+ } from "wynkjs";
1002
+
1003
+ const app = WynkFactory.create({
1004
+ controllers: [UserController],
1005
+ validationErrorFormatter: new DetailedErrorFormatter(),
1006
+ });
1007
+
1008
+ // Register global exception filters
1009
+ app.useGlobalFilters(
1010
+ new DatabaseExceptionFilter(), // Handles database errors
1011
+ new NotFoundExceptionFilter(), // Smart 404 handling with response data checking
1012
+ new GlobalExceptionFilter() // Catch-all for other exceptions
1013
+ );
1014
+ ```
1015
+
1016
+ **Available global filters:**
1017
+
1018
+ - `DatabaseExceptionFilter` - Catches database errors (unique constraints, foreign keys, etc.)
1019
+ - `NotFoundExceptionFilter` - Smart filter that only formats truly empty 404 responses
1020
+ - `FileUploadExceptionFilter` - Handles file upload errors
1021
+ - `GlobalExceptionFilter` - Catch-all for unhandled exceptions
1022
+
1023
+ **What's the difference?**
1024
+
1025
+ | Feature | Formatters | Filters |
1026
+ | ---------------- | -------------------------------------------------- | -------------------------- |
1027
+ | **Purpose** | Format validation errors | Handle runtime exceptions |
1028
+ | **When?** | During request validation (TypeBox) | When exceptions are thrown |
1029
+ | **Registration** | `WynkFactory.create({ validationErrorFormatter })` | `app.useGlobalFilters()` |
1030
+ | **Example** | `FormatErrorFormatter` | `DatabaseExceptionFilter` |
1031
+
1032
+ #### Custom Exception Filters
1033
+
1034
+ Create your own filters for specific routes:
1035
+
1036
+ ```typescript
1037
+ import { WynkExceptionFilter, ExecutionContext, Catch } from "wynkjs";
1038
+
1039
+ @Catch() // Catches all exceptions
1040
+ export class CustomExceptionFilter implements WynkExceptionFilter {
1041
+ catch(exception: any, context: ExecutionContext) {
1042
+ const request = context.getRequest();
1043
+
1044
+ return {
1045
+ statusCode: exception.statusCode || 500,
1046
+ message: exception.message,
1047
+ timestamp: new Date().toISOString(),
1048
+ path: request.url,
1049
+ };
1050
+ }
1051
+ }
1052
+
1053
+ // Use globally
1054
+ app.useGlobalFilters(new CustomExceptionFilter());
1055
+
1056
+ // Or on specific controllers/routes
1057
+ @UseFilters(CustomExceptionFilter)
1058
+ @Controller("/api")
1059
+ export class ApiController {}
1060
+ ```
1061
+
1062
+ **See [ARCHITECTURE.md](./ARCHITECTURE.md) for complete architecture details**
725
1063
 
726
1064
  ### 🔄 Multiple Params and Query Validation
727
1065
 
@@ -821,157 +1159,71 @@ my-wynk-app/
821
1159
 
822
1160
  ---
823
1161
 
824
- ## 🎨 Complete Working Example
825
-
826
- Here's a complete, production-ready example with all features:
827
-
828
- ```typescript
829
- // dto/user.dto.ts
830
- import { DTO, CommonDTO } from "wynkjs";
831
-
832
- export const CreateUserDTO = DTO.Strict({
833
- name: DTO.Optional(DTO.String({ minLength: 2, maxLength: 50 })),
834
- email: CommonDTO.Email({ description: "User email address" }),
835
- mobile: DTO.Optional(
836
- DTO.String({
837
- pattern: "^[6-9]{1}[0-9]{9}$",
838
- errorMessage: "Invalid mobile number",
839
- })
840
- ),
841
- age: DTO.Optional(DTO.Number({ minimum: 18 })),
842
- });
843
-
844
- export const UserIdDto = DTO.Object({
845
- id: DTO.String({ minLength: 2, maxLength: 50 }),
846
- });
847
-
848
- export interface CreateUserType {
849
- name?: string;
850
- email: string;
851
- mobile?: string;
852
- age?: number;
853
- }
1162
+ ## 📖 API Reference
854
1163
 
855
- // services/email.service.ts
856
- import { Injectable } from "wynkjs";
1164
+ ### Core Decorators
857
1165
 
858
- @Injectable()
859
- export class EmailService {
860
- async sendWelcomeEmail(email: string, userName: string): Promise<void> {
861
- console.log(`📧 Sending welcome email to ${email}`);
862
- // Your email sending logic (SendGrid, AWS SES, etc.)
863
- }
864
- }
1166
+ #### `@Controller(basePath?: string)`
865
1167
 
866
- // controllers/user.controller.ts
867
- import {
868
- Controller,
869
- Get,
870
- Post,
871
- Patch,
872
- Body,
873
- Param,
874
- Injectable,
875
- NotFoundException,
876
- } from "wynkjs";
877
- import { CreateUserDTO, UserIdDto } from "../dto/user.dto";
878
- import type { CreateUserType } from "../dto/user.dto";
879
- import { EmailService } from "../services/email.service";
1168
+ Define a controller class with optional base path.
880
1169
 
881
- @Injectable()
1170
+ ```typescript
882
1171
  @Controller("/users")
883
1172
  export class UserController {
884
- constructor(private emailService: EmailService) {}
885
-
886
- @Get("/")
887
- async list() {
888
- return { users: ["Alice", "Bob", "Charlie"] };
889
- }
890
-
891
- @Post({ path: "/", body: CreateUserDTO })
892
- async create(@Body() body: CreateUserType) {
893
- // Send welcome email using injected service
894
- if (body.email && body.name) {
895
- await this.emailService.sendWelcomeEmail(body.email, body.name);
896
- }
897
- return { message: "User created", data: body };
898
- }
899
-
900
- @Get({ path: "/:id", params: UserIdDto })
901
- async findOne(@Param("id") id: string) {
902
- if (id === "nonexistent") {
903
- throw new NotFoundException("User not found");
904
- }
905
- return { user: { id, name: "Alice" } };
906
- }
907
-
908
- @Patch({ path: "/:id", params: UserIdDto })
909
- async update(@Param("id") id: string, @Body() body: any) {
910
- return { message: "User updated", id, data: body };
911
- }
1173
+ // All routes will be prefixed with /users
912
1174
  }
913
-
914
- // index.ts
915
- import { WynkFactory } from "wynkjs";
916
- import { UserController } from "./controllers/user.controller";
917
-
918
- const app = WynkFactory.create({
919
- controllers: [UserController],
920
- });
921
-
922
- await app.listen(3000);
923
- console.log("🚀 Server running on http://localhost:3000");
924
1175
  ```
925
1176
 
926
- **Test the API:**
1177
+ #### HTTP Method Decorators
927
1178
 
928
- ```bash
929
- # List all users
930
- curl http://localhost:3000/users
931
-
932
- # Create a new user (with validation and email)
933
- curl -X POST http://localhost:3000/users \
934
- -H "Content-Type: application/json" \
935
- -d '{"name":"Alice","email":"alice@example.com","age":25}'
936
-
937
- # Get user by ID
938
- curl http://localhost:3000/users/123
1179
+ All HTTP methods support both **string** and **object** formats:
939
1180
 
940
- # Update user
941
- curl -X PATCH http://localhost:3000/users/123 \
942
- -H "Content-Type: application/json" \
943
- -d '{"email":"newemail@example.com"}'
1181
+ **String format:**
944
1182
 
945
- # Test 404 exception
946
- curl http://localhost:3000/users/nonexistent
1183
+ ```typescript
1184
+ @Get("/") // GET /users
1185
+ @Post("/") // POST /users
1186
+ @Patch("/:id") // PATCH /users/:id
947
1187
  ```
948
1188
 
949
- ---
1189
+ **Object format with validation:**
950
1190
 
951
- ## 📖 API Reference
1191
+ ```typescript
1192
+ @Get({ path: "/" }) // GET with options
952
1193
 
953
- ### Core Decorators
1194
+ @Post({
1195
+ path: "/",
1196
+ body: CreateUserDTO // POST with body validation
1197
+ })
954
1198
 
955
- #### `@Controller(basePath?: string)`
1199
+ @Patch({
1200
+ path: "/:id",
1201
+ params: UserIdDto, // PATCH with param validation
1202
+ body: UpdateUserDTO // PATCH with body validation
1203
+ })
956
1204
 
957
- Define a controller class with optional base path.
1205
+ @Get({
1206
+ path: "/",
1207
+ query: UserQueryDto // GET with query validation
1208
+ })
958
1209
 
959
- ```typescript
960
- @Controller("/users")
961
- export class UserController {
962
- // All routes will be prefixed with /users
963
- }
1210
+ @Post({
1211
+ path: "/:id1/:id2",
1212
+ body: CreateUserDTO, // Multiple validations
1213
+ params: MultiParamDto,
1214
+ query: UserQueryDto
1215
+ })
964
1216
  ```
965
1217
 
966
- #### `@Get(path?: string)` / `@Post()` / `@Patch()` / `@Delete()`
1218
+ **Available HTTP methods:**
967
1219
 
968
- HTTP method decorators with optional path and options.
969
-
970
- ```typescript
971
- @Get("/") // GET /users
972
- @Post({ path: "/", body: CreateUserDTO }) // POST with validation
973
- @Patch({ path: "/:id", params: UserIdDto }) // PATCH with param validation
974
- ```
1220
+ - `@Get()` - GET requests (params, query)
1221
+ - `@Post()` - POST requests (body, params, query)
1222
+ - `@Put()` - PUT requests (body, params, query)
1223
+ - `@Patch()` - PATCH requests (body, params, query)
1224
+ - `@Delete()` - DELETE requests (params, query)
1225
+ - `@Options()` - OPTIONS requests
1226
+ - `@Head()` - HEAD requests
975
1227
 
976
1228
  #### `@Body()` / `@Param(key?)` / `@Query(key?)`
977
1229
 
@@ -1033,60 +1285,13 @@ throw new InternalServerErrorException("Error"); // 500
1033
1285
 
1034
1286
  ---
1035
1287
 
1036
- ## �️ CLI Tool
1037
-
1038
- ### create-wynkjs
1039
-
1040
- Quickly scaffold a new WynkJS project with best practices:
1041
-
1042
- ```bash
1043
- bunx create-wynkjs
1044
- # or
1045
- npx create-wynkjs
1046
- ```
1047
-
1048
- **Features:**
1049
-
1050
- - 🎯 Interactive project setup
1051
- - ✅ TypeScript configuration (strict mode)
1052
- - 🔍 ESLint with TypeScript rules
1053
- - 💅 Prettier for code formatting
1054
- - 🪝 Husky for Git hooks (optional)
1055
- - 🔥 Hot reload with `bun --watch` (faster than nodemon)
1056
- - 📝 Complete working example (CRUD API)
1057
-
1058
- **Generated Project Structure:**
1059
-
1060
- ```
1061
- my-wynkjs-app/
1062
- ├── src/
1063
- │ ├── modules/
1064
- │ │ └── user/
1065
- │ │ ├── user.controller.ts
1066
- │ │ ├── user.service.ts
1067
- │ │ └── user.dto.ts
1068
- │ └── index.ts
1069
- ├── .eslintrc.json
1070
- ├── .prettierrc
1071
- ├── tsconfig.json
1072
- └── package.json
1073
- ```
1074
-
1075
- **Available Scripts:**
1076
-
1077
- - `bun run dev` - Development with hot reload
1078
- - `bun run start` - Production server
1079
- - `bun run build` - Build TypeScript
1080
- - `bun run lint` - Run ESLint
1081
- - `bun run format` - Format with Prettier
1082
-
1083
- [Learn more about create-wynkjs](./packages/create-wynkjs/README.md)
1084
-
1085
- ---
1086
-
1087
- ## �🔗 Resources
1288
+ ## 🔗 Resources
1088
1289
 
1089
1290
  - 📚 [Full Documentation](https://github.com/wynkjs/wynkjs-core)
1291
+ - 💡 [Example Code](./docs-wynkjs/EXAMPLE_GUIDE.md)
1292
+ - 🏗️ [Architecture Guide](./ARCHITECTURE.md) - Complete guide to formatters vs filters
1293
+ - 🔧 [Provider System](./docs-wynkjs/PROVIDERS.md) - **NEW!** Database, config, and service providers
1294
+ - 🔄 [Migration Guide](./MIGRATION.md) - Upgrading from older versions
1090
1295
  - 🚀 [CLI Tool (create-wynkjs)](./packages/create-wynkjs/README.md)
1091
1296
  - 🎨 [Validation Formatters](./docs-wynkjs/VALIDATION_FORMATTERS.md)
1092
1297
  - 📝 [Changelog](./CHANGELOG.md)
@@ -1127,33 +1332,21 @@ If you find a bug or have a feature request:
1127
1332
  bun install
1128
1333
  ```
1129
1334
 
1130
- 3. **Build the packages**
1335
+ 3. **Create a branch**
1131
1336
 
1132
- ```bash
1133
- # Build main framework
1134
- bun run build
1135
-
1136
- # Build CLI tools
1137
- cd packages/create-wynkjs && bun run build
1138
- cd ../wynkjs-cli && bun run build
1139
- ```
1140
-
1141
- 4. **Create a branch**
1142
1337
  ```bash
1143
1338
  git checkout -b feature/your-feature-name
1144
1339
  # or
1145
1340
  git checkout -b fix/bug-description
1146
1341
  ```
1147
1342
 
1148
- #### Development Workflow
1149
-
1150
- 1. **Make your changes** in the appropriate package:
1343
+ 4. **Make your changes** in the appropriate package:
1151
1344
 
1152
1345
  - `core/` - Core framework decorators and utilities
1153
1346
  - `packages/create-wynkjs/` - Project scaffolding CLI
1154
1347
  - `packages/wynkjs-cli/` - Code generator CLI
1155
1348
 
1156
- 2. **Test your changes**
1349
+ 5. **Test your changes**
1157
1350
 
1158
1351
  ```bash
1159
1352
  # Test in the example project
@@ -1164,7 +1357,7 @@ If you find a bug or have a feature request:
1164
1357
  cd /tmp && bunx /path/to/wynkjs-core/packages/create-wynkjs
1165
1358
  ```
1166
1359
 
1167
- 3. **Build all packages**
1360
+ 6. **Build all packages**
1168
1361
 
1169
1362
  ```bash
1170
1363
  # From project root
@@ -1173,7 +1366,7 @@ If you find a bug or have a feature request:
1173
1366
  cd ../wynkjs-cli && bun run build
1174
1367
  ```
1175
1368
 
1176
- 4. **Commit your changes**
1369
+ 7. **Commit your changes**
1177
1370
 
1178
1371
  ```bash
1179
1372
  git add .
@@ -1191,7 +1384,7 @@ If you find a bug or have a feature request:
1191
1384
  - `test:` - Adding tests
1192
1385
  - `chore:` - Maintenance tasks
1193
1386
 
1194
- 5. **Push and create a Pull Request**
1387
+ 8. **Push and create a Pull Request**
1195
1388
 
1196
1389
  ```bash
1197
1390
  git push origin feature/your-feature-name
@@ -1229,19 +1422,6 @@ Documentation improvements are always welcome!
1229
1422
  - **Guides**: Create helpful guides in `docs-wynkjs/`
1230
1423
  - **Examples**: Add real-world usage examples
1231
1424
 
1232
- ### 🚀 Release Process (Maintainers)
1233
-
1234
- 1. Update `CHANGELOG.md` with changes
1235
- 2. Bump version in `package.json` files
1236
- 3. Build all packages
1237
- 4. Commit and tag the release
1238
- 5. Publish to npm:
1239
- ```bash
1240
- npm publish --access public
1241
- cd packages/create-wynkjs && npm publish --access public
1242
- cd ../wynkjs-cli && npm publish --access public
1243
- ```
1244
-
1245
1425
  ### 💬 Community
1246
1426
 
1247
1427
  - **GitHub Discussions**: Ask questions and share ideas