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.
Files changed (46) hide show
  1. package/README.md +361 -315
  2. package/dist/cors.d.ts +28 -0
  3. package/dist/cors.d.ts.map +1 -0
  4. package/dist/cors.js +121 -0
  5. package/dist/decorators/exception.decorators.d.ts +1 -0
  6. package/dist/decorators/exception.decorators.d.ts.map +1 -1
  7. package/dist/decorators/exception.decorators.js +20 -3
  8. package/dist/decorators/guard.decorators.d.ts.map +1 -1
  9. package/dist/decorators/guard.decorators.js +11 -5
  10. package/dist/decorators/http.decorators.d.ts +8 -3
  11. package/dist/decorators/http.decorators.d.ts.map +1 -1
  12. package/dist/decorators/http.decorators.js +9 -2
  13. package/dist/decorators/interceptor.advanced.d.ts +9 -9
  14. package/dist/decorators/interceptor.advanced.d.ts.map +1 -1
  15. package/dist/decorators/interceptor.advanced.js +7 -7
  16. package/dist/decorators/interceptor.decorators.d.ts +9 -7
  17. package/dist/decorators/interceptor.decorators.d.ts.map +1 -1
  18. package/dist/decorators/interceptor.decorators.js +29 -18
  19. package/dist/decorators/param.decorators.d.ts +2 -2
  20. package/dist/decorators/param.decorators.js +1 -1
  21. package/dist/decorators/pipe.decorators.d.ts +2 -2
  22. package/dist/decorators/pipe.decorators.js +2 -2
  23. package/dist/factory.d.ts +62 -1
  24. package/dist/factory.d.ts.map +1 -1
  25. package/dist/factory.js +191 -180
  26. package/dist/global-prefix.d.ts +49 -0
  27. package/dist/global-prefix.d.ts.map +1 -0
  28. package/dist/global-prefix.js +155 -0
  29. package/dist/index.d.ts +6 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +4 -0
  32. package/dist/interfaces/interceptor.interface.d.ts +15 -0
  33. package/dist/interfaces/interceptor.interface.d.ts.map +1 -0
  34. package/dist/interfaces/interceptor.interface.js +1 -0
  35. package/dist/optimized-handler.d.ts +31 -0
  36. package/dist/optimized-handler.d.ts.map +1 -0
  37. package/dist/optimized-handler.js +180 -0
  38. package/dist/pipes/validation.pipe.d.ts +10 -10
  39. package/dist/pipes/validation.pipe.js +4 -4
  40. package/dist/plugins/compression.d.ts +75 -0
  41. package/dist/plugins/compression.d.ts.map +1 -0
  42. package/dist/plugins/compression.js +125 -0
  43. package/dist/ultra-optimized-handler.d.ts +51 -0
  44. package/dist/ultra-optimized-handler.d.ts.map +1 -0
  45. package/dist/ultra-optimized-handler.js +302 -0
  46. package/package.json +17 -10
