wynkjs 1.0.6 → 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 +66 -3
- package/dist/factory.d.ts +33 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +36 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- 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/package.json +8 -3
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ _10x faster than Express/NestJs, built for modern TypeScript development for Bun
|
|
|
19
19
|
|
|
20
20
|
## About
|
|
21
21
|
|
|
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.
|
|
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
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.
|
|
25
25
|
|
|
@@ -34,7 +34,8 @@ WynkJS combines the **speed of Elysia** with an **Elegant Decorator-Based Archit
|
|
|
34
34
|
- 💉 **Dependency Injection** - Built-in DI (no need to import reflect-metadata!)
|
|
35
35
|
- 🔒 **TypeScript First** - TypeScript is mandatory, not optional. Full type safety and IntelliSense support
|
|
36
36
|
- 🎯 **Simple & Clean** - Easy to learn, powerful to use
|
|
37
|
-
- 🔌 **
|
|
37
|
+
- 🔌 **Plugin System** - Compression, custom middleware via app.use()
|
|
38
|
+
- 🛡️ **Middleware Support** - Guards, interceptors, pipes, filters
|
|
38
39
|
- ⚡ **Bun Only** - Built exclusively for Bun runtime (not Node.js)
|
|
39
40
|
- 📦 **Single Import** - Everything from `wynkjs` (Injectable, Controller, Get, etc.)
|
|
40
41
|
|
|
@@ -510,7 +511,69 @@ const corsOptions: CorsOptions = {
|
|
|
510
511
|
|
|
511
512
|
See [CORS.md](./CORS.md) for complete documentation.
|
|
512
513
|
|
|
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
|
|
514
577
|
|
|
515
578
|
```typescript
|
|
516
579
|
import { Controller, Get, Use } from "wynkjs";
|
package/dist/factory.d.ts
CHANGED
|
@@ -72,6 +72,39 @@ export declare class WynkFramework {
|
|
|
72
72
|
* Providers with onModuleDestroy() method will be called
|
|
73
73
|
*/
|
|
74
74
|
private destroyProviders;
|
|
75
|
+
/**
|
|
76
|
+
* Use an Elysia plugin or middleware (fully compatible with Elysia.js ecosystem)
|
|
77
|
+
*
|
|
78
|
+
* This method directly proxies to Elysia's use() method, making all Elysia plugins
|
|
79
|
+
* and middleware work seamlessly with WynkJS.
|
|
80
|
+
*
|
|
81
|
+
* @param plugin - Any Elysia plugin or instance
|
|
82
|
+
* @returns this for method chaining
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* import { WynkFactory } from "wynkjs";
|
|
87
|
+
* import { compression } from "wynkjs";
|
|
88
|
+
* import { cors } from "@elysiajs/cors";
|
|
89
|
+
* import { swagger } from "@elysiajs/swagger";
|
|
90
|
+
* import { jwt } from "@elysiajs/jwt";
|
|
91
|
+
*
|
|
92
|
+
* const app = WynkFactory.create({
|
|
93
|
+
* controllers: [UserController],
|
|
94
|
+
* });
|
|
95
|
+
*
|
|
96
|
+
* // Use WynkJS built-in plugins
|
|
97
|
+
* app.use(compression({ threshold: 1024 }));
|
|
98
|
+
*
|
|
99
|
+
* // Use any Elysia plugin from npm
|
|
100
|
+
* app.use(cors());
|
|
101
|
+
* app.use(swagger());
|
|
102
|
+
* app.use(jwt({ name: 'jwt', secret: 'secret' }));
|
|
103
|
+
*
|
|
104
|
+
* await app.listen(3000);
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
use(...plugins: any[]): this;
|
|
75
108
|
/**
|
|
76
109
|
* Start listening on a port
|
|
77
110
|
*/
|
package/dist/factory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../core/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,kBAAkB,CAAC;AAc1B,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAa,MAAM,QAAQ,CAAC;AAOhD;;;GAGG;AAEH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wBAAwB,CAAC,EAAE,cAAc,CAAC;IAC1C,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;CACnB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,mBAAmB,CAAC,CAAiB;IAC7C,OAAO,CAAC,0BAA0B,CAAS;IAC3C,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,GAAE,kBAAuB;IA2L5C;;OAEG;IACH,MAAM,CAAC,MAAM,CACX,OAAO,GAAE,kBAAkB,GAAG;QAC5B,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;QACpB,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;KACd,GACL,aAAa;IAahB;;;OAGG;IACH,iBAAiB,CAAC,GAAG,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI;IAK5C;;OAEG;IACH,mBAAmB,CAAC,GAAG,WAAW,EAAE,GAAG,EAAE,GAAG,IAAI;IAKhD;;OAEG;IACH,eAAe,CAAC,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI;IAKvC;;OAEG;IACH,qBAAqB,CAAC,GAAG,YAAY,EAAE,GAAG,EAAE,GAAG,IAAI;IAKnD;;OAEG;IACH,cAAc,CAAC,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI;IAKrC;;OAEG;IACH,gBAAgB,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI;IAKzC;;;OAGG;YACW,mBAAmB;IAkCjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAwD9B;;;OAGG;YACW,gBAAgB;IA0B9B;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkCzC;;OAEG;IACH,MAAM,IAAI,MAAM;IAIhB;;;OAGG;IACG,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAOjD;;OAEG;YACW,kBAAkB;CAwLjC;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,kBAAuB,GAAG,aAAa,CAEzE;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,MAAM,CAAC,MAAM,CACX,OAAO,GAAE,kBAAkB,GAAG;QAC5B,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;QACpB,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;KACd,GACL,aAAa;CAYjB;AAGD,OAAO,EAAE,aAAa,IAAI,eAAe,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../core/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,kBAAkB,CAAC;AAc1B,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAa,MAAM,QAAQ,CAAC;AAOhD;;;GAGG;AAEH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wBAAwB,CAAC,EAAE,cAAc,CAAC;IAC1C,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;CACnB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,mBAAmB,CAAC,CAAiB;IAC7C,OAAO,CAAC,0BAA0B,CAAS;IAC3C,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,GAAE,kBAAuB;IA2L5C;;OAEG;IACH,MAAM,CAAC,MAAM,CACX,OAAO,GAAE,kBAAkB,GAAG;QAC5B,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;QACpB,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;KACd,GACL,aAAa;IAahB;;;OAGG;IACH,iBAAiB,CAAC,GAAG,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI;IAK5C;;OAEG;IACH,mBAAmB,CAAC,GAAG,WAAW,EAAE,GAAG,EAAE,GAAG,IAAI;IAKhD;;OAEG;IACH,eAAe,CAAC,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI;IAKvC;;OAEG;IACH,qBAAqB,CAAC,GAAG,YAAY,EAAE,GAAG,EAAE,GAAG,IAAI;IAKnD;;OAEG;IACH,cAAc,CAAC,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI;IAKrC;;OAEG;IACH,gBAAgB,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI;IAKzC;;;OAGG;YACW,mBAAmB;IAkCjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAwD9B;;;OAGG;YACW,gBAAgB;IA0B9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,GAAG,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI;IAK5B;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkCzC;;OAEG;IACH,MAAM,IAAI,MAAM;IAIhB;;;OAGG;IACG,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAOjD;;OAEG;YACW,kBAAkB;CAwLjC;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,kBAAuB,GAAG,aAAa,CAEzE;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,MAAM,CAAC,MAAM,CACX,OAAO,GAAE,kBAAkB,GAAG;QAC5B,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;QACpB,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;KACd,GACL,aAAa;CAYjB;AAGD,OAAO,EAAE,aAAa,IAAI,eAAe,EAAE,CAAC"}
|
package/dist/factory.js
CHANGED
|
@@ -316,6 +316,42 @@ export class WynkFramework {
|
|
|
316
316
|
}
|
|
317
317
|
console.log(`✅ All providers cleaned up\n`);
|
|
318
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* Use an Elysia plugin or middleware (fully compatible with Elysia.js ecosystem)
|
|
321
|
+
*
|
|
322
|
+
* This method directly proxies to Elysia's use() method, making all Elysia plugins
|
|
323
|
+
* and middleware work seamlessly with WynkJS.
|
|
324
|
+
*
|
|
325
|
+
* @param plugin - Any Elysia plugin or instance
|
|
326
|
+
* @returns this for method chaining
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```typescript
|
|
330
|
+
* import { WynkFactory } from "wynkjs";
|
|
331
|
+
* import { compression } from "wynkjs";
|
|
332
|
+
* import { cors } from "@elysiajs/cors";
|
|
333
|
+
* import { swagger } from "@elysiajs/swagger";
|
|
334
|
+
* import { jwt } from "@elysiajs/jwt";
|
|
335
|
+
*
|
|
336
|
+
* const app = WynkFactory.create({
|
|
337
|
+
* controllers: [UserController],
|
|
338
|
+
* });
|
|
339
|
+
*
|
|
340
|
+
* // Use WynkJS built-in plugins
|
|
341
|
+
* app.use(compression({ threshold: 1024 }));
|
|
342
|
+
*
|
|
343
|
+
* // Use any Elysia plugin from npm
|
|
344
|
+
* app.use(cors());
|
|
345
|
+
* app.use(swagger());
|
|
346
|
+
* app.use(jwt({ name: 'jwt', secret: 'secret' }));
|
|
347
|
+
*
|
|
348
|
+
* await app.listen(3000);
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
use(...plugins) {
|
|
352
|
+
this.app.use(...plugins);
|
|
353
|
+
return this;
|
|
354
|
+
}
|
|
319
355
|
/**
|
|
320
356
|
* Start listening on a port
|
|
321
357
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export type { CorsOptions } from "./cors";
|
|
|
27
27
|
export { setupCors, validateCorsOptions } from "./cors";
|
|
28
28
|
export type { GlobalPrefixOptions } from "./global-prefix";
|
|
29
29
|
export { applyGlobalPrefix, normalizePrefixPath, validateGlobalPrefix, wrapWithPrefix, } from "./global-prefix";
|
|
30
|
+
export { compression } from "./plugins/compression";
|
|
31
|
+
export type { CompressionOptions } from "./plugins/compression";
|
|
30
32
|
export * from "./testing";
|
|
31
33
|
/**
|
|
32
34
|
* Framework version
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../core/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,kBAAkB,CAAC;AAI1B,OAAO,EACL,UAAU,EACV,MAAM,EACN,SAAS,EACT,cAAc,EACd,QAAQ,EACR,SAAS,GACV,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAGpD,OAAO,EACL,UAAU,IAAI,UAAU,EACxB,MAAM,IAAI,MAAM,EAChB,SAAS,IAAI,SAAS,EACtB,cAAc,IAAI,cAAc,EAChC,QAAQ,IAAI,QAAQ,EACpB,SAAS,IAAI,SAAS,GACvB,MAAM,UAAU,CAAC;AAGlB,cAAc,8BAA8B,CAAC;AAG7C,cAAc,+BAA+B,CAAC;AAG9C,cAAc,+BAA+B,CAAC;AAG9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,mCAAmC,CAAC;AAGlD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAI3C,cAAc,mCAAmC,CAAC;AAClD,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAI5C,cAAc,kCAAkC,CAAC;AASjD,cAAc,OAAO,CAAC;AAGtB,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGnD,cAAc,WAAW,CAAC;AAG1B,YAAY,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAGxD,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,GACf,MAAM,iBAAiB,CAAC;AAGzB,cAAc,WAAW,CAAC;AAE1B;;GAEG;AACH,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B;;GAEG;AACH,eAAO,MAAM,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../core/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,kBAAkB,CAAC;AAI1B,OAAO,EACL,UAAU,EACV,MAAM,EACN,SAAS,EACT,cAAc,EACd,QAAQ,EACR,SAAS,GACV,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAGpD,OAAO,EACL,UAAU,IAAI,UAAU,EACxB,MAAM,IAAI,MAAM,EAChB,SAAS,IAAI,SAAS,EACtB,cAAc,IAAI,cAAc,EAChC,QAAQ,IAAI,QAAQ,EACpB,SAAS,IAAI,SAAS,GACvB,MAAM,UAAU,CAAC;AAGlB,cAAc,8BAA8B,CAAC;AAG7C,cAAc,+BAA+B,CAAC;AAG9C,cAAc,+BAA+B,CAAC;AAG9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,mCAAmC,CAAC;AAGlD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAI3C,cAAc,mCAAmC,CAAC;AAClD,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAI5C,cAAc,kCAAkC,CAAC;AASjD,cAAc,OAAO,CAAC;AAGtB,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGnD,cAAc,WAAW,CAAC;AAG1B,YAAY,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAGxD,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,GACf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAGhE,cAAc,WAAW,CAAC;AAE1B;;GAEG;AACH,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B;;GAEG;AACH,eAAO,MAAM,cAAc,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,8 @@ export { schemaRegistry } from "./schema-registry";
|
|
|
46
46
|
export * from "./factory";
|
|
47
47
|
export { setupCors, validateCorsOptions } from "./cors";
|
|
48
48
|
export { applyGlobalPrefix, normalizePrefixPath, validateGlobalPrefix, wrapWithPrefix, } from "./global-prefix";
|
|
49
|
+
// Plugins
|
|
50
|
+
export { compression } from "./plugins/compression";
|
|
49
51
|
// Testing Module
|
|
50
52
|
export * from "./testing";
|
|
51
53
|
/**
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compression Plugin Options
|
|
3
|
+
*/
|
|
4
|
+
export interface CompressionOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Minimum byte size for compression
|
|
7
|
+
* @default 1024
|
|
8
|
+
*/
|
|
9
|
+
threshold?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Preferred encoding order (first match will be used)
|
|
12
|
+
* @default ["br", "gzip", "deflate"]
|
|
13
|
+
*/
|
|
14
|
+
encodings?: ("br" | "gzip" | "deflate")[];
|
|
15
|
+
/**
|
|
16
|
+
* Brotli compression options
|
|
17
|
+
*/
|
|
18
|
+
brotliOptions?: {
|
|
19
|
+
params?: Record<number, number>;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Zlib (gzip/deflate) compression options
|
|
23
|
+
*/
|
|
24
|
+
zlibOptions?: {
|
|
25
|
+
level?: number;
|
|
26
|
+
memLevel?: number;
|
|
27
|
+
strategy?: number;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Compression Plugin for WynkJS
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* import { WynkFactory } from "wynkjs";
|
|
36
|
+
* import { compression } from "wynkjs/plugins/compression";
|
|
37
|
+
*
|
|
38
|
+
* const app = WynkFactory.create({
|
|
39
|
+
* controllers: [UserController],
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* // Add compression middleware
|
|
43
|
+
* app.use(compression({
|
|
44
|
+
* threshold: 1024,
|
|
45
|
+
* encodings: ["br", "gzip", "deflate"]
|
|
46
|
+
* }));
|
|
47
|
+
*
|
|
48
|
+
* await app.listen(3000);
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* Compression Plugin for WynkJS
|
|
53
|
+
*
|
|
54
|
+
* Simple compression middleware using Elysia's onAfterHandle hook
|
|
55
|
+
* Supports Brotli, Gzip, and Deflate compression
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* import { WynkFactory, compression } from "wynkjs";
|
|
60
|
+
*
|
|
61
|
+
* const app = WynkFactory.create({
|
|
62
|
+
* controllers: [UserController],
|
|
63
|
+
* });
|
|
64
|
+
*
|
|
65
|
+
* // Add compression middleware
|
|
66
|
+
* app.use(compression({
|
|
67
|
+
* threshold: 1024,
|
|
68
|
+
* encodings: ["gzip", "br"]
|
|
69
|
+
* }));
|
|
70
|
+
*
|
|
71
|
+
* await app.listen(3000);
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare function compression(options?: CompressionOptions): (app: any) => any;
|
|
75
|
+
//# sourceMappingURL=compression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../../core/plugins/compression.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;IAE1C;;OAEG;IACH,aAAa,CAAC,EAAE;QACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACjC,CAAC;IAEF;;OAEG;IACH,WAAW,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CACzB,OAAO,GAAE,kBAAuB,GAC/B,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CA4FnB"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compression Plugin for WynkJS
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { WynkFactory } from "wynkjs";
|
|
7
|
+
* import { compression } from "wynkjs/plugins/compression";
|
|
8
|
+
*
|
|
9
|
+
* const app = WynkFactory.create({
|
|
10
|
+
* controllers: [UserController],
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* // Add compression middleware
|
|
14
|
+
* app.use(compression({
|
|
15
|
+
* threshold: 1024,
|
|
16
|
+
* encodings: ["br", "gzip", "deflate"]
|
|
17
|
+
* }));
|
|
18
|
+
*
|
|
19
|
+
* await app.listen(3000);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Compression Plugin for WynkJS
|
|
24
|
+
*
|
|
25
|
+
* Simple compression middleware using Elysia's onAfterHandle hook
|
|
26
|
+
* Supports Brotli, Gzip, and Deflate compression
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { WynkFactory, compression } from "wynkjs";
|
|
31
|
+
*
|
|
32
|
+
* const app = WynkFactory.create({
|
|
33
|
+
* controllers: [UserController],
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* // Add compression middleware
|
|
37
|
+
* app.use(compression({
|
|
38
|
+
* threshold: 1024,
|
|
39
|
+
* encodings: ["gzip", "br"]
|
|
40
|
+
* }));
|
|
41
|
+
*
|
|
42
|
+
* await app.listen(3000);
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export function compression(options = {}) {
|
|
46
|
+
const config = {
|
|
47
|
+
threshold: options.threshold ?? 1024,
|
|
48
|
+
encodings: options.encodings ?? ["gzip", "br", "deflate"],
|
|
49
|
+
brotliOptions: options.brotliOptions ?? {},
|
|
50
|
+
zlibOptions: options.zlibOptions ?? {},
|
|
51
|
+
};
|
|
52
|
+
return (app) => {
|
|
53
|
+
return app.onAfterHandle(async function compressionHandler(context) {
|
|
54
|
+
const { response, request, set } = context;
|
|
55
|
+
// Skip if no response
|
|
56
|
+
if (!response)
|
|
57
|
+
return;
|
|
58
|
+
// Skip if already compressed
|
|
59
|
+
if (set.headers?.["content-encoding"])
|
|
60
|
+
return;
|
|
61
|
+
// Get client's accepted encodings
|
|
62
|
+
const acceptEncoding = (request.headers.get("accept-encoding") || "").toLowerCase();
|
|
63
|
+
// Find best compression match
|
|
64
|
+
let encoding = null;
|
|
65
|
+
for (const enc of config.encodings) {
|
|
66
|
+
if (acceptEncoding.includes(enc)) {
|
|
67
|
+
encoding = enc;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (!encoding)
|
|
72
|
+
return; // No supported encoding
|
|
73
|
+
// Convert response to buffer
|
|
74
|
+
let body;
|
|
75
|
+
if (Buffer.isBuffer(response)) {
|
|
76
|
+
body = response;
|
|
77
|
+
}
|
|
78
|
+
else if (typeof response === "string") {
|
|
79
|
+
body = Buffer.from(response);
|
|
80
|
+
}
|
|
81
|
+
else if (typeof response === "object") {
|
|
82
|
+
body = Buffer.from(JSON.stringify(response));
|
|
83
|
+
set.headers["content-type"] =
|
|
84
|
+
set.headers["content-type"] || "application/json";
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
body = Buffer.from(String(response));
|
|
88
|
+
}
|
|
89
|
+
// Check size threshold
|
|
90
|
+
if (body.length < config.threshold)
|
|
91
|
+
return;
|
|
92
|
+
// Compress
|
|
93
|
+
try {
|
|
94
|
+
const zlib = await import("node:zlib");
|
|
95
|
+
const { promisify } = await import("node:util");
|
|
96
|
+
let compressed;
|
|
97
|
+
switch (encoding) {
|
|
98
|
+
case "br":
|
|
99
|
+
compressed = await promisify(zlib.brotliCompress)(body, config.brotliOptions);
|
|
100
|
+
break;
|
|
101
|
+
case "gzip":
|
|
102
|
+
compressed = await promisify(zlib.gzip)(body, config.zlibOptions);
|
|
103
|
+
break;
|
|
104
|
+
case "deflate":
|
|
105
|
+
compressed = await promisify(zlib.deflate)(body, config.zlibOptions);
|
|
106
|
+
break;
|
|
107
|
+
default:
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Only use if smaller
|
|
111
|
+
if (compressed.length >= body.length)
|
|
112
|
+
return;
|
|
113
|
+
// Set headers and return compressed body
|
|
114
|
+
set.headers["content-encoding"] = encoding;
|
|
115
|
+
set.headers["vary"] = "Accept-Encoding";
|
|
116
|
+
delete set.headers["content-length"]; // Let Elysia set this
|
|
117
|
+
return compressed;
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
console.error("[Compression Error]:", error);
|
|
121
|
+
return; // Return original on error
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wynkjs",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "A high-performance TypeScript framework built on Elysia for Bun with elegant decorator-based architecture - 10x faster than Express/NestJS",
|
|
3
|
+
"version": "1.0.7",
|
|
4
|
+
"description": "A high-performance TypeScript framework built on Elysia for Bun with elegant decorator-based architecture, built-in compression, and plugin system - 10x faster than Express/NestJS",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -27,7 +27,12 @@
|
|
|
27
27
|
"dependency-injection",
|
|
28
28
|
"rest-api",
|
|
29
29
|
"backend",
|
|
30
|
-
"server"
|
|
30
|
+
"server",
|
|
31
|
+
"compression",
|
|
32
|
+
"gzip",
|
|
33
|
+
"brotli",
|
|
34
|
+
"plugins",
|
|
35
|
+
"middleware"
|
|
31
36
|
],
|
|
32
37
|
"author": "Alam Jamal alamjamal88@gmail.com",
|
|
33
38
|
"license": "MIT",
|