wynkjs 1.0.4 → 1.0.7
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 +361 -315
- 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 +62 -1
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +191 -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 +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -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/plugins/compression.d.ts +75 -0
- package/dist/plugins/compression.d.ts.map +1 -0
- package/dist/plugins/compression.js +125 -0
- 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
|
-
_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,95 +19,120 @@ _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, Plugins, 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
|
|
50
36
|
- 🎯 **Simple & Clean** - Easy to learn, powerful to use
|
|
51
|
-
- 🔌 **
|
|
37
|
+
- 🔌 **Plugin System** - Compression, custom middleware via app.use()
|
|
38
|
+
- 🛡️ **Middleware Support** - Guards, interceptors, pipes, filters
|
|
52
39
|
- ⚡ **Bun Only** - Built exclusively for Bun runtime (not Node.js)
|
|
53
40
|
- 📦 **Single Import** - Everything from `wynkjs` (Injectable, Controller, Get, etc.)
|
|
54
41
|
|
|
55
42
|
---
|
|
56
43
|
|
|
57
|
-
##
|
|
58
|
-
|
|
59
|
-
**Requirements:** Bun 1.0 or higher
|
|
44
|
+
## 🚀 Get Started in 30 Seconds:
|
|
60
45
|
|
|
61
|
-
###
|
|
46
|
+
### 📦 create-wynkjs - Project Scaffolding
|
|
62
47
|
|
|
63
|
-
|
|
48
|
+
Quickly scaffold a new WynkJS project with best practices:
|
|
64
49
|
|
|
65
50
|
```bash
|
|
51
|
+
# Create a new project
|
|
66
52
|
bunx create-wynkjs
|
|
67
53
|
# or
|
|
68
54
|
npx create-wynkjs
|
|
69
55
|
```
|
|
70
56
|
|
|
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)
|
|
57
|
+
**What you get:**
|
|
78
58
|
|
|
79
|
-
|
|
59
|
+
- ✅ **TypeScript** - Strict mode with decorators enabled (mandatory)
|
|
60
|
+
- ✅ **ESLint** - Code linting with TypeScript rules (optional)
|
|
61
|
+
- ✅ **Prettier** - Code formatting (optional)
|
|
62
|
+
- ✅ **Husky** - Git hooks for pre-commit checks (optional)
|
|
63
|
+
- ✅ **Hot Reload** - `bun --watch` for instant feedback
|
|
64
|
+
- ✅ **Working Example** - Complete CRUD controller, service, and DTOs
|
|
80
65
|
|
|
81
|
-
|
|
66
|
+
**Generated Project Structure:**
|
|
82
67
|
|
|
83
|
-
```
|
|
84
|
-
|
|
68
|
+
```
|
|
69
|
+
my-wynkjs-app/
|
|
70
|
+
├── src/
|
|
71
|
+
│ ├── modules/
|
|
72
|
+
│ │ └── user/
|
|
73
|
+
│ │ ├── user.controller.ts
|
|
74
|
+
│ │ ├── user.service.ts
|
|
75
|
+
│ │ └── user.dto.ts
|
|
76
|
+
│ └── index.ts
|
|
77
|
+
├── .eslintrc.json
|
|
78
|
+
├── .prettierrc
|
|
79
|
+
├── tsconfig.json
|
|
80
|
+
└── package.json
|
|
85
81
|
```
|
|
86
82
|
|
|
87
|
-
**
|
|
83
|
+
**Available Scripts:**
|
|
88
84
|
|
|
89
|
-
|
|
85
|
+
- `bun run dev` - Development with hot reload
|
|
86
|
+
- `bun run start` - Production server
|
|
87
|
+
- `bun run build` - Build TypeScript
|
|
88
|
+
- `bun run lint` - Run ESLint
|
|
89
|
+
- `bun run format` - Format with Prettier
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
[Learn more about create-wynkjs](./packages/create-wynkjs/README.md)
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
**Example:**
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
bunx create-wynkjs
|
|
97
|
+
# Choose project name: my-api
|
|
98
|
+
# Add ESLint? Yes
|
|
99
|
+
# Add Prettier? Yes
|
|
100
|
+
# Add Husky? No
|
|
101
|
+
|
|
102
|
+
cd my-api
|
|
103
|
+
bun run dev
|
|
104
|
+
# 🚀 Server running on http://localhost:3000
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 1. Find Your DTOs (Data Transfer Objects)
|
|
94
108
|
|
|
95
109
|
```typescript
|
|
96
110
|
// user.dto.ts
|
|
97
111
|
import { DTO, CommonDTO } from "wynkjs";
|
|
98
112
|
|
|
99
113
|
export const CreateUserDTO = DTO.Strict({
|
|
100
|
-
name: DTO.Optional(
|
|
114
|
+
name: DTO.Optional(
|
|
115
|
+
DTO.String({
|
|
116
|
+
maxLength: 50,
|
|
117
|
+
error: "Name must be between 2 and 50 characters",
|
|
118
|
+
})
|
|
119
|
+
),
|
|
101
120
|
email: CommonDTO.Email({
|
|
102
121
|
description: "User email address",
|
|
122
|
+
error: "Please provide a valid email address",
|
|
103
123
|
}),
|
|
104
124
|
mobile: DTO.Optional(
|
|
105
125
|
DTO.String({
|
|
106
126
|
pattern: "^[6-9]{1}[0-9]{9}$",
|
|
107
|
-
|
|
127
|
+
error: "Invalid mobile number format",
|
|
128
|
+
})
|
|
129
|
+
),
|
|
130
|
+
age: DTO.Optional(
|
|
131
|
+
DTO.Number({
|
|
132
|
+
minimum: 18,
|
|
133
|
+
error: "Age must be at least 18 years",
|
|
108
134
|
})
|
|
109
135
|
),
|
|
110
|
-
age: DTO.Optional(DTO.Number({ minimum: 18 })),
|
|
111
136
|
});
|
|
112
137
|
|
|
113
138
|
export interface CreateUserType {
|
|
@@ -126,7 +151,7 @@ export interface ParamIdType {
|
|
|
126
151
|
}
|
|
127
152
|
```
|
|
128
153
|
|
|
129
|
-
### 2.
|
|
154
|
+
### 2. Find Your Service with Dependency Injection
|
|
130
155
|
|
|
131
156
|
```typescript
|
|
132
157
|
// email.service.ts
|
|
@@ -141,7 +166,7 @@ export class EmailService {
|
|
|
141
166
|
}
|
|
142
167
|
```
|
|
143
168
|
|
|
144
|
-
### 3.
|
|
169
|
+
### 3. Find Your Controller
|
|
145
170
|
|
|
146
171
|
```typescript
|
|
147
172
|
// user.controller.ts
|
|
@@ -221,9 +246,9 @@ console.log("🚀 Server running on http://localhost:3000");
|
|
|
221
246
|
### 5. Run Your Server
|
|
222
247
|
|
|
223
248
|
```bash
|
|
224
|
-
bun run
|
|
249
|
+
bun run start
|
|
225
250
|
# or with --watch for hot reload
|
|
226
|
-
bun
|
|
251
|
+
bun run dev
|
|
227
252
|
```
|
|
228
253
|
|
|
229
254
|
### 6. Test Your API
|
|
@@ -254,25 +279,56 @@ That's it! 🎉
|
|
|
254
279
|
|
|
255
280
|
### HTTP Methods
|
|
256
281
|
|
|
282
|
+
All HTTP method decorators support both **string** and **object** formats:
|
|
283
|
+
|
|
257
284
|
```typescript
|
|
258
|
-
|
|
259
|
-
@
|
|
260
|
-
@
|
|
261
|
-
@
|
|
262
|
-
@
|
|
263
|
-
@
|
|
264
|
-
@
|
|
285
|
+
// Simple string format
|
|
286
|
+
@Get(path?: string)
|
|
287
|
+
@Post(path?: string)
|
|
288
|
+
@Put(path?: string)
|
|
289
|
+
@Patch(path?: string)
|
|
290
|
+
@Delete(path?: string)
|
|
291
|
+
@Options(path?: string)
|
|
292
|
+
@Head(path?: string)
|
|
293
|
+
|
|
294
|
+
// Object format with validation
|
|
295
|
+
@Get({ path?: string, params?: Schema, query?: Schema })
|
|
296
|
+
@Post({ path?: string, body?: Schema, params?: Schema, query?: Schema })
|
|
297
|
+
@Put({ path?: string, body?: Schema, params?: Schema, query?: Schema })
|
|
298
|
+
@Patch({ path?: string, body?: Schema, params?: Schema, query?: Schema })
|
|
299
|
+
@Delete({ path?: string, params?: Schema, query?: Schema })
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Examples:**
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
// Simple string path
|
|
306
|
+
@Get("/users")
|
|
307
|
+
async findAll() { }
|
|
308
|
+
|
|
309
|
+
// Object with body validation
|
|
310
|
+
@Post({ path: "/users", body: CreateUserDTO })
|
|
311
|
+
async create(@Body() body: CreateUserType) { }
|
|
312
|
+
|
|
313
|
+
// Object with multiple validations
|
|
314
|
+
@Post({
|
|
315
|
+
path: "/:id1/:id2",
|
|
316
|
+
body: CreateUserDTO,
|
|
317
|
+
params: MultiParamDto,
|
|
318
|
+
query: UserQueryDto
|
|
319
|
+
})
|
|
320
|
+
async create(@Body() body, @Param("id1") id1, @Query() query) { }
|
|
265
321
|
```
|
|
266
322
|
|
|
267
323
|
### Parameter Decorators
|
|
268
324
|
|
|
269
325
|
```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
|
|
326
|
+
@Param(key?: string) // Route parameters (single or all)
|
|
327
|
+
@Body() // Request body (validated by decorator schema)
|
|
328
|
+
@Query(key?: string) // Query parameters (single or all)
|
|
329
|
+
@Headers(key?: string) // Request headers (single or all)
|
|
330
|
+
@Req() // Full Elysia request object
|
|
331
|
+
@Res() // Full Elysia response object
|
|
276
332
|
```
|
|
277
333
|
|
|
278
334
|
### Route Options
|
|
@@ -299,40 +355,6 @@ That's it! 🎉
|
|
|
299
355
|
|
|
300
356
|
WynkJS provides powerful CLI tools to speed up your development workflow:
|
|
301
357
|
|
|
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
358
|
### ⚡ wynkjs-cli - Code Generator
|
|
337
359
|
|
|
338
360
|
Generate modules, controllers, services, and DTOs instantly:
|
|
@@ -450,7 +472,108 @@ Create `wynkjs.config.json` in your project root:
|
|
|
450
472
|
|
|
451
473
|
## 🎯 Features & Examples
|
|
452
474
|
|
|
453
|
-
###
|
|
475
|
+
### 🌐 Built-in CORS Support
|
|
476
|
+
|
|
477
|
+
WynkJS includes built-in CORS support - no additional packages needed!
|
|
478
|
+
|
|
479
|
+
```typescript
|
|
480
|
+
import { WynkFactory, CorsOptions } from "wynkjs";
|
|
481
|
+
|
|
482
|
+
// Simple: Allow all origins (development)
|
|
483
|
+
const app = WynkFactory.create({
|
|
484
|
+
controllers: [UserController],
|
|
485
|
+
cors: true,
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
// Advanced: Custom CORS with specific origins (production)
|
|
489
|
+
const corsOptions: CorsOptions = {
|
|
490
|
+
origin: ["https://yourdomain.com", "https://app.yourdomain.com"],
|
|
491
|
+
credentials: true,
|
|
492
|
+
methods: ["GET", "POST", "PUT", "DELETE"],
|
|
493
|
+
allowedHeaders: ["Content-Type", "Authorization"],
|
|
494
|
+
maxAge: 86400, // 24 hours
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
const app = WynkFactory.create({
|
|
498
|
+
controllers: [UserController],
|
|
499
|
+
cors: corsOptions,
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
// Dynamic origin validation (NestJS-style)
|
|
503
|
+
const corsOptions: CorsOptions = {
|
|
504
|
+
origin: (origin: string) => {
|
|
505
|
+
const allowedOrigins = ["https://yourdomain.com"];
|
|
506
|
+
return allowedOrigins.includes(origin);
|
|
507
|
+
},
|
|
508
|
+
credentials: true,
|
|
509
|
+
};
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
See [CORS.md](./CORS.md) for complete documentation.
|
|
513
|
+
|
|
514
|
+
### � Plugins & Middleware
|
|
515
|
+
|
|
516
|
+
WynkJS provides a flexible plugin system to extend your application. Add compression, rate limiting, caching, and more using the `app.use()` API.
|
|
517
|
+
|
|
518
|
+
#### Compression Plugin (Built-in)
|
|
519
|
+
|
|
520
|
+
Automatically compress HTTP responses with Brotli, Gzip, or Deflate:
|
|
521
|
+
|
|
522
|
+
```typescript
|
|
523
|
+
import { WynkFactory, compression } from "wynkjs";
|
|
524
|
+
|
|
525
|
+
const app = WynkFactory.create({
|
|
526
|
+
controllers: [UserController],
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
// Add compression middleware
|
|
530
|
+
app.use(
|
|
531
|
+
compression({
|
|
532
|
+
threshold: 1024, // Compress responses > 1KB
|
|
533
|
+
encodings: ["br", "gzip", "deflate"], // Prefer brotli, then gzip
|
|
534
|
+
})
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
await app.listen(3000);
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
**Real-world performance:**
|
|
541
|
+
|
|
542
|
+
- Brotli: 58KB → 2.9KB (95% reduction) ⚡
|
|
543
|
+
- Gzip: 58KB → 7.7KB (87% reduction)
|
|
544
|
+
|
|
545
|
+
**Features:**
|
|
546
|
+
|
|
547
|
+
- Smart compression (only compresses if it reduces size)
|
|
548
|
+
- Auto-detects client support
|
|
549
|
+
- Configurable threshold and compression levels
|
|
550
|
+
- No external dependencies
|
|
551
|
+
|
|
552
|
+
See [Plugins README](./core/plugins/README.md) for full documentation and options.
|
|
553
|
+
|
|
554
|
+
#### Custom Plugins
|
|
555
|
+
|
|
556
|
+
Create your own plugins:
|
|
557
|
+
|
|
558
|
+
```typescript
|
|
559
|
+
export function myPlugin(options = {}) {
|
|
560
|
+
return (app: Elysia) => {
|
|
561
|
+
return app
|
|
562
|
+
.onBeforeHandle(async (context) => {
|
|
563
|
+
// Before request
|
|
564
|
+
})
|
|
565
|
+
.onAfterHandle(async (context) => {
|
|
566
|
+
// After request
|
|
567
|
+
return context.response;
|
|
568
|
+
});
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Use it
|
|
573
|
+
app.use(myPlugin({ option: "value" }));
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### �🔒 Authentication with Guards
|
|
454
577
|
|
|
455
578
|
```typescript
|
|
456
579
|
import { Controller, Get, Use } from "wynkjs";
|
|
@@ -561,7 +684,65 @@ export class UserController {
|
|
|
561
684
|
|
|
562
685
|
- Capital: `Injectable`, `Inject`, `Singleton`, `AutoInjectable`, `Container`
|
|
563
686
|
|
|
564
|
-
###
|
|
687
|
+
### � Provider System
|
|
688
|
+
|
|
689
|
+
WynkJS providers are singleton services that initialize when your app starts. Perfect for database connections, configuration, and external services:
|
|
690
|
+
|
|
691
|
+
```typescript
|
|
692
|
+
import { Injectable, singleton } from "wynkjs";
|
|
693
|
+
import { drizzle } from "drizzle-orm/bun-sqlite";
|
|
694
|
+
import { Database } from "bun:sqlite";
|
|
695
|
+
|
|
696
|
+
@Injectable()
|
|
697
|
+
@singleton()
|
|
698
|
+
export class DatabaseService {
|
|
699
|
+
public db: any;
|
|
700
|
+
private sqlite: Database;
|
|
701
|
+
|
|
702
|
+
// Called automatically when app starts
|
|
703
|
+
async onModuleInit() {
|
|
704
|
+
console.log("🔌 Connecting to database...");
|
|
705
|
+
this.sqlite = new Database("mydb.sqlite", { create: true });
|
|
706
|
+
this.db = drizzle(this.sqlite);
|
|
707
|
+
console.log("✅ Database connected");
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
getDb() {
|
|
711
|
+
return this.db;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// Register provider in factory
|
|
716
|
+
const app = WynkFactory.create({
|
|
717
|
+
providers: [DatabaseService], // ✅ Initialized on startup
|
|
718
|
+
controllers: [UserController],
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
// Use in controllers/services
|
|
722
|
+
@Injectable()
|
|
723
|
+
@Controller("/users")
|
|
724
|
+
export class UserController {
|
|
725
|
+
constructor(private dbService: DatabaseService) {}
|
|
726
|
+
|
|
727
|
+
@Get("/")
|
|
728
|
+
async findAll() {
|
|
729
|
+
const db = this.dbService.getDb();
|
|
730
|
+
return await db.select().from(userTable);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
**Benefits:**
|
|
736
|
+
|
|
737
|
+
- ✅ **Automatic Initialization**: Providers init before routes are registered
|
|
738
|
+
- ✅ **Error Handling**: App won't start if provider fails to initialize
|
|
739
|
+
- ✅ **Tight Coupling**: Only registered providers are available
|
|
740
|
+
- ✅ **Lifecycle Hooks**: `onModuleInit()` for setup, `onModuleDestroy()` for cleanup
|
|
741
|
+
- ✅ **Type Safety**: Full TypeScript support with DI
|
|
742
|
+
|
|
743
|
+
**See [docs-wynkjs/PROVIDERS.md](./docs-wynkjs/PROVIDERS.md) for complete guide**
|
|
744
|
+
|
|
745
|
+
### �🗃️ Database Integration (Drizzle ORM)
|
|
565
746
|
|
|
566
747
|
```typescript
|
|
567
748
|
import { drizzle } from "drizzle-orm/bun-sqlite";
|
|
@@ -592,25 +773,38 @@ export class UserService {
|
|
|
592
773
|
|
|
593
774
|
### 📝 Request Validation
|
|
594
775
|
|
|
595
|
-
WynkJS provides automatic request validation with **full IntelliSense support** and customizable error formats:
|
|
776
|
+
WynkJS provides automatic request validation with **full IntelliSense support**, **custom error messages**, and customizable error formats:
|
|
596
777
|
|
|
597
778
|
```typescript
|
|
598
779
|
// user.dto.ts
|
|
599
780
|
import { DTO, CommonDTO } from "wynkjs";
|
|
600
781
|
|
|
601
782
|
// ✨ Full IntelliSense when typing DTO.String(), DTO.Number(), etc!
|
|
783
|
+
// ✨ Add custom error messages with the `error` property
|
|
602
784
|
export const CreateUserDTO = DTO.Strict({
|
|
603
|
-
name: DTO.Optional(
|
|
785
|
+
name: DTO.Optional(
|
|
786
|
+
DTO.String({
|
|
787
|
+
minLength: 2,
|
|
788
|
+
maxLength: 50,
|
|
789
|
+
error: "Name must be between 2 and 50 characters",
|
|
790
|
+
})
|
|
791
|
+
),
|
|
604
792
|
email: CommonDTO.Email({
|
|
605
793
|
description: "User email address",
|
|
794
|
+
error: "Please provide a valid email address",
|
|
606
795
|
}),
|
|
607
796
|
mobile: DTO.Optional(
|
|
608
797
|
DTO.String({
|
|
609
798
|
pattern: "^[6-9]{1}[0-9]{9}$",
|
|
610
|
-
|
|
799
|
+
error: "Invalid mobile number format",
|
|
800
|
+
})
|
|
801
|
+
),
|
|
802
|
+
age: DTO.Optional(
|
|
803
|
+
DTO.Number({
|
|
804
|
+
minimum: 18,
|
|
805
|
+
error: "Age must be at least 18 years",
|
|
611
806
|
})
|
|
612
807
|
),
|
|
613
|
-
age: DTO.Optional(DTO.Number({ minimum: 18 })),
|
|
614
808
|
});
|
|
615
809
|
|
|
616
810
|
export interface CreateUserType {
|
|
@@ -621,8 +815,19 @@ export interface CreateUserType {
|
|
|
621
815
|
}
|
|
622
816
|
|
|
623
817
|
export const UserUpdateDTO = DTO.Strict({
|
|
624
|
-
email: DTO.Optional(
|
|
625
|
-
|
|
818
|
+
email: DTO.Optional(
|
|
819
|
+
DTO.String({
|
|
820
|
+
format: "email",
|
|
821
|
+
minLength: 5,
|
|
822
|
+
error: "Email must be valid and at least 5 characters",
|
|
823
|
+
})
|
|
824
|
+
),
|
|
825
|
+
age: DTO.Optional(
|
|
826
|
+
DTO.Number({
|
|
827
|
+
minimum: 18,
|
|
828
|
+
error: "Age must be at least 18 years",
|
|
829
|
+
})
|
|
830
|
+
),
|
|
626
831
|
});
|
|
627
832
|
|
|
628
833
|
export interface UserUpdateType {
|
|
@@ -883,7 +1088,7 @@ app.useGlobalFilters(
|
|
|
883
1088
|
| Feature | Formatters | Filters |
|
|
884
1089
|
| ---------------- | -------------------------------------------------- | -------------------------- |
|
|
885
1090
|
| **Purpose** | Format validation errors | Handle runtime exceptions |
|
|
886
|
-
| **When?** | During request validation (TypeBox
|
|
1091
|
+
| **When?** | During request validation (TypeBox) | When exceptions are thrown |
|
|
887
1092
|
| **Registration** | `WynkFactory.create({ validationErrorFormatter })` | `app.useGlobalFilters()` |
|
|
888
1093
|
| **Example** | `FormatErrorFormatter` | `DatabaseExceptionFilter` |
|
|
889
1094
|
|
|
@@ -1017,169 +1222,71 @@ my-wynk-app/
|
|
|
1017
1222
|
|
|
1018
1223
|
---
|
|
1019
1224
|
|
|
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
|
-
}
|
|
1225
|
+
## 📖 API Reference
|
|
1050
1226
|
|
|
1051
|
-
|
|
1052
|
-
import { Injectable } from "wynkjs";
|
|
1227
|
+
### Core Decorators
|
|
1053
1228
|
|
|
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
|
-
}
|
|
1229
|
+
#### `@Controller(basePath?: string)`
|
|
1061
1230
|
|
|
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";
|
|
1231
|
+
Define a controller class with optional base path.
|
|
1076
1232
|
|
|
1077
|
-
|
|
1233
|
+
```typescript
|
|
1078
1234
|
@Controller("/users")
|
|
1079
1235
|
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
|
-
}
|
|
1236
|
+
// All routes will be prefixed with /users
|
|
1108
1237
|
}
|
|
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
1238
|
```
|
|
1133
1239
|
|
|
1134
|
-
|
|
1240
|
+
#### HTTP Method Decorators
|
|
1135
1241
|
|
|
1136
|
-
|
|
1137
|
-
# List all users
|
|
1138
|
-
curl http://localhost:3000/users
|
|
1242
|
+
All HTTP methods support both **string** and **object** formats:
|
|
1139
1243
|
|
|
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}'
|
|
1244
|
+
**String format:**
|
|
1144
1245
|
|
|
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
|
|
1246
|
+
```typescript
|
|
1247
|
+
@Get("/") // GET /users
|
|
1248
|
+
@Post("/") // POST /users
|
|
1249
|
+
@Patch("/:id") // PATCH /users/:id
|
|
1155
1250
|
```
|
|
1156
1251
|
|
|
1157
|
-
|
|
1252
|
+
**Object format with validation:**
|
|
1158
1253
|
|
|
1159
|
-
|
|
1254
|
+
```typescript
|
|
1255
|
+
@Get({ path: "/" }) // GET with options
|
|
1160
1256
|
|
|
1161
|
-
|
|
1257
|
+
@Post({
|
|
1258
|
+
path: "/",
|
|
1259
|
+
body: CreateUserDTO // POST with body validation
|
|
1260
|
+
})
|
|
1162
1261
|
|
|
1163
|
-
|
|
1262
|
+
@Patch({
|
|
1263
|
+
path: "/:id",
|
|
1264
|
+
params: UserIdDto, // PATCH with param validation
|
|
1265
|
+
body: UpdateUserDTO // PATCH with body validation
|
|
1266
|
+
})
|
|
1164
1267
|
|
|
1165
|
-
|
|
1268
|
+
@Get({
|
|
1269
|
+
path: "/",
|
|
1270
|
+
query: UserQueryDto // GET with query validation
|
|
1271
|
+
})
|
|
1166
1272
|
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1273
|
+
@Post({
|
|
1274
|
+
path: "/:id1/:id2",
|
|
1275
|
+
body: CreateUserDTO, // Multiple validations
|
|
1276
|
+
params: MultiParamDto,
|
|
1277
|
+
query: UserQueryDto
|
|
1278
|
+
})
|
|
1172
1279
|
```
|
|
1173
1280
|
|
|
1174
|
-
|
|
1281
|
+
**Available HTTP methods:**
|
|
1175
1282
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1283
|
+
- `@Get()` - GET requests (params, query)
|
|
1284
|
+
- `@Post()` - POST requests (body, params, query)
|
|
1285
|
+
- `@Put()` - PUT requests (body, params, query)
|
|
1286
|
+
- `@Patch()` - PATCH requests (body, params, query)
|
|
1287
|
+
- `@Delete()` - DELETE requests (params, query)
|
|
1288
|
+
- `@Options()` - OPTIONS requests
|
|
1289
|
+
- `@Head()` - HEAD requests
|
|
1183
1290
|
|
|
1184
1291
|
#### `@Body()` / `@Param(key?)` / `@Query(key?)`
|
|
1185
1292
|
|
|
@@ -1241,61 +1348,12 @@ throw new InternalServerErrorException("Error"); // 500
|
|
|
1241
1348
|
|
|
1242
1349
|
---
|
|
1243
1350
|
|
|
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
1351
|
## 🔗 Resources
|
|
1296
1352
|
|
|
1297
1353
|
- 📚 [Full Documentation](https://github.com/wynkjs/wynkjs-core)
|
|
1298
|
-
-
|
|
1354
|
+
- 💡 [Example Code](./docs-wynkjs/EXAMPLE_GUIDE.md)
|
|
1355
|
+
- 🏗️ [Architecture Guide](./ARCHITECTURE.md) - Complete guide to formatters vs filters
|
|
1356
|
+
- 🔧 [Provider System](./docs-wynkjs/PROVIDERS.md) - **NEW!** Database, config, and service providers
|
|
1299
1357
|
- 🔄 [Migration Guide](./MIGRATION.md) - Upgrading from older versions
|
|
1300
1358
|
- 🚀 [CLI Tool (create-wynkjs)](./packages/create-wynkjs/README.md)
|
|
1301
1359
|
- 🎨 [Validation Formatters](./docs-wynkjs/VALIDATION_FORMATTERS.md)
|
|
@@ -1337,33 +1395,21 @@ If you find a bug or have a feature request:
|
|
|
1337
1395
|
bun install
|
|
1338
1396
|
```
|
|
1339
1397
|
|
|
1340
|
-
3. **
|
|
1398
|
+
3. **Create a branch**
|
|
1341
1399
|
|
|
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
|
-
```
|
|
1350
|
-
|
|
1351
|
-
4. **Create a branch**
|
|
1352
1400
|
```bash
|
|
1353
1401
|
git checkout -b feature/your-feature-name
|
|
1354
1402
|
# or
|
|
1355
1403
|
git checkout -b fix/bug-description
|
|
1356
1404
|
```
|
|
1357
1405
|
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
1. **Make your changes** in the appropriate package:
|
|
1406
|
+
4. **Make your changes** in the appropriate package:
|
|
1361
1407
|
|
|
1362
1408
|
- `core/` - Core framework decorators and utilities
|
|
1363
1409
|
- `packages/create-wynkjs/` - Project scaffolding CLI
|
|
1364
1410
|
- `packages/wynkjs-cli/` - Code generator CLI
|
|
1365
1411
|
|
|
1366
|
-
|
|
1412
|
+
5. **Test your changes**
|
|
1367
1413
|
|
|
1368
1414
|
```bash
|
|
1369
1415
|
# Test in the example project
|
|
@@ -1374,7 +1420,7 @@ If you find a bug or have a feature request:
|
|
|
1374
1420
|
cd /tmp && bunx /path/to/wynkjs-core/packages/create-wynkjs
|
|
1375
1421
|
```
|
|
1376
1422
|
|
|
1377
|
-
|
|
1423
|
+
6. **Build all packages**
|
|
1378
1424
|
|
|
1379
1425
|
```bash
|
|
1380
1426
|
# From project root
|
|
@@ -1383,7 +1429,7 @@ If you find a bug or have a feature request:
|
|
|
1383
1429
|
cd ../wynkjs-cli && bun run build
|
|
1384
1430
|
```
|
|
1385
1431
|
|
|
1386
|
-
|
|
1432
|
+
7. **Commit your changes**
|
|
1387
1433
|
|
|
1388
1434
|
```bash
|
|
1389
1435
|
git add .
|
|
@@ -1401,7 +1447,7 @@ If you find a bug or have a feature request:
|
|
|
1401
1447
|
- `test:` - Adding tests
|
|
1402
1448
|
- `chore:` - Maintenance tasks
|
|
1403
1449
|
|
|
1404
|
-
|
|
1450
|
+
8. **Push and create a Pull Request**
|
|
1405
1451
|
|
|
1406
1452
|
```bash
|
|
1407
1453
|
git push origin feature/your-feature-name
|