@@ -0,0 +1,49 @@
1
+ import { Elysia } from "elysia";
2
+ /**
3
+ * Global Prefix Module for WynkJS Framework
4
+ * Adds a prefix to all routes in the application
5
+ * Separated from factory.ts for better maintainability
6
+ */
7
+ export interface GlobalPrefixOptions {
8
+ prefix: string;
9
+ exclude?: string[];
10
+ }
11
+ /**
12
+ * Apply global prefix to all routes
13
+ * @param app - Elysia instance
14
+ * @param prefix - Prefix string (e.g., '/api', '/v1')
15
+ * @param options - Additional options like route exclusions
16
+ * @returns Modified Elysia instance
17
+ */
18
+ export declare function applyGlobalPrefix(app: Elysia, prefix: string | GlobalPrefixOptions): any;
19
+ /**
20
+ * Normalize prefix path
21
+ * - Ensures it starts with /
22
+ * - Removes trailing /
23
+ * - Validates format
24
+ * @param prefix - Raw prefix string
25
+ * @returns Normalized prefix
26
+ */
27
+ export declare function normalizePrefixPath(prefix: string): string;
28
+ /**
29
+ * Check if a route should be excluded from global prefix
30
+ * @param path - Route path
31
+ * @param excludedRoutes - List of routes to exclude
32
+ * @returns true if route should be excluded
33
+ */
34
+ export declare function isRouteExcluded(path: string, excludedRoutes: string[]): boolean;
35
+ /**
36
+ * Apply global prefix to an existing Elysia app by wrapping it
37
+ * This is useful when you want to add prefix to already configured app
38
+ * @param app - Existing Elysia instance
39
+ * @param prefix - Prefix to apply
40
+ * @returns New Elysia instance with prefix
41
+ */
42
+ export declare function wrapWithPrefix(app: Elysia, prefix: string | GlobalPrefixOptions): any;
43
+ /**
44
+ * Validate global prefix configuration
45
+ * @param prefix - Prefix configuration
46
+ * @returns true if valid, throws error if invalid
47
+ */
48
+ export declare function validateGlobalPrefix(prefix: string | GlobalPrefixOptions): boolean;
49
+ //# sourceMappingURL=global-prefix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-prefix.d.ts","sourceRoot":"","sources":["../core/global-prefix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC;;;;GAIG;AAEH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GAAG,mBAAmB,GACnC,GAAG,CAkCL;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA0B1D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAuBT;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GAAG,mBAAmB,GACnC,GAAG,CA0BL;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,GAAG,mBAAmB,GACnC,OAAO,CA2CT"}
@@ -0,0 +1,155 @@
1
+ import { Elysia } from "elysia";
2
+ /**
3
+ * Apply global prefix to all routes
4
+ * @param app - Elysia instance
5
+ * @param prefix - Prefix string (e.g., '/api', '/v1')
6
+ * @param options - Additional options like route exclusions
7
+ * @returns Modified Elysia instance
8
+ */
9
+ export function applyGlobalPrefix(app, prefix) {
10
+ // Normalize prefix
11
+ let prefixStr;
12
+ let excludedRoutes = [];
13
+ if (typeof prefix === "string") {
14
+ prefixStr = prefix;
15
+ }
16
+ else {
17
+ prefixStr = prefix.prefix;
18
+ excludedRoutes = prefix.exclude || [];
19
+ }
20
+ // Validate and normalize prefix
21
+ prefixStr = normalizePrefixPath(prefixStr);
22
+ if (!prefixStr) {
23
+ console.warn("⚠️ Global prefix is empty after normalization. Skipping prefix setup.");
24
+ return app;
25
+ }
26
+ // Create a new Elysia instance with the prefix
27
+ const prefixedApp = new Elysia({ prefix: prefixStr });
28
+ // Note: Elysia's prefix option automatically applies to all routes
29
+ // registered on this instance. We'll return the prefixed instance.
30
+ console.log(`✅ Global prefix applied: ${prefixStr}`);
31
+ if (excludedRoutes.length > 0) {
32
+ console.log(` Excluded routes: ${excludedRoutes.join(", ")}`);
33
+ }
34
+ return prefixedApp;
35
+ }
36
+ /**
37
+ * Normalize prefix path
38
+ * - Ensures it starts with /
39
+ * - Removes trailing /
40
+ * - Validates format
41
+ * @param prefix - Raw prefix string
42
+ * @returns Normalized prefix
43
+ */
44
+ export function normalizePrefixPath(prefix) {
45
+ if (!prefix) {
46
+ return "";
47
+ }
48
+ let normalized = prefix.trim();
49
+ // Ensure starts with /
50
+ if (!normalized.startsWith("/")) {
51
+ normalized = "/" + normalized;
52
+ }
53
+ // Remove trailing /
54
+ if (normalized.endsWith("/") && normalized.length > 1) {
55
+ normalized = normalized.slice(0, -1);
56
+ }
57
+ // Validate format (no spaces, no special chars except /, -, _)
58
+ const validPattern = /^\/[\w\-\/]*$/;
59
+ if (!validPattern.test(normalized)) {
60
+ throw new Error(`Invalid global prefix format: "${prefix}". Only alphanumeric, hyphens, underscores, and forward slashes are allowed.`);
61
+ }
62
+ return normalized;
63
+ }
64
+ /**
65
+ * Check if a route should be excluded from global prefix
66
+ * @param path - Route path
67
+ * @param excludedRoutes - List of routes to exclude
68
+ * @returns true if route should be excluded
69
+ */
70
+ export function isRouteExcluded(path, excludedRoutes) {
71
+ if (!excludedRoutes || excludedRoutes.length === 0) {
72
+ return false;
73
+ }
74
+ // Normalize the path
75
+ const normalizedPath = path.startsWith("/") ? path : "/" + path;
76
+ // Check for exact match or wildcard match
77
+ return excludedRoutes.some((excluded) => {
78
+ // Exact match
79
+ if (excluded === normalizedPath) {
80
+ return true;
81
+ }
82
+ // Wildcard match (e.g., '/health/*')
83
+ if (excluded.endsWith("/*")) {
84
+ const base = excluded.slice(0, -2);
85
+ return normalizedPath.startsWith(base);
86
+ }
87
+ return false;
88
+ });
89
+ }
90
+ /**
91
+ * Apply global prefix to an existing Elysia app by wrapping it
92
+ * This is useful when you want to add prefix to already configured app
93
+ * @param app - Existing Elysia instance
94
+ * @param prefix - Prefix to apply
95
+ * @returns New Elysia instance with prefix
96
+ */
97
+ export function wrapWithPrefix(app, prefix) {
98
+ let prefixStr;
99
+ let excludedRoutes = [];
100
+ if (typeof prefix === "string") {
101
+ prefixStr = prefix;
102
+ }
103
+ else {
104
+ prefixStr = prefix.prefix;
105
+ excludedRoutes = prefix.exclude || [];
106
+ }
107
+ prefixStr = normalizePrefixPath(prefixStr);
108
+ // Create wrapper app with prefix
109
+ const wrapper = new Elysia();
110
+ // Mount the original app under the prefix
111
+ wrapper.use(new Elysia({
112
+ prefix: prefixStr,
113
+ }).use(app));
114
+ console.log(`✅ Wrapped existing app with prefix: ${prefixStr}`);
115
+ return wrapper;
116
+ }
117
+ /**
118
+ * Validate global prefix configuration
119
+ * @param prefix - Prefix configuration
120
+ * @returns true if valid, throws error if invalid
121
+ */
122
+ export function validateGlobalPrefix(prefix) {
123
+ if (typeof prefix === "string") {
124
+ // Validate string prefix
125
+ if (prefix.length === 0) {
126
+ throw new Error("Global prefix cannot be an empty string");
127
+ }
128
+ normalizePrefixPath(prefix); // This will throw if invalid
129
+ return true;
130
+ }
131
+ if (typeof prefix === "object" && prefix !== null) {
132
+ // Validate object prefix
133
+ if (!prefix.prefix) {
134
+ throw new Error("GlobalPrefixOptions must have a 'prefix' property");
135
+ }
136
+ if (typeof prefix.prefix !== "string") {
137
+ throw new Error("Global prefix must be a string");
138
+ }
139
+ normalizePrefixPath(prefix.prefix); // This will throw if invalid
140
+ // Validate exclude array
141
+ if (prefix.exclude !== undefined) {
142
+ if (!Array.isArray(prefix.exclude)) {
143
+ throw new Error("GlobalPrefixOptions.exclude must be an array");
144
+ }
145
+ // Validate each excluded route
146
+ prefix.exclude.forEach((route) => {
147
+ if (typeof route !== "string") {
148
+ throw new Error("All routes in GlobalPrefixOptions.exclude must be strings");
149
+ }
150
+ });
151
+ }
152
+ return true;
153
+ }
154
+ throw new Error("Global prefix must be string or GlobalPrefixOptions object");
155
+ }
package/dist/index.d.ts CHANGED
@@ -23,6 +23,12 @@ export * from "./decorators/database.decorators";
23
23
  export * from "./dto";
