wynkjs 1.0.2 → 1.0.4

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 (41) hide show
  1. package/README.md +401 -112
  2. package/dist/database.d.ts +1 -1
  3. package/dist/database.js +1 -1
  4. package/dist/decorators/exception.advanced.d.ts +286 -18
  5. package/dist/decorators/exception.advanced.d.ts.map +1 -1
  6. package/dist/decorators/exception.advanced.js +410 -17
  7. package/dist/decorators/exception.decorators.d.ts +92 -2
  8. package/dist/decorators/exception.decorators.d.ts.map +1 -1
  9. package/dist/decorators/exception.decorators.js +120 -5
  10. package/dist/decorators/formatter.decorators.d.ts +93 -0
  11. package/dist/decorators/formatter.decorators.d.ts.map +1 -0
  12. package/dist/decorators/formatter.decorators.js +131 -0
  13. package/dist/decorators/guard.decorators.d.ts +2 -2
  14. package/dist/decorators/http.decorators.d.ts +3 -2
  15. package/dist/decorators/http.decorators.d.ts.map +1 -1
  16. package/dist/decorators/pipe.decorators.d.ts +2 -2
  17. package/dist/decorators/pipe.decorators.d.ts.map +1 -1
  18. package/dist/decorators/pipe.decorators.js +2 -2
  19. package/dist/dto.js +1 -1
  20. package/dist/factory.d.ts +1 -1
  21. package/dist/factory.d.ts.map +1 -1
  22. package/dist/factory.js +55 -6
  23. package/dist/filters/exception.filters.d.ts +124 -0
  24. package/dist/filters/exception.filters.d.ts.map +1 -0
  25. package/dist/filters/exception.filters.js +208 -0
  26. package/dist/index.d.ts +4 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +6 -1
  29. package/dist/pipes/validation.pipe.d.ts +3 -3
  30. package/dist/pipes/validation.pipe.d.ts.map +1 -1
  31. package/dist/pipes/validation.pipe.js +39 -11
  32. package/dist/schema-registry.d.ts +51 -0
  33. package/dist/schema-registry.d.ts.map +1 -0
  34. package/dist/schema-registry.js +134 -0
  35. package/dist/testing/index.d.ts +74 -0
  36. package/dist/testing/index.d.ts.map +1 -0
  37. package/dist/testing/index.js +106 -0
  38. package/dist/testing/test-utils.d.ts +31 -0
  39. package/dist/testing/test-utils.d.ts.map +1 -0
  40. package/dist/testing/test-utils.js +72 -0
  41. package/package.json +8 -3
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Schema Registry for storing and retrieving custom error messages
3
+ * This allows validation pipes to look up custom error messages from schemas
4
+ */
5
+ class SchemaRegistry {
6
+ static instance;
7
+ errorMessages = {};
8
+ routeSchemas = {};
9
+ constructor() { }
10
+ static getInstance() {
11
+ if (!SchemaRegistry.instance) {
12
+ SchemaRegistry.instance = new SchemaRegistry();
13
+ }
14
+ return SchemaRegistry.instance;
15
+ }
16
+ /**
17
+ * Register custom error messages for a schema
18
+ * @param schemaKey Unique key for the schema (e.g., class name + method)
19
+ * @param schema The TypeBox schema object
20
+ */
21
+ registerSchema(schemaKey, schema) {
22
+ if (!schema || typeof schema !== "object")
23
+ return;
24
+ const messages = {};
25
+ this.extractErrorMessages(schema, "", messages);
26
+ if (Object.keys(messages).length > 0) {
27
+ this.errorMessages[schemaKey] = messages;
28
+ }
29
+ }
30
+ /**
31
+ * Register route-to-schema mapping
32
+ * @param method HTTP method (GET, POST, etc.)
33
+ * @param path Route path
34
+ * @param schemaKey The schema key
35
+ * @param validationType Type of validation (body, query, params)
36
+ */
37
+ registerRoute(method, path, schemaKey, validationType) {
38
+ const routeKey = `${method.toUpperCase()}:${path}`;
39
+ if (!this.routeSchemas[routeKey]) {
40
+ this.routeSchemas[routeKey] = [];
41
+ }
42
+ this.routeSchemas[routeKey].push({ schemaKey, validationType });
43
+ }
44
+ /**
45
+ * Get schema key for a route and validation type
46
+ * @param method HTTP method
47
+ * @param path Route path (actual request path with values)
48
+ * @param validationType Type of validation
49
+ * @returns Schema key or undefined
50
+ */
51
+ getSchemaKeyForRoute(method, path, validationType) {
52
+ // First try exact match
53
+ const exactKey = `${method.toUpperCase()}:${path}`;
54
+ if (this.routeSchemas[exactKey]) {
55
+ const found = this.routeSchemas[exactKey].find((s) => s.validationType === validationType);
56
+ if (found)
57
+ return found.schemaKey;
58
+ }
59
+ // If no exact match, try to match patterns
60
+ // e.g., request path "/users/10/100" should match pattern "/users/:id1/:id2"
61
+ for (const [routeKey, schemas] of Object.entries(this.routeSchemas)) {
62
+ // Split only on the first colon to separate method from path
63
+ const colonIndex = routeKey.indexOf(":");
64
+ const routeMethod = routeKey.substring(0, colonIndex);
65
+ const routePath = routeKey.substring(colonIndex + 1);
66
+ if (routeMethod !== method.toUpperCase())
67
+ continue;
68
+ // Check if the routePath is a pattern (contains :param)
69
+ if (routePath.includes(":")) {
70
+ // Convert pattern to regex
71
+ const pattern = routePath
72
+ .replace(/:[^/]+/g, "([^/]+)") // Replace :param with regex group
73
+ .replace(/\//g, "\\/"); // Escape slashes
74
+ const regex = new RegExp(`^${pattern}$`);
75
+ if (regex.test(path)) {
76
+ const found = schemas.find((s) => s.validationType === validationType);
77
+ if (found)
78
+ return found.schemaKey;
79
+ }
80
+ }
81
+ }
82
+ return undefined;
83
+ }
84
+ /**
85
+ * Recursively extract error messages from schema
86
+ */
87
+ extractErrorMessages(schema, path, messages) {
88
+ // Check for custom error message at current level
89
+ if (schema.error || schema.errorMessage) {
90
+ messages[path || "root"] = schema.error || schema.errorMessage;
91
+ }
92
+ // Recurse into object properties
93
+ if (schema.type === "object" && schema.properties) {
94
+ for (const [key, value] of Object.entries(schema.properties)) {
95
+ const newPath = path ? `${path}.${key}` : key;
96
+ this.extractErrorMessages(value, newPath, messages);
97
+ }
98
+ }
99
+ // Recurse into array items
100
+ if (schema.type === "array" && schema.items) {
101
+ const newPath = path ? `${path}[]` : "[]";
102
+ this.extractErrorMessages(schema.items, newPath, messages);
103
+ }
104
+ }
105
+ /**
106
+ * Get custom error message for a field path
107
+ * @param schemaKey The schema key
108
+ * @param fieldPath The field path (e.g., "user.email")
109
+ * @returns Custom error message or undefined
110
+ */
111
+ getErrorMessage(schemaKey, fieldPath) {
112
+ const schemaMessages = this.errorMessages[schemaKey];
113
+ if (!schemaMessages)
114
+ return undefined;
115
+ // Try exact match first
116
+ if (schemaMessages[fieldPath]) {
117
+ return schemaMessages[fieldPath];
118
+ }
119
+ // Try without array indices (e.g., "items.0.name" -> "items[].name")
120
+ const normalizedPath = fieldPath.replace(/\.\d+\./g, "[].");
121
+ if (schemaMessages[normalizedPath]) {
122
+ return schemaMessages[normalizedPath];
123
+ }
124
+ return undefined;
125
+ }
126
+ /**
127
+ * Clear all registered schemas (useful for testing)
128
+ */
129
+ clear() {
130
+ this.errorMessages = {};
131
+ this.routeSchemas = {};
132
+ }
133
+ }
134
+ export const schemaRegistry = SchemaRegistry.getInstance();
@@ -0,0 +1,74 @@
1
+ /**
2
+ * WynkJS Testing Module
3
+ * Built-in testing utilities for WynkJS applications
4
+ * Works with Bun's native test runner
5
+ */
6
+ /**
7
+ * Test class for creating isolated testing modules
8
+ */
9
+ export declare class Test {
10
+ /**
11
+ * Create a testing module with providers
12
+ * @param options Testing module options
13
+ * @returns TestingModule instance
14
+ */
15
+ static createTestingModule(options: TestingModuleOptions): TestingModule;
16
+ }
17
+ /**
18
+ * Options for creating a testing module
19
+ */
20
+ export interface TestingModuleOptions {
21
+ /**
22
+ * Array of providers (services, classes) to register in the testing container
23
+ */
24
+ providers?: any[];
25
+ /**
26
+ * Array of controllers to register in the testing container
27
+ */
28
+ controllers?: any[];
29
+ }
30
+ /**
31
+ * Testing module that provides isolated dependency injection container
32
+ */
33
+ export declare class TestingModule {
34
+ private testContainer;
35
+ private providers;
36
+ private controllers;
37
+ constructor(options: TestingModuleOptions);
38
+ /**
39
+ * Compile the testing module (register all providers and controllers)
40
+ */
41
+ compile(): Promise<TestingModule>;
42
+ /**
43
+ * Get an instance of a provider from the testing container
44
+ * @param type The class/token to resolve
45
+ * @returns Instance of the requested type
46
+ */
47
+ get<T>(type: any): T;
48
+ /**
49
+ * Close the testing module and clean up
50
+ */
51
+ close(): Promise<void>;
52
+ }
53
+ /**
54
+ * Mock factory for creating mock instances
55
+ */
56
+ export declare class MockFactory {
57
+ /**
58
+ * Create a mock object with methods
59
+ * @param methods Object with method names and return values
60
+ * @returns Mock object
61
+ */
62
+ static createMock<T = any>(methods?: Record<string, any>): T;
63
+ /**
64
+ * Create a spy function that tracks calls
65
+ * @param implementation Optional implementation
66
+ * @returns Spy function
67
+ */
68
+ static createSpy(implementation?: (...args: any[]) => any): any;
69
+ }
70
+ /**
71
+ * Export everything for convenient imports
72
+ */
73
+ export * from "./test-utils";
74
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../core/testing/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;GAEG;AACH,qBAAa,IAAI;IACf;;;;OAIG;IACH,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa;CAGzE;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;IAElB;;OAEG;IACH,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,WAAW,CAAQ;gBAEf,OAAO,EAAE,oBAAoB;IAOzC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC;IAcvC;;;;OAIG;IACH,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC;IAIpB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB;;;;OAIG;IACH,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAAG,CAAC;IAchE;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,GAAG;CAiBhE;AAED;;GAEG;AACH,cAAc,cAAc,CAAC"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * WynkJS Testing Module
3
+ * Built-in testing utilities for WynkJS applications
4
+ * Works with Bun's native test runner
5
+ */
6
+ import { container } from "tsyringe";
7
+ /**
8
+ * Test class for creating isolated testing modules
9
+ */
10
+ export class Test {
11
+ /**
12
+ * Create a testing module with providers
13
+ * @param options Testing module options
14
+ * @returns TestingModule instance
15
+ */
16
+ static createTestingModule(options) {
17
+ return new TestingModule(options);
18
+ }
19
+ }
20
+ /**
21
+ * Testing module that provides isolated dependency injection container
22
+ */
23
+ export class TestingModule {
24
+ testContainer;
25
+ providers;
26
+ controllers;
27
+ constructor(options) {
28
+ // Create a child container for isolation
29
+ this.testContainer = container.createChildContainer();
30
+ this.providers = options.providers || [];
31
+ this.controllers = options.controllers || [];
32
+ }
33
+ /**
34
+ * Compile the testing module (register all providers and controllers)
35
+ */
36
+ async compile() {
37
+ // Register all providers
38
+ for (const provider of this.providers) {
39
+ this.testContainer.register(provider, { useClass: provider });
40
+ }
41
+ // Register all controllers
42
+ for (const controller of this.controllers) {
43
+ this.testContainer.register(controller, { useClass: controller });
44
+ }
45
+ return this;
46
+ }
47
+ /**
48
+ * Get an instance of a provider from the testing container
49
+ * @param type The class/token to resolve
50
+ * @returns Instance of the requested type
51
+ */
52
+ get(type) {
53
+ return this.testContainer.resolve(type);
54
+ }
55
+ /**
56
+ * Close the testing module and clean up
57
+ */
58
+ async close() {
59
+ // Reset the test container
60
+ this.testContainer.reset();
61
+ }
62
+ }
63
+ /**
64
+ * Mock factory for creating mock instances
65
+ */
66
+ export class MockFactory {
67
+ /**
68
+ * Create a mock object with methods
69
+ * @param methods Object with method names and return values
70
+ * @returns Mock object
71
+ */
72
+ static createMock(methods = {}) {
73
+ const mock = {};
74
+ for (const [key, value] of Object.entries(methods)) {
75
+ if (typeof value === "function") {
76
+ mock[key] = value;
77
+ }
78
+ else {
79
+ mock[key] = () => value;
80
+ }
81
+ }
82
+ return mock;
83
+ }
84
+ /**
85
+ * Create a spy function that tracks calls
86
+ * @param implementation Optional implementation
87
+ * @returns Spy function
88
+ */
89
+ static createSpy(implementation) {
90
+ const calls = [];
91
+ const spy = (...args) => {
92
+ calls.push(args);
93
+ return implementation ? implementation(...args) : undefined;
94
+ };
95
+ spy.calls = calls;
96
+ spy.mock = {
97
+ calls,
98
+ results: calls.map((args) => implementation ? implementation(...args) : undefined),
99
+ };
100
+ return spy;
101
+ }
102
+ }
103
+ /**
104
+ * Export everything for convenient imports
105
+ */
106
+ export * from "./test-utils";
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Testing utilities and helpers
3
+ */
4
+ /**
5
+ * Create a mock request object for testing controllers
6
+ */
7
+ export declare function createMockRequest(options?: {
8
+ method?: string;
9
+ url?: string;
10
+ body?: any;
11
+ params?: Record<string, string>;
12
+ query?: Record<string, any>;
13
+ headers?: Record<string, string>;
14
+ }): any;
15
+ /**
16
+ * Create a mock response object for testing controllers
17
+ */
18
+ export declare function createMockResponse(): any;
19
+ /**
20
+ * Create a mock execution context for testing guards, interceptors, etc.
21
+ */
22
+ export declare function createMockExecutionContext(request?: any, response?: any): any;
23
+ /**
24
+ * Assert that a value is defined (not null or undefined)
25
+ */
26
+ export declare function assertDefined<T>(value: T | null | undefined): asserts value is T;
27
+ /**
28
+ * Assert that a value is an instance of a class
29
+ */
30
+ export declare function assertInstanceOf<T>(value: any, type: new (...args: any[]) => T): asserts value is T;
31
+ //# sourceMappingURL=test-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../core/testing/test-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B,GACL,GAAG,CASL;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,GAAG,CAwBxC;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,GAAE,GAAyB,EAClC,QAAQ,GAAE,GAA0B,GACnC,GAAG,CASL;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GAC1B,OAAO,CAAC,KAAK,IAAI,CAAC,CAIpB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,KAAK,EAAE,GAAG,EACV,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAC9B,OAAO,CAAC,KAAK,IAAI,CAAC,CAIpB"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Testing utilities and helpers
3
+ */
4
+ /**
5
+ * Create a mock request object for testing controllers
6
+ */
7
+ export function createMockRequest(options = {}) {
8
+ return {
9
+ method: options.method || "GET",
10
+ url: options.url || "/",
11
+ body: options.body || {},
12
+ params: options.params || {},
13
+ query: options.query || {},
14
+ headers: options.headers || {},
15
+ };
16
+ }
17
+ /**
18
+ * Create a mock response object for testing controllers
19
+ */
20
+ export function createMockResponse() {
21
+ const response = {
22
+ statusCode: 200,
23
+ headers: {},
24
+ body: null,
25
+ status: function (code) {
26
+ this.statusCode = code;
27
+ return this;
28
+ },
29
+ send: function (data) {
30
+ this.body = data;
31
+ return this;
32
+ },
33
+ json: function (data) {
34
+ this.body = data;
35
+ return this;
36
+ },
37
+ setHeader: function (name, value) {
38
+ this.headers[name] = value;
39
+ return this;
40
+ },
41
+ };
42
+ return response;
43
+ }
44
+ /**
45
+ * Create a mock execution context for testing guards, interceptors, etc.
46
+ */
47
+ export function createMockExecutionContext(request = createMockRequest(), response = createMockResponse()) {
48
+ return {
49
+ getRequest: () => request,
50
+ getResponse: () => response,
51
+ switchToHttp: () => ({
52
+ getRequest: () => request,
53
+ getResponse: () => response,
54
+ }),
55
+ };
56
+ }
57
+ /**
58
+ * Assert that a value is defined (not null or undefined)
59
+ */
60
+ export function assertDefined(value) {
61
+ if (value === null || value === undefined) {
62
+ throw new Error("Expected value to be defined");
63
+ }
64
+ }
65
+ /**
66
+ * Assert that a value is an instance of a class
67
+ */
68
+ export function assertInstanceOf(value, type) {
69
+ if (!(value instanceof type)) {
70
+ throw new Error(`Expected value to be instance of ${type.name}`);
71
+ }
72
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wynkjs",
3
- "version": "1.0.2",
4
- "description": "A high-performance TypeScript framework built on Elysia for Bun with NestJS-style decorators - 20x faster than Express",
3
+ "version": "1.0.4",
4
+ "description": "A high-performance TypeScript framework built on Elysia for Bun with elegant decorator-based architecture - 10x faster than Express/NestJS",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -10,6 +10,10 @@
10
10
  "wynk",
11
11
  "wynkjs",
12
12
  "elysia",
13
+ "nestjs",
14
+ "nestjs alternative",
15
+ "express",
16
+ "expressjs alternative",
13
17
  "bun",
14
18
  "framework",
15
19
  "typescript",
@@ -18,7 +22,8 @@
18
22
  "web-framework",
19
23
  "http",
20
24
  "api",
21
- "nestjs-alternative",
25
+ "bun-framework",
26
+ "typescript-decorators",
22
27
  "dependency-injection",
23
28
  "rest-api",
24
29
  "backend",