wynkjs 1.0.6 → 1.0.8
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 +142 -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 +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -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/dist/request.d.ts +127 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/request.js +213 -0
- package/dist/response.d.ts +129 -0
- package/dist/response.d.ts.map +1 -0
- package/dist/response.js +260 -0
- package/dist/ultra-optimized-handler.d.ts.map +1 -1
- package/dist/ultra-optimized-handler.js +28 -1
- package/package.json +13 -5
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,145 @@ 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
|
+
#### Swagger / OpenAPI Documentation
|
|
577
|
+
|
|
578
|
+
**✨ New Feature**: WynkJS can use Elysia's Swagger plugin for automatic API documentation!
|
|
579
|
+
|
|
580
|
+
Since WynkJS is built on top of Elysia, you can use the official `@elysiajs/swagger` plugin to generate interactive API documentation from your WynkJS decorators.
|
|
581
|
+
|
|
582
|
+
```bash
|
|
583
|
+
bun add @elysiajs/swagger
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
```typescript
|
|
587
|
+
import { WynkFactory } from "wynkjs";
|
|
588
|
+
import { swagger } from "@elysiajs/swagger";
|
|
589
|
+
|
|
590
|
+
const app = WynkFactory.create({
|
|
591
|
+
controllers: [UserController, ProductController],
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
const server = await app.build();
|
|
595
|
+
|
|
596
|
+
// Add Swagger documentation
|
|
597
|
+
server.use(
|
|
598
|
+
swagger({
|
|
599
|
+
documentation: {
|
|
600
|
+
info: {
|
|
601
|
+
title: "My API Documentation",
|
|
602
|
+
version: "1.0.0",
|
|
603
|
+
description: "Auto-generated from WynkJS decorators",
|
|
604
|
+
},
|
|
605
|
+
tags: [
|
|
606
|
+
{ name: "users", description: "User management" },
|
|
607
|
+
{ name: "products", description: "Product catalog" },
|
|
608
|
+
],
|
|
609
|
+
},
|
|
610
|
+
path: "/docs",
|
|
611
|
+
})
|
|
612
|
+
);
|
|
613
|
+
|
|
614
|
+
server.listen(3000);
|
|
615
|
+
// 📚 Visit: http://localhost:3000/docs
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
**What gets auto-documented:**
|
|
619
|
+
|
|
620
|
+
✅ All HTTP routes (@Get, @Post, etc.)
|
|
621
|
+
✅ Query parameters (from DTOs)
|
|
622
|
+
✅ Request body schemas (from DTOs)
|
|
623
|
+
✅ Path parameters (from DTOs)
|
|
624
|
+
✅ Validation rules (min, max, format)
|
|
625
|
+
✅ JWT Authentication support
|
|
626
|
+
|
|
627
|
+
**With JWT Authentication:**
|
|
628
|
+
|
|
629
|
+
```typescript
|
|
630
|
+
server.use(
|
|
631
|
+
swagger({
|
|
632
|
+
documentation: {
|
|
633
|
+
info: { title: "Secure API", version: "1.0.0" },
|
|
634
|
+
components: {
|
|
635
|
+
securitySchemes: {
|
|
636
|
+
bearerAuth: {
|
|
637
|
+
type: "http",
|
|
638
|
+
scheme: "bearer",
|
|
639
|
+
bearerFormat: "JWT",
|
|
640
|
+
},
|
|
641
|
+
},
|
|
642
|
+
},
|
|
643
|
+
security: [{ bearerAuth: [] }],
|
|
644
|
+
},
|
|
645
|
+
path: "/docs",
|
|
646
|
+
})
|
|
647
|
+
);
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
📚 See [Swagger Integration Guide](./docs/SWAGGER_INTEGRATION.md) for complete examples and best practices.
|
|
651
|
+
|
|
652
|
+
### �🔒 Authentication with Guards
|
|
514
653
|
|
|
515
654
|
```typescript
|
|
516
655
|
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
|
@@ -21,12 +21,21 @@ export * from "./decorators/formatter.decorators";
|
|
|
21
21
|
export * from "./filters/exception.filters";
|
|
22
22
|
export * from "./decorators/database.decorators";
|
|
23
23
|
export * from "./dto";
|
|
24
|
+
export { Request } from "./request";
|
|
25
|
+
export { Response } from "./response";
|
|
26
|
+
export type { WynkRequest } from "./request";
|
|
27
|
+
export type { WynkResponse } from "./response";
|
|
28
|
+
export type { CookieOptions } from "./response";
|
|
29
|
+
export type { Request as RequestType } from "./request";
|
|
30
|
+
export type { Response as ResponseType } from "./response";
|
|
24
31
|
export { schemaRegistry } from "./schema-registry";
|
|
25
32
|
export * from "./factory";
|
|
26
33
|
export type { CorsOptions } from "./cors";
|
|
27
34
|
export { setupCors, validateCorsOptions } from "./cors";
|
|
28
35
|
export type { GlobalPrefixOptions } from "./global-prefix";
|
|
29
36
|
export { applyGlobalPrefix, normalizePrefixPath, validateGlobalPrefix, wrapWithPrefix, } from "./global-prefix";
|
|
37
|
+
export { compression } from "./plugins/compression";
|
|
38
|
+
export type { CompressionOptions } from "./plugins/compression";
|
|
30
39
|
export * from "./testing";
|
|
31
40
|
/**
|
|
32
41
|
* 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,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,YAAY,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AACxD,YAAY,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,YAAY,CAAC;AAG3D,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
|
@@ -40,12 +40,17 @@ export * from "./decorators/database.decorators";
|
|
|
40
40
|
// See: plugins/drizzle and plugins/mongoose
|
|
41
41
|
// DTO Utilities
|
|
42
42
|
export * from "./dto";
|
|
43
|
+
// Request and Response wrappers
|
|
44
|
+
export { Request } from "./request";
|
|
45
|
+
export { Response } from "./response";
|
|
43
46
|
// Schema Registry for custom error messages
|
|
44
47
|
export { schemaRegistry } from "./schema-registry";
|
|
45
48
|
// Application Factory
|
|
46
49
|
export * from "./factory";
|
|
47
50
|
export { setupCors, validateCorsOptions } from "./cors";
|
|
48
51
|
export { applyGlobalPrefix, normalizePrefixPath, validateGlobalPrefix, wrapWithPrefix, } from "./global-prefix";
|
|
52
|
+
// Plugins
|
|
53
|
+
export { compression } from "./plugins/compression";
|
|
49
54
|
// Testing Module
|
|
50
55
|
export * from "./testing";
|
|
51
56
|
/**
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request Wrapper for WynkJS Framework
|
|
3
|
+
* Provides a clean API for accessing request data and adding custom properties
|
|
4
|
+
*/
|
|
5
|
+
export interface CookieOptions {
|
|
6
|
+
domain?: string;
|
|
7
|
+
expires?: Date;
|
|
8
|
+
httpOnly?: boolean;
|
|
9
|
+
maxAge?: number;
|
|
10
|
+
path?: string;
|
|
11
|
+
sameSite?: boolean | "lax" | "strict" | "none";
|
|
12
|
+
secure?: boolean;
|
|
13
|
+
priority?: "low" | "medium" | "high";
|
|
14
|
+
partitioned?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Request class - wraps Elysia context for request operations
|
|
18
|
+
* Allows middleware to add custom properties that persist through the request lifecycle
|
|
19
|
+
*/
|
|
20
|
+
export declare class Request {
|
|
21
|
+
private ctx;
|
|
22
|
+
private customData;
|
|
23
|
+
private originalRequest;
|
|
24
|
+
constructor(ctx: any);
|
|
25
|
+
/**
|
|
26
|
+
* Get request body
|
|
27
|
+
*/
|
|
28
|
+
get body(): any;
|
|
29
|
+
/**
|
|
30
|
+
* Get route parameters
|
|
31
|
+
*/
|
|
32
|
+
get params(): any;
|
|
33
|
+
/**
|
|
34
|
+
* Get query parameters
|
|
35
|
+
*/
|
|
36
|
+
get query(): any;
|
|
37
|
+
/**
|
|
38
|
+
* Get request headers
|
|
39
|
+
*/
|
|
40
|
+
get headers(): any;
|
|
41
|
+
/**
|
|
42
|
+
* Get request method (GET, POST, etc.)
|
|
43
|
+
*/
|
|
44
|
+
get method(): string;
|
|
45
|
+
/**
|
|
46
|
+
* Get request URL
|
|
47
|
+
*/
|
|
48
|
+
get url(): string;
|
|
49
|
+
/**
|
|
50
|
+
* Get request path
|
|
51
|
+
*/
|
|
52
|
+
get path(): string;
|
|
53
|
+
/**
|
|
54
|
+
* Get client IP address
|
|
55
|
+
*/
|
|
56
|
+
get ip(): string | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Get cookies from request
|
|
59
|
+
*/
|
|
60
|
+
get cookies(): Record<string, string>;
|
|
61
|
+
/**
|
|
62
|
+
* Get a specific cookie value
|
|
63
|
+
*/
|
|
64
|
+
getCookie(name: string): string | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Get user object (set by authentication middleware)
|
|
67
|
+
*/
|
|
68
|
+
get user(): any;
|
|
69
|
+
/**
|
|
70
|
+
* Set user object (typically used by authentication middleware)
|
|
71
|
+
*/
|
|
72
|
+
set user(value: any);
|
|
73
|
+
/**
|
|
74
|
+
* Get the raw Elysia context
|
|
75
|
+
*/
|
|
76
|
+
get raw(): any;
|
|
77
|
+
/**
|
|
78
|
+
* Get the Response wrapper instance
|
|
79
|
+
*/
|
|
80
|
+
getResponse(): any;
|
|
81
|
+
/**
|
|
82
|
+
* Set custom data that persists through request lifecycle
|
|
83
|
+
* Useful for middleware to pass data to handlers
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* // In middleware
|
|
87
|
+
* request.set('startTime', Date.now());
|
|
88
|
+
*
|
|
89
|
+
* // In handler
|
|
90
|
+
* const startTime = request.get('startTime');
|
|
91
|
+
*/
|
|
92
|
+
set(key: string, value: any): this;
|
|
93
|
+
/**
|
|
94
|
+
* Get custom data set by middleware
|
|
95
|
+
*/
|
|
96
|
+
get(key: string): any;
|
|
97
|
+
/**
|
|
98
|
+
* Check if custom data exists
|
|
99
|
+
*/
|
|
100
|
+
has(key: string): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Delete custom data
|
|
103
|
+
*/
|
|
104
|
+
delete(key: string): boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Get all custom data
|
|
107
|
+
*/
|
|
108
|
+
getAllCustomData(): Record<string, any>;
|
|
109
|
+
/**
|
|
110
|
+
* Check if request accepts a certain content type
|
|
111
|
+
*/
|
|
112
|
+
accepts(type: string): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Check if request is JSON
|
|
115
|
+
*/
|
|
116
|
+
isJson(): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Check if request is form data
|
|
119
|
+
*/
|
|
120
|
+
isFormData(): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Get bearer token from Authorization header
|
|
123
|
+
*/
|
|
124
|
+
getBearerToken(): string | undefined;
|
|
125
|
+
}
|
|
126
|
+
export type WynkRequest = Request;
|
|
127
|
+
//# sourceMappingURL=request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../core/request.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,eAAe,CAAM;gBAEjB,GAAG,EAAE,GAAG;IAMpB;;OAEG;IACH,IAAI,IAAI,IAAI,GAAG,CAEd;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,GAAG,CAEhB;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,GAAG,CAEf;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,GAAG,CAoBjB;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,GAAG,SAAS,CAM3B;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAapC;IAED;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3C;;OAEG;IACH,IAAI,IAAI,IAAI,GAAG,CAEd;IAED;;OAEG;IACH,IAAI,IAAI,CAAC,KAAK,EAAE,GAAG,EAElB;IAED;;OAEG;IACH,IAAI,GAAG,IAAI,GAAG,CAEb;IAED;;OAEG;IACH,WAAW,IAAI,GAAG;IAIlB;;;;;;;;;;OAUG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAUlC;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG;IAIrB;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAQ5B;;OAEG;IACH,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAQvC;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAK9B;;OAEG;IACH,MAAM,IAAI,OAAO;IAKjB;;OAEG;IACH,UAAU,IAAI,OAAO;IAKrB;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,SAAS;CAOrC;AAGD,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC"}
|