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.
- package/README.md +528 -348
- package/dist/cors.d.ts +28 -0
- package/dist/cors.d.ts.map +1 -0
- package/dist/cors.js +121 -0
- package/dist/database.d.ts +1 -1
- package/dist/database.js +1 -1
- package/dist/decorators/exception.advanced.d.ts +286 -18
- package/dist/decorators/exception.advanced.d.ts.map +1 -1
- package/dist/decorators/exception.advanced.js +410 -17
- package/dist/decorators/exception.decorators.d.ts +93 -2
- package/dist/decorators/exception.decorators.d.ts.map +1 -1
- package/dist/decorators/exception.decorators.js +140 -8
- package/dist/decorators/formatter.decorators.d.ts +93 -0
- package/dist/decorators/formatter.decorators.d.ts.map +1 -0
- package/dist/decorators/formatter.decorators.js +131 -0
- package/dist/decorators/guard.decorators.d.ts +2 -2
- 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 +10 -4
- 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 +4 -4
- package/dist/decorators/pipe.decorators.d.ts.map +1 -1
- package/dist/decorators/pipe.decorators.js +4 -4
- package/dist/dto.js +1 -1
- package/dist/factory.d.ts +30 -2
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +210 -186
- package/dist/filters/exception.filters.d.ts +124 -0
- package/dist/filters/exception.filters.d.ts.map +1 -0
- package/dist/filters/exception.filters.js +208 -0
- 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 +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- 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 +12 -12
- package/dist/pipes/validation.pipe.d.ts.map +1 -1
- package/dist/pipes/validation.pipe.js +43 -15
- package/dist/schema-registry.d.ts +51 -0
- package/dist/schema-registry.d.ts.map +1 -0
- package/dist/schema-registry.js +134 -0
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +2 -2
- 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 +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
|
|
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
|
-
|
|
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
|
|
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: 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
|
|
30
|
+
WynkJS combines the **speed of Elysia** with an **Elegant Decorator-Based Architecture**, giving you the best of both worlds:
|
|
45
31
|
|
|
46
|
-
- 🚀 **
|
|
47
|
-
- 🎨 **Decorator-Based** -
|
|
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
|
-
##
|
|
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
|
|
89
|
+
|
|
90
|
+
[Learn more about create-wynkjs](./packages/create-wynkjs/README.md)
|
|
90
91
|
|
|
91
|
-
|
|
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.
|
|
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:
|
|
@@ -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
|
-
###
|
|
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 {
|
|
@@ -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 {
|
|
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
|
|
669
|
-
// validationErrorFormatter: new SimpleErrorFormatter(), // Simple array
|
|
670
|
-
// validationErrorFormatter: new DetailedErrorFormatter(), // Detailed with paths
|
|
817
|
+
validationErrorFormatter: new DetailedErrorFormatter(), // ✅ Recommended
|
|
671
818
|
});
|
|
819
|
+
```
|
|
672
820
|
|
|
673
|
-
|
|
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
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
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
|
-
**
|
|
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
|
-
##
|
|
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
|
-
|
|
856
|
-
import { Injectable } from "wynkjs";
|
|
1164
|
+
### Core Decorators
|
|
857
1165
|
|
|
858
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1170
|
+
```typescript
|
|
882
1171
|
@Controller("/users")
|
|
883
1172
|
export class UserController {
|
|
884
|
-
|
|
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
|
-
|
|
1177
|
+
#### HTTP Method Decorators
|
|
927
1178
|
|
|
928
|
-
|
|
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
|
-
|
|
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
|
-
|
|
946
|
-
|
|
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
|
-
|
|
1191
|
+
```typescript
|
|
1192
|
+
@Get({ path: "/" }) // GET with options
|
|
952
1193
|
|
|
953
|
-
|
|
1194
|
+
@Post({
|
|
1195
|
+
path: "/",
|
|
1196
|
+
body: CreateUserDTO // POST with body validation
|
|
1197
|
+
})
|
|
954
1198
|
|
|
955
|
-
|
|
1199
|
+
@Patch({
|
|
1200
|
+
path: "/:id",
|
|
1201
|
+
params: UserIdDto, // PATCH with param validation
|
|
1202
|
+
body: UpdateUserDTO // PATCH with body validation
|
|
1203
|
+
})
|
|
956
1204
|
|
|
957
|
-
|
|
1205
|
+
@Get({
|
|
1206
|
+
path: "/",
|
|
1207
|
+
query: UserQueryDto // GET with query validation
|
|
1208
|
+
})
|
|
958
1209
|
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
1210
|
+
@Post({
|
|
1211
|
+
path: "/:id1/:id2",
|
|
1212
|
+
body: CreateUserDTO, // Multiple validations
|
|
1213
|
+
params: MultiParamDto,
|
|
1214
|
+
query: UserQueryDto
|
|
1215
|
+
})
|
|
964
1216
|
```
|
|
965
1217
|
|
|
966
|
-
|
|
1218
|
+
**Available HTTP methods:**
|
|
967
1219
|
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
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
|
-
##
|
|
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. **
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|