wynkjs 1.0.4 → 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.
- package/README.md +296 -313
- package/dist/cors.d.ts +28 -0
- package/dist/cors.d.ts.map +1 -0
- package/dist/cors.js +121 -0
- package/dist/decorators/exception.decorators.d.ts +1 -0
- package/dist/decorators/exception.decorators.d.ts.map +1 -1
- package/dist/decorators/exception.decorators.js +20 -3
- package/dist/decorators/guard.decorators.d.ts.map +1 -1
- package/dist/decorators/guard.decorators.js +11 -5
- package/dist/decorators/http.decorators.d.ts +8 -3
- package/dist/decorators/http.decorators.d.ts.map +1 -1
- package/dist/decorators/http.decorators.js +9 -2
- package/dist/decorators/interceptor.advanced.d.ts +9 -9
- package/dist/decorators/interceptor.advanced.d.ts.map +1 -1
- package/dist/decorators/interceptor.advanced.js +7 -7
- package/dist/decorators/interceptor.decorators.d.ts +9 -7
- package/dist/decorators/interceptor.decorators.d.ts.map +1 -1
- package/dist/decorators/interceptor.decorators.js +29 -18
- package/dist/decorators/param.decorators.d.ts +2 -2
- package/dist/decorators/param.decorators.js +1 -1
- package/dist/decorators/pipe.decorators.d.ts +2 -2
- package/dist/decorators/pipe.decorators.js +2 -2
- package/dist/factory.d.ts +29 -1
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +155 -180
- package/dist/global-prefix.d.ts +49 -0
- package/dist/global-prefix.d.ts.map +1 -0
- package/dist/global-prefix.js +155 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/interfaces/interceptor.interface.d.ts +15 -0
- package/dist/interfaces/interceptor.interface.d.ts.map +1 -0
- package/dist/interfaces/interceptor.interface.js +1 -0
- package/dist/optimized-handler.d.ts +31 -0
- package/dist/optimized-handler.d.ts.map +1 -0
- package/dist/optimized-handler.js +180 -0
- package/dist/pipes/validation.pipe.d.ts +10 -10
- package/dist/pipes/validation.pipe.js +4 -4
- package/dist/ultra-optimized-handler.d.ts +51 -0
- package/dist/ultra-optimized-handler.d.ts.map +1 -0
- package/dist/ultra-optimized-handler.js +302 -0
- package/package.json +10 -8
package/README.md
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
|
-
**A high-performance TypeScript framework built
|
|
5
|
+
**A high-performance TypeScript first framework built for Bun with Elegant Decorator-Based Architecture**
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/wynkjs)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
9
|
[](https://www.typescriptlang.org/)
|
|
10
10
|
[](https://bun.sh/)
|
|
11
11
|
|
|
12
|
-
_10x faster than Express/NestJs, built for modern TypeScript development
|
|
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,31 +19,17 @@ _10x faster than Express/NestJs, built for modern TypeScript development on Bun_
|
|
|
19
19
|
|
|
20
20
|
## About
|
|
21
21
|
|
|
22
|
-
WynkJS is a modern, TypeScript-first web framework that brings
|
|
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
|
-
|
|
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: Bun framework, Elysia framework, TypeScript decorators, dependency injection (DI), guards, pipes, interceptors, exception filters, fast web framework, REST API, backend, modern TypeScript.
|
|
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 an **
|
|
30
|
+
WynkJS combines the **speed of Elysia** with an **Elegant Decorator-Based Architecture**, giving you the best of both worlds:
|
|
45
31
|
|
|
46
|
-
- 🚀 **
|
|
32
|
+
- 🚀 **10x Faster** - One of the fastest web frameworks for Bun
|
|
47
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
|
|
@@ -54,60 +40,98 @@ WynkJS combines the **speed of Elysia** with an **elegant decorator-based archit
|
|
|
54
40
|
|
|
55
41
|
---
|
|
56
42
|
|
|
57
|
-
##
|
|
58
|
-
|
|
59
|
-
**Requirements:** Bun 1.0 or higher
|
|
43
|
+
## 🚀 Get Started in 30 Seconds:
|
|
60
44
|
|
|
61
|
-
###
|
|
45
|
+
### 📦 create-wynkjs - Project Scaffolding
|
|
62
46
|
|
|
63
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
65
|
+
**Generated Project Structure:**
|
|
82
66
|
|
|
83
|
-
```
|
|
84
|
-
|
|
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
|
-
**
|
|
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
|
|
90
89
|
|
|
91
|
-
|
|
90
|
+
[Learn more about create-wynkjs](./packages/create-wynkjs/README.md)
|
|
92
91
|
|
|
93
|
-
|
|
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
|
+
```
|
|
105
|
+
|
|
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(
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
|
248
|
+
bun run start
|
|
225
249
|
# or with --watch for hot reload
|
|
226
|
-
bun
|
|
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
|
-
|
|
259
|
-
@
|
|
260
|
-
@
|
|
261
|
-
@
|
|
262
|
-
@
|
|
263
|
-
@
|
|
264
|
-
@
|
|
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:
|
|
@@ -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
|
-
###
|
|
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(
|
|
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
|
-
|
|
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(
|
|
625
|
-
|
|
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 {
|
|
@@ -883,7 +1025,7 @@ app.useGlobalFilters(
|
|
|
883
1025
|
| Feature | Formatters | Filters |
|
|
884
1026
|
| ---------------- | -------------------------------------------------- | -------------------------- |
|
|
885
1027
|
| **Purpose** | Format validation errors | Handle runtime exceptions |
|
|
886
|
-
| **When?** | During request validation (TypeBox
|
|
1028
|
+
| **When?** | During request validation (TypeBox) | When exceptions are thrown |
|
|
887
1029
|
| **Registration** | `WynkFactory.create({ validationErrorFormatter })` | `app.useGlobalFilters()` |
|
|
888
1030
|
| **Example** | `FormatErrorFormatter` | `DatabaseExceptionFilter` |
|
|
889
1031
|
|
|
@@ -1017,169 +1159,71 @@ my-wynk-app/
|
|
|
1017
1159
|
|
|
1018
1160
|
---
|
|
1019
1161
|
|
|
1020
|
-
##
|
|
1021
|
-
|
|
1022
|
-
Here's a complete, production-ready example with all features:
|
|
1023
|
-
|
|
1024
|
-
```typescript
|
|
1025
|
-
// dto/user.dto.ts
|
|
1026
|
-
import { DTO, CommonDTO } from "wynkjs";
|
|
1027
|
-
|
|
1028
|
-
export const CreateUserDTO = DTO.Strict({
|
|
1029
|
-
name: DTO.Optional(DTO.String({ minLength: 2, maxLength: 50 })),
|
|
1030
|
-
email: CommonDTO.Email({ description: "User email address" }),
|
|
1031
|
-
mobile: DTO.Optional(
|
|
1032
|
-
DTO.String({
|
|
1033
|
-
pattern: "^[6-9]{1}[0-9]{9}$",
|
|
1034
|
-
errorMessage: "Invalid mobile number",
|
|
1035
|
-
})
|
|
1036
|
-
),
|
|
1037
|
-
age: DTO.Optional(DTO.Number({ minimum: 18 })),
|
|
1038
|
-
});
|
|
1039
|
-
|
|
1040
|
-
export const UserIdDto = DTO.Object({
|
|
1041
|
-
id: DTO.String({ minLength: 2, maxLength: 50 }),
|
|
1042
|
-
});
|
|
1043
|
-
|
|
1044
|
-
export interface CreateUserType {
|
|
1045
|
-
name?: string;
|
|
1046
|
-
email: string;
|
|
1047
|
-
mobile?: string;
|
|
1048
|
-
age?: number;
|
|
1049
|
-
}
|
|
1162
|
+
## 📖 API Reference
|
|
1050
1163
|
|
|
1051
|
-
|
|
1052
|
-
import { Injectable } from "wynkjs";
|
|
1164
|
+
### Core Decorators
|
|
1053
1165
|
|
|
1054
|
-
|
|
1055
|
-
export class EmailService {
|
|
1056
|
-
async sendWelcomeEmail(email: string, userName: string): Promise<void> {
|
|
1057
|
-
console.log(`📧 Sending welcome email to ${email}`);
|
|
1058
|
-
// Your email sending logic (SendGrid, AWS SES, etc.)
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1166
|
+
#### `@Controller(basePath?: string)`
|
|
1061
1167
|
|
|
1062
|
-
|
|
1063
|
-
import {
|
|
1064
|
-
Controller,
|
|
1065
|
-
Get,
|
|
1066
|
-
Post,
|
|
1067
|
-
Patch,
|
|
1068
|
-
Body,
|
|
1069
|
-
Param,
|
|
1070
|
-
Injectable,
|
|
1071
|
-
NotFoundException,
|
|
1072
|
-
} from "wynkjs";
|
|
1073
|
-
import { CreateUserDTO, UserIdDto } from "../dto/user.dto";
|
|
1074
|
-
import type { CreateUserType } from "../dto/user.dto";
|
|
1075
|
-
import { EmailService } from "../services/email.service";
|
|
1168
|
+
Define a controller class with optional base path.
|
|
1076
1169
|
|
|
1077
|
-
|
|
1170
|
+
```typescript
|
|
1078
1171
|
@Controller("/users")
|
|
1079
1172
|
export class UserController {
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
@Get("/")
|
|
1083
|
-
async list() {
|
|
1084
|
-
return { users: ["Alice", "Bob", "Charlie"] };
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
|
-
@Post({ path: "/", body: CreateUserDTO })
|
|
1088
|
-
async create(@Body() body: CreateUserType) {
|
|
1089
|
-
// Send welcome email using injected service
|
|
1090
|
-
if (body.email && body.name) {
|
|
1091
|
-
await this.emailService.sendWelcomeEmail(body.email, body.name);
|
|
1092
|
-
}
|
|
1093
|
-
return { message: "User created", data: body };
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
@Get({ path: "/:id", params: UserIdDto })
|
|
1097
|
-
async findOne(@Param("id") id: string) {
|
|
1098
|
-
if (id === "nonexistent") {
|
|
1099
|
-
throw new NotFoundException("User not found");
|
|
1100
|
-
}
|
|
1101
|
-
return { user: { id, name: "Alice" } };
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
@Patch({ path: "/:id", params: UserIdDto })
|
|
1105
|
-
async update(@Param("id") id: string, @Body() body: any) {
|
|
1106
|
-
return { message: "User updated", id, data: body };
|
|
1107
|
-
}
|
|
1173
|
+
// All routes will be prefixed with /users
|
|
1108
1174
|
}
|
|
1109
|
-
|
|
1110
|
-
// index.ts
|
|
1111
|
-
import {
|
|
1112
|
-
WynkFactory,
|
|
1113
|
-
DetailedErrorFormatter,
|
|
1114
|
-
GlobalExceptionFilter,
|
|
1115
|
-
DatabaseExceptionFilter,
|
|
1116
|
-
} from "wynkjs";
|
|
1117
|
-
import { UserController } from "./controllers/user.controller";
|
|
1118
|
-
|
|
1119
|
-
const app = WynkFactory.create({
|
|
1120
|
-
controllers: [UserController],
|
|
1121
|
-
validationErrorFormatter: new DetailedErrorFormatter(), // ✅ Format validation errors
|
|
1122
|
-
});
|
|
1123
|
-
|
|
1124
|
-
// Register global exception filters
|
|
1125
|
-
app.useGlobalFilters(
|
|
1126
|
-
new DatabaseExceptionFilter(), // Handles database errors
|
|
1127
|
-
new GlobalExceptionFilter() // Catch-all for other exceptions
|
|
1128
|
-
);
|
|
1129
|
-
|
|
1130
|
-
await app.listen(3000);
|
|
1131
|
-
console.log("🚀 Server running on http://localhost:3000");
|
|
1132
1175
|
```
|
|
1133
1176
|
|
|
1134
|
-
|
|
1177
|
+
#### HTTP Method Decorators
|
|
1135
1178
|
|
|
1136
|
-
|
|
1137
|
-
# List all users
|
|
1138
|
-
curl http://localhost:3000/users
|
|
1179
|
+
All HTTP methods support both **string** and **object** formats:
|
|
1139
1180
|
|
|
1140
|
-
|
|
1141
|
-
curl -X POST http://localhost:3000/users \
|
|
1142
|
-
-H "Content-Type: application/json" \
|
|
1143
|
-
-d '{"name":"Alice","email":"alice@example.com","age":25}'
|
|
1181
|
+
**String format:**
|
|
1144
1182
|
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
curl -X PATCH http://localhost:3000/users/123 \
|
|
1150
|
-
-H "Content-Type: application/json" \
|
|
1151
|
-
-d '{"email":"newemail@example.com"}'
|
|
1152
|
-
|
|
1153
|
-
# Test 404 exception
|
|
1154
|
-
curl http://localhost:3000/users/nonexistent
|
|
1183
|
+
```typescript
|
|
1184
|
+
@Get("/") // GET /users
|
|
1185
|
+
@Post("/") // POST /users
|
|
1186
|
+
@Patch("/:id") // PATCH /users/:id
|
|
1155
1187
|
```
|
|
1156
1188
|
|
|
1157
|
-
|
|
1189
|
+
**Object format with validation:**
|
|
1158
1190
|
|
|
1159
|
-
|
|
1191
|
+
```typescript
|
|
1192
|
+
@Get({ path: "/" }) // GET with options
|
|
1160
1193
|
|
|
1161
|
-
|
|
1194
|
+
@Post({
|
|
1195
|
+
path: "/",
|
|
1196
|
+
body: CreateUserDTO // POST with body validation
|
|
1197
|
+
})
|
|
1162
1198
|
|
|
1163
|
-
|
|
1199
|
+
@Patch({
|
|
1200
|
+
path: "/:id",
|
|
1201
|
+
params: UserIdDto, // PATCH with param validation
|
|
1202
|
+
body: UpdateUserDTO // PATCH with body validation
|
|
1203
|
+
})
|
|
1164
1204
|
|
|
1165
|
-
|
|
1205
|
+
@Get({
|
|
1206
|
+
path: "/",
|
|
1207
|
+
query: UserQueryDto // GET with query validation
|
|
1208
|
+
})
|
|
1166
1209
|
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1210
|
+
@Post({
|
|
1211
|
+
path: "/:id1/:id2",
|
|
1212
|
+
body: CreateUserDTO, // Multiple validations
|
|
1213
|
+
params: MultiParamDto,
|
|
1214
|
+
query: UserQueryDto
|
|
1215
|
+
})
|
|
1172
1216
|
```
|
|
1173
1217
|
|
|
1174
|
-
|
|
1218
|
+
**Available HTTP methods:**
|
|
1175
1219
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
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
|
|
1183
1227
|
|
|
1184
1228
|
#### `@Body()` / `@Param(key?)` / `@Query(key?)`
|
|
1185
1229
|
|
|
@@ -1241,61 +1285,12 @@ throw new InternalServerErrorException("Error"); // 500
|
|
|
1241
1285
|
|
|
1242
1286
|
---
|
|
1243
1287
|
|
|
1244
|
-
## �️ CLI Tool
|
|
1245
|
-
|
|
1246
|
-
### create-wynkjs
|
|
1247
|
-
|
|
1248
|
-
Quickly scaffold a new WynkJS project with best practices:
|
|
1249
|
-
|
|
1250
|
-
```bash
|
|
1251
|
-
bunx create-wynkjs
|
|
1252
|
-
# or
|
|
1253
|
-
npx create-wynkjs
|
|
1254
|
-
```
|
|
1255
|
-
|
|
1256
|
-
**Features:**
|
|
1257
|
-
|
|
1258
|
-
- 🎯 Interactive project setup
|
|
1259
|
-
- ✅ TypeScript configuration (strict mode)
|
|
1260
|
-
- 🔍 ESLint with TypeScript rules
|
|
1261
|
-
- 💅 Prettier for code formatting
|
|
1262
|
-
- 🪝 Husky for Git hooks (optional)
|
|
1263
|
-
- 🔥 Hot reload with `bun --watch` (faster than nodemon)
|
|
1264
|
-
- 📝 Complete working example (CRUD API)
|
|
1265
|
-
|
|
1266
|
-
**Generated Project Structure:**
|
|
1267
|
-
|
|
1268
|
-
```
|
|
1269
|
-
my-wynkjs-app/
|
|
1270
|
-
├── src/
|
|
1271
|
-
│ ├── modules/
|
|
1272
|
-
│ │ └── user/
|
|
1273
|
-
│ │ ├── user.controller.ts
|
|
1274
|
-
│ │ ├── user.service.ts
|
|
1275
|
-
│ │ └── user.dto.ts
|
|
1276
|
-
│ └── index.ts
|
|
1277
|
-
├── .eslintrc.json
|
|
1278
|
-
├── .prettierrc
|
|
1279
|
-
├── tsconfig.json
|
|
1280
|
-
└── package.json
|
|
1281
|
-
```
|
|
1282
|
-
|
|
1283
|
-
**Available Scripts:**
|
|
1284
|
-
|
|
1285
|
-
- `bun run dev` - Development with hot reload
|
|
1286
|
-
- `bun run start` - Production server
|
|
1287
|
-
- `bun run build` - Build TypeScript
|
|
1288
|
-
- `bun run lint` - Run ESLint
|
|
1289
|
-
- `bun run format` - Format with Prettier
|
|
1290
|
-
|
|
1291
|
-
[Learn more about create-wynkjs](./packages/create-wynkjs/README.md)
|
|
1292
|
-
|
|
1293
|
-
---
|
|
1294
|
-
|
|
1295
1288
|
## 🔗 Resources
|
|
1296
1289
|
|
|
1297
1290
|
- 📚 [Full Documentation](https://github.com/wynkjs/wynkjs-core)
|
|
1298
|
-
-
|
|
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
|
|
1299
1294
|
- 🔄 [Migration Guide](./MIGRATION.md) - Upgrading from older versions
|
|
1300
1295
|
- 🚀 [CLI Tool (create-wynkjs)](./packages/create-wynkjs/README.md)
|
|
1301
1296
|
- 🎨 [Validation Formatters](./docs-wynkjs/VALIDATION_FORMATTERS.md)
|
|
@@ -1337,33 +1332,21 @@ If you find a bug or have a feature request:
|
|
|
1337
1332
|
bun install
|
|
1338
1333
|
```
|
|
1339
1334
|
|
|
1340
|
-
3. **
|
|
1341
|
-
|
|
1342
|
-
```bash
|
|
1343
|
-
# Build main framework
|
|
1344
|
-
bun run build
|
|
1345
|
-
|
|
1346
|
-
# Build CLI tools
|
|
1347
|
-
cd packages/create-wynkjs && bun run build
|
|
1348
|
-
cd ../wynkjs-cli && bun run build
|
|
1349
|
-
```
|
|
1335
|
+
3. **Create a branch**
|
|
1350
1336
|
|
|
1351
|
-
4. **Create a branch**
|
|
1352
1337
|
```bash
|
|
1353
1338
|
git checkout -b feature/your-feature-name
|
|
1354
1339
|
# or
|
|
1355
1340
|
git checkout -b fix/bug-description
|
|
1356
1341
|
```
|
|
1357
1342
|
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
1. **Make your changes** in the appropriate package:
|
|
1343
|
+
4. **Make your changes** in the appropriate package:
|
|
1361
1344
|
|
|
1362
1345
|
- `core/` - Core framework decorators and utilities
|
|
1363
1346
|
- `packages/create-wynkjs/` - Project scaffolding CLI
|
|
1364
1347
|
- `packages/wynkjs-cli/` - Code generator CLI
|
|
1365
1348
|
|
|
1366
|
-
|
|
1349
|
+
5. **Test your changes**
|
|
1367
1350
|
|
|
1368
1351
|
```bash
|
|
1369
1352
|
# Test in the example project
|
|
@@ -1374,7 +1357,7 @@ If you find a bug or have a feature request:
|
|
|
1374
1357
|
cd /tmp && bunx /path/to/wynkjs-core/packages/create-wynkjs
|
|
1375
1358
|
```
|
|
1376
1359
|
|
|
1377
|
-
|
|
1360
|
+
6. **Build all packages**
|
|
1378
1361
|
|
|
1379
1362
|
```bash
|
|
1380
1363
|
# From project root
|
|
@@ -1383,7 +1366,7 @@ If you find a bug or have a feature request:
|
|
|
1383
1366
|
cd ../wynkjs-cli && bun run build
|
|
1384
1367
|
```
|
|
1385
1368
|
|
|
1386
|
-
|
|
1369
|
+
7. **Commit your changes**
|
|
1387
1370
|
|
|
1388
1371
|
```bash
|
|
1389
1372
|
git add .
|
|
@@ -1401,7 +1384,7 @@ If you find a bug or have a feature request:
|
|
|
1401
1384
|
- `test:` - Adding tests
|
|
1402
1385
|
- `chore:` - Maintenance tasks
|
|
1403
1386
|
|
|
1404
|
-
|
|
1387
|
+
8. **Push and create a Pull Request**
|
|
1405
1388
|
|
|
1406
1389
|
```bash
|
|
1407
1390
|
git push origin feature/your-feature-name
|