24
24
  export { schemaRegistry } from "./schema-registry";
25
25
  export * from "./factory";
26
+ export type { CorsOptions } from "./cors";
27
+ export { setupCors, validateCorsOptions } from "./cors";
28
+ export type { GlobalPrefixOptions } from "./global-prefix";
29
+ export { applyGlobalPrefix, normalizePrefixPath, validateGlobalPrefix, wrapWithPrefix, } from "./global-prefix";
30
+ export { compression } from "./plugins/compression";
31
+ export type { CompressionOptions } from "./plugins/compression";
26
32
  export * from "./testing";
27
33
  /**
28
34
  * Framework version
@@ -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,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
@@ -44,6 +44,10 @@ export * from "./dto";
44
44
  export { schemaRegistry } from "./schema-registry";
45
45
  // Application Factory
46
46
  export * from "./factory";
47
+ export { setupCors, validateCorsOptions } from "./cors";
48
+ export { applyGlobalPrefix, normalizePrefixPath, validateGlobalPrefix, wrapWithPrefix, } from "./global-prefix";
49
+ // Plugins
50
+ export { compression } from "./plugins/compression";
47
51
  // Testing Module
48
52
  export * from "./testing";
49
53
  /**
@@ -0,0 +1,15 @@
1
+ export interface InterceptorContext {
2
+ getRequest<T = any>(): T;
3
+ getResponse<T = any>(): T;
4
+ getContext<T = any>(): T;
5
+ getHandler(): Function;
6
+ getClass(): any;
7
+ request?: any;
8
+ body?: any;
9
+ params?: any;
10
+ query?: any;
11
+ headers?: any;
12
+ path?: string;
13
+ method?: string;
14
+ }
15
+ //# sourceMappingURL=interceptor.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interceptor.interface.d.ts","sourceRoot":"","sources":["../../core/interfaces/interceptor.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IACzB,WAAW,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IAC1B,UAAU,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IACzB,UAAU,IAAI,QAAQ,CAAC;IACvB,QAAQ,IAAI,GAAG,CAAC;IAEhB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,OAAO,CAAC,EAAE,GAAG,CAAC;IAEd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Optimized Handler Builder for WynkJS
3
+ * Builds route handlers conditionally - only adds overhead when features are actually used
4
+ */
5
+ import { ParamMetadata } from "./decorators/param.decorators";
6
+ export interface HandlerBuildOptions {
7
+ instance: any;
8
+ methodName: string;
9
+ ControllerClass: any;
10
+ params: ParamMetadata[];
11
+ allGuards: any[];
12
+ allInterceptors: any[];
13
+ allPipes: any[];
14
+ allFilters: any[];
15
+ httpCode?: number;
16
+ headers?: Record<string, string>;
17
+ redirect?: {
18
+ url: string;
19
+ statusCode: number;
20
+ };
21
+ }
22
+ /**
23
+ * Build optimized handler - only include overhead when features are used
24
+ * This eliminates conditional checks on every request for unused features
25
+ */
26
+ export declare function buildOptimizedHandler(options: HandlerBuildOptions): (ctx: any) => Promise<any>;
27
+ /**
28
+ * Build middleware chain - only if middleware exists
29
+ */
30
+ export declare function buildMiddlewareChain(handler: (ctx: any) => Promise<any>, middlewares: any[]): (ctx: any) => Promise<any>;
31
+ //# sourceMappingURL=optimized-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimized-handler.d.ts","sourceRoot":"","sources":["../core/optimized-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,GAAG,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,GAAG,CAAC;IACrB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,SAAS,EAAE,GAAG,EAAE,CAAC;IACjB,eAAe,EAAE,GAAG,EAAE,CAAC;IACvB,QAAQ,EAAE,GAAG,EAAE,CAAC;IAChB,UAAU,EAAE,GAAG,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,mBAAmB,GAC3B,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAyM5B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,EACnC,WAAW,EAAE,GAAG,EAAE,GACjB,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAW5B"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Optimized Handler Builder for WynkJS
3
+ * Builds route handlers conditionally - only adds overhead when features are actually used
4
+ */
5
+ import { createExecutionContext, executeGuards, } from "./decorators/guard.decorators";
6
+ import { executeInterceptors } from "./decorators/interceptor.decorators";
7
+ import { executePipes } from "./decorators/pipe.decorators";
8
+ import { executeExceptionFilters, HttpException, } from "./decorators/exception.decorators";
9
+ /**
10
+ * Build optimized handler - only include overhead when features are used
11
+ * This eliminates conditional checks on every request for unused features
12
+ */
13
+ export function buildOptimizedHandler(options) {
14
+ const { instance, methodName, ControllerClass, params, allGuards, allInterceptors, allPipes, allFilters, httpCode, headers, redirect, } = options;
15
+ // Pre-sort params once during registration (not on every request)
16
+ if (params.length > 0) {
17
+ params.sort((a, b) => a.index - b.index);
18
+ }
19
+ // Base parameter extractor and method executor
20
+ const extractParamsAndExecute = async (ctx) => {
21
+ if (params.length === 0) {
22
+ // No parameter decorators - pass full context
23
+ return await instance[methodName](ctx);
24
+ }
25
+ // Build arguments array
26
+ const args = new Array(params.length);
27
+ for (const param of params) {
28
+ let value;
29
+ // Extract value based on type (optimized switch)
30
+ switch (param.type) {
31
+ case "body":
32
+ value = param.data ? ctx.body?.[param.data] : ctx.body;
33
+ break;
34
+ case "param":
35
+ value = param.data ? ctx.params?.[param.data] : ctx.params;
36
+ break;
37
+ case "query":
38
+ value = param.data ? ctx.query?.[param.data] : ctx.query;
39
+ break;
40
+ case "headers":
41
+ value = param.data
42
+ ? ctx.headers?.get?.(param.data) ||
43
+ ctx.request?.headers?.get?.(param.data)
44
+ : ctx.headers || ctx.request?.headers;
45
+ break;
46
+ case "request":
47
+ value = ctx.request || ctx;
48
+ break;
49
+ case "response":
50
+ value = ctx.set || ctx.response;
51
+ break;
52
+ case "context":
53
+ if (param.data) {
54
+ const keys = param.data.split(".");
55
+ value = keys.reduce((obj, key) => obj?.[key], ctx);
56
+ }
57
+ else {
58
+ value = ctx;
59
+ }
60
+ break;
61
+ case "user":
62
+ value = param.data ? ctx.user?.[param.data] : ctx.user;
63
+ break;
64
+ case "file":
65
+ value = ctx.body?.file || ctx.file;
66
+ break;
67
+ case "files":
68
+ value = ctx.body?.files || ctx.files;
69
+ break;
70
+ }
71
+ // Apply parameter-specific pipes
72
+ if (param.pipes && param.pipes.length > 0) {
73
+ const metadata = {
74
+ type: param.type,
75
+ data: param.data,
76
+ };
77
+ value = await executePipes(param.pipes, value, metadata);
78
+ }
79
+ // Apply global/controller/method pipes
80
+ if (allPipes.length > 0) {
81
+ const metadata = {
82
+ type: param.type,
83
+ data: param.data,
84
+ };
85
+ value = await executePipes(allPipes, value, metadata);
86
+ }
87
+ args[param.index] = value;
88
+ }
89
+ return await instance[methodName].apply(instance, args);
90
+ };
91
+ // Build handler layers conditionally
92
+ let handler = extractParamsAndExecute;
93
+ // Wrap with interceptors (only if they exist)
94
+ if (allInterceptors.length > 0) {
95
+ const prevHandler = handler;
96
+ handler = async (ctx) => {
97
+ const executionContext = createExecutionContext(ctx, instance[methodName], ControllerClass);
98
+ return await executeInterceptors(allInterceptors, executionContext, () => prevHandler(ctx));
99
+ };
100
+ }
101
+ // Wrap with guards (only if they exist)
102
+ if (allGuards.length > 0) {
103
+ const prevHandler = handler;
104
+ handler = async (ctx) => {
105
+ const executionContext = createExecutionContext(ctx, instance[methodName], ControllerClass);
106
+ const canActivate = await executeGuards(allGuards, executionContext);
107
+ if (!canActivate) {
108
+ throw new HttpException("Forbidden", 403, "Access denied");
109
+ }
110
+ return await prevHandler(ctx);
111
+ };
112
+ }
113
+ // Final handler with response modifications
114
+ const finalHandler = async (ctx) => {
115
+ try {
116
+ const result = await handler(ctx);
117
+ // Handle redirect (if configured)
118
+ if (redirect) {
119
+ ctx.set.redirect = redirect.url;
120
+ ctx.set.status = redirect.statusCode;
121
+ return;
122
+ }
123
+ // Set custom HTTP code (if configured)
124
+ if (httpCode) {
125
+ ctx.set.status = httpCode;
126
+ }
127
+ // Set custom headers (if configured)
128
+ if (headers) {
129
+ Object.entries(headers).forEach(([key, value]) => {
130
+ ctx.set.headers[key] = value;
131
+ });
132
+ }
133
+ return result;
134
+ }
135
+ catch (error) {
136
+ // Execute exception filters (only if they exist)
137
+ if (allFilters.length > 0) {
138
+ const executionContext = createExecutionContext(ctx, instance[methodName], ControllerClass);
139
+ try {
140
+ const result = await executeExceptionFilters(allFilters, error, executionContext);
141
+ if (result) {
142
+ if (result.statusCode) {
143
+ ctx.set.status = result.statusCode;
144
+ }
145
+ return result;
146
+ }
147
+ }
148
+ catch (filterError) {
149
+ error = filterError;
150
+ }
151
+ }
152
+ // Default error handling
153
+ if (error instanceof HttpException) {
154
+ ctx.set.status = error.getStatus();
155
+ return error.getResponse();
156
+ }
157
+ ctx.set.status = 500;
158
+ return {
159
+ statusCode: 500,
160
+ message: error.message || "Internal server error",
161
+ error: "Internal Server Error",
162
+ };
163
+ }
164
+ };
165
+ return finalHandler;
166
+ }
167
+ /**
168
+ * Build middleware chain - only if middleware exists
169
+ */
170
+ export function buildMiddlewareChain(handler, middlewares) {
171
+ if (middlewares.length === 0) {
172
+ return handler;
173
+ }
174
+ // Build middleware chain (removed console.log for performance)
175
+ return middlewares.reduceRight((next, middleware) => {
176
+ return async (ctx) => {
177
+ return await middleware(ctx, () => next(ctx));
178
+ };
179
+ }, handler);
180
+ }
@@ -15,9 +15,9 @@ export interface ArgumentMetadata {
15
15
  data?: string;
16
16
  }
17
17
  /**
18
- * Validation Error structure (Elysia format)
18
+ * Validation Error structure (WynkJS format)
19
19
  */
20
- export interface ElysiaValidationError {
20
+ export interface WynkJSValidationError {
21
21
  type: "validation";
22
22
  on: "body" | "params" | "query" | "headers";
23
23
  property: string;
@@ -36,36 +36,36 @@ export interface ElysiaValidationError {
36
36
  }
37
37
  /**
38
38
  * Base Validation Pipe
39
- * Handles Elysia validation errors and formats them
39
+ * Handles WynkJS validation errors and formats them
40
40
  */
41
41
  export declare class ValidationPipe implements ValidationPipeTransform {
42
42
  protected options: {
43
- exceptionFactory?: (errors: ElysiaValidationError) => any;
43
+ exceptionFactory?: (errors: WynkJSValidationError) => any;
44
44
  transform?: boolean;
45
45
  whitelist?: boolean;
46
46
  };
47
47
  constructor(options?: {
48
- exceptionFactory?: (errors: ElysiaValidationError) => any;
48
+ exceptionFactory?: (errors: WynkJSValidationError) => any;
49
49
  transform?: boolean;
50
50
  whitelist?: boolean;
51
51
  });
52
52
  /**
53
- * Transform method (not used for Elysia validation, but required by interface)
53
+ * Transform method (not used for WynkJS validation, but required by interface)
54
54
  */
55
55
  transform(value: any, metadata: ArgumentMetadata): any;
56
56
  /**
57
- * Format Elysia validation error
57
+ * Format WynkJS validation error
58
58
  * This is called by the exception filter
59
59
  */
60
60
  formatError(exception: any): any;
61
61
  /**
62
- * Parse Elysia validation error from exception
62
+ * Parse WynkJS validation error from exception
63
63
  */
64
- protected parseValidationError(exception: any): ElysiaValidationError;
64
+ protected parseValidationError(exception: any): WynkJSValidationError;
65
65
  /**
66
66
  * Default error formatting with custom errorMessage support
67
67
  */
68
- protected defaultFormatError(error: ElysiaValidationError, schemaKey?: string): any;
68
+ protected defaultFormatError(error: WynkJSValidationError, schemaKey?: string): any;
69
69
  }
70
70
  /**
71
71
  * Custom Format Error Pipe
@@ -2,7 +2,7 @@ import "reflect-metadata";
2
2
  import { schemaRegistry } from "../schema-registry";
3
3
  /**
4
4
  * Base Validation Pipe
5
- * Handles Elysia validation errors and formats them
5
+ * Handles WynkJS validation errors and formats them
6
6
  */
7
7
  export class ValidationPipe {
8
8
  options;
@@ -10,13 +10,13 @@ export class ValidationPipe {
10
10
  this.options = options || {};
11
11
  }
12
12
  /**
13
- * Transform method (not used for Elysia validation, but required by interface)
13
+ * Transform method (not used for WynkJS validation, but required by interface)
14
14
  */
15
15
  transform(value, metadata) {
16
16
  return value;
17
17
  }
18
18
  /**
19
- * Format Elysia validation error
19
+ * Format WynkJS validation error
20
20
  * This is called by the exception filter
21
21
  */
22
22
  formatError(exception) {
@@ -30,7 +30,7 @@ export class ValidationPipe {
30
30
  return this.defaultFormatError(validationError);
31
31
  }
32
32
  /**
33
- * Parse Elysia validation error from exception
33
+ * Parse WynkJS validation error from exception
34
34
  */
35
35
  parseValidationError(exception) {
36
36
  let validationData;
@@ -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"}