@hazeljs/core 0.2.0-beta.1

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 (194) hide show
  1. package/README.md +522 -0
  2. package/dist/__tests__/container.test.d.ts +2 -0
  3. package/dist/__tests__/container.test.d.ts.map +1 -0
  4. package/dist/__tests__/container.test.js +454 -0
  5. package/dist/__tests__/decorators.test.d.ts +2 -0
  6. package/dist/__tests__/decorators.test.d.ts.map +1 -0
  7. package/dist/__tests__/decorators.test.js +693 -0
  8. package/dist/__tests__/errors/http.error.test.d.ts +2 -0
  9. package/dist/__tests__/errors/http.error.test.d.ts.map +1 -0
  10. package/dist/__tests__/errors/http.error.test.js +117 -0
  11. package/dist/__tests__/filters/exception-filter.test.d.ts +2 -0
  12. package/dist/__tests__/filters/exception-filter.test.d.ts.map +1 -0
  13. package/dist/__tests__/filters/exception-filter.test.js +135 -0
  14. package/dist/__tests__/filters/http-exception.filter.test.d.ts +2 -0
  15. package/dist/__tests__/filters/http-exception.filter.test.d.ts.map +1 -0
  16. package/dist/__tests__/filters/http-exception.filter.test.js +119 -0
  17. package/dist/__tests__/hazel-app.test.d.ts +2 -0
  18. package/dist/__tests__/hazel-app.test.d.ts.map +1 -0
  19. package/dist/__tests__/hazel-app.test.js +682 -0
  20. package/dist/__tests__/hazel-module.test.d.ts +2 -0
  21. package/dist/__tests__/hazel-module.test.d.ts.map +1 -0
  22. package/dist/__tests__/hazel-module.test.js +408 -0
  23. package/dist/__tests__/hazel-response.test.d.ts +2 -0
  24. package/dist/__tests__/hazel-response.test.d.ts.map +1 -0
  25. package/dist/__tests__/hazel-response.test.js +138 -0
  26. package/dist/__tests__/health.test.d.ts +2 -0
  27. package/dist/__tests__/health.test.d.ts.map +1 -0
  28. package/dist/__tests__/health.test.js +147 -0
  29. package/dist/__tests__/index.test.d.ts +2 -0
  30. package/dist/__tests__/index.test.d.ts.map +1 -0
  31. package/dist/__tests__/index.test.js +239 -0
  32. package/dist/__tests__/interceptors/interceptor.test.d.ts +2 -0
  33. package/dist/__tests__/interceptors/interceptor.test.d.ts.map +1 -0
  34. package/dist/__tests__/interceptors/interceptor.test.js +166 -0
  35. package/dist/__tests__/logger.test.d.ts +2 -0
  36. package/dist/__tests__/logger.test.d.ts.map +1 -0
  37. package/dist/__tests__/logger.test.js +141 -0
  38. package/dist/__tests__/middleware/cors.test.d.ts +2 -0
  39. package/dist/__tests__/middleware/cors.test.d.ts.map +1 -0
  40. package/dist/__tests__/middleware/cors.test.js +129 -0
  41. package/dist/__tests__/middleware/csrf.test.d.ts +2 -0
  42. package/dist/__tests__/middleware/csrf.test.d.ts.map +1 -0
  43. package/dist/__tests__/middleware/csrf.test.js +247 -0
  44. package/dist/__tests__/middleware/global-middleware.test.d.ts +2 -0
  45. package/dist/__tests__/middleware/global-middleware.test.d.ts.map +1 -0
  46. package/dist/__tests__/middleware/global-middleware.test.js +259 -0
  47. package/dist/__tests__/middleware/rate-limit.test.d.ts +2 -0
  48. package/dist/__tests__/middleware/rate-limit.test.d.ts.map +1 -0
  49. package/dist/__tests__/middleware/rate-limit.test.js +264 -0
  50. package/dist/__tests__/middleware/security-headers.test.d.ts +2 -0
  51. package/dist/__tests__/middleware/security-headers.test.d.ts.map +1 -0
  52. package/dist/__tests__/middleware/security-headers.test.js +229 -0
  53. package/dist/__tests__/middleware/timeout.test.d.ts +2 -0
  54. package/dist/__tests__/middleware/timeout.test.d.ts.map +1 -0
  55. package/dist/__tests__/middleware/timeout.test.js +132 -0
  56. package/dist/__tests__/middleware.test.d.ts +2 -0
  57. package/dist/__tests__/middleware.test.d.ts.map +1 -0
  58. package/dist/__tests__/middleware.test.js +180 -0
  59. package/dist/__tests__/pipes/pipe.test.d.ts +2 -0
  60. package/dist/__tests__/pipes/pipe.test.d.ts.map +1 -0
  61. package/dist/__tests__/pipes/pipe.test.js +245 -0
  62. package/dist/__tests__/pipes/validation.pipe.test.d.ts +2 -0
  63. package/dist/__tests__/pipes/validation.pipe.test.d.ts.map +1 -0
  64. package/dist/__tests__/pipes/validation.pipe.test.js +297 -0
  65. package/dist/__tests__/request-parser.test.d.ts +2 -0
  66. package/dist/__tests__/request-parser.test.d.ts.map +1 -0
  67. package/dist/__tests__/request-parser.test.js +182 -0
  68. package/dist/__tests__/router.test.d.ts +2 -0
  69. package/dist/__tests__/router.test.d.ts.map +1 -0
  70. package/dist/__tests__/router.test.js +680 -0
  71. package/dist/__tests__/routing/route-matcher.test.d.ts +2 -0
  72. package/dist/__tests__/routing/route-matcher.test.d.ts.map +1 -0
  73. package/dist/__tests__/routing/route-matcher.test.js +219 -0
  74. package/dist/__tests__/routing/version.decorator.test.d.ts +2 -0
  75. package/dist/__tests__/routing/version.decorator.test.d.ts.map +1 -0
  76. package/dist/__tests__/routing/version.decorator.test.js +298 -0
  77. package/dist/__tests__/service.test.d.ts +2 -0
  78. package/dist/__tests__/service.test.d.ts.map +1 -0
  79. package/dist/__tests__/service.test.js +121 -0
  80. package/dist/__tests__/shutdown.test.d.ts +2 -0
  81. package/dist/__tests__/shutdown.test.d.ts.map +1 -0
  82. package/dist/__tests__/shutdown.test.js +250 -0
  83. package/dist/__tests__/testing/testing.module.test.d.ts +2 -0
  84. package/dist/__tests__/testing/testing.module.test.d.ts.map +1 -0
  85. package/dist/__tests__/testing/testing.module.test.js +370 -0
  86. package/dist/__tests__/upload/file-upload.test.d.ts +2 -0
  87. package/dist/__tests__/upload/file-upload.test.d.ts.map +1 -0
  88. package/dist/__tests__/upload/file-upload.test.js +498 -0
  89. package/dist/__tests__/utils/sanitize.test.d.ts +2 -0
  90. package/dist/__tests__/utils/sanitize.test.d.ts.map +1 -0
  91. package/dist/__tests__/utils/sanitize.test.js +291 -0
  92. package/dist/__tests__/validator.test.d.ts +2 -0
  93. package/dist/__tests__/validator.test.d.ts.map +1 -0
  94. package/dist/__tests__/validator.test.js +300 -0
  95. package/dist/container.d.ts +80 -0
  96. package/dist/container.d.ts.map +1 -0
  97. package/dist/container.js +271 -0
  98. package/dist/decorators.d.ts +92 -0
  99. package/dist/decorators.d.ts.map +1 -0
  100. package/dist/decorators.js +343 -0
  101. package/dist/errors/http.error.d.ts +31 -0
  102. package/dist/errors/http.error.d.ts.map +1 -0
  103. package/dist/errors/http.error.js +62 -0
  104. package/dist/filters/exception-filter.d.ts +39 -0
  105. package/dist/filters/exception-filter.d.ts.map +1 -0
  106. package/dist/filters/exception-filter.js +38 -0
  107. package/dist/filters/http-exception.filter.d.ts +9 -0
  108. package/dist/filters/http-exception.filter.d.ts.map +1 -0
  109. package/dist/filters/http-exception.filter.js +42 -0
  110. package/dist/hazel-app.d.ts +78 -0
  111. package/dist/hazel-app.d.ts.map +1 -0
  112. package/dist/hazel-app.js +453 -0
  113. package/dist/hazel-module.d.ts +20 -0
  114. package/dist/hazel-module.d.ts.map +1 -0
  115. package/dist/hazel-module.js +109 -0
  116. package/dist/hazel-response.d.ts +20 -0
  117. package/dist/hazel-response.d.ts.map +1 -0
  118. package/dist/hazel-response.js +68 -0
  119. package/dist/health.d.ts +73 -0
  120. package/dist/health.d.ts.map +1 -0
  121. package/dist/health.js +174 -0
  122. package/dist/index.d.ts +41 -0
  123. package/dist/index.d.ts.map +1 -0
  124. package/dist/index.js +140 -0
  125. package/dist/interceptors/interceptor.d.ts +22 -0
  126. package/dist/interceptors/interceptor.d.ts.map +1 -0
  127. package/dist/interceptors/interceptor.js +46 -0
  128. package/dist/logger.d.ts +8 -0
  129. package/dist/logger.d.ts.map +1 -0
  130. package/dist/logger.js +238 -0
  131. package/dist/middleware/cors.middleware.d.ts +44 -0
  132. package/dist/middleware/cors.middleware.d.ts.map +1 -0
  133. package/dist/middleware/cors.middleware.js +118 -0
  134. package/dist/middleware/csrf.middleware.d.ts +82 -0
  135. package/dist/middleware/csrf.middleware.d.ts.map +1 -0
  136. package/dist/middleware/csrf.middleware.js +183 -0
  137. package/dist/middleware/global-middleware.d.ts +111 -0
  138. package/dist/middleware/global-middleware.d.ts.map +1 -0
  139. package/dist/middleware/global-middleware.js +179 -0
  140. package/dist/middleware/rate-limit.middleware.d.ts +73 -0
  141. package/dist/middleware/rate-limit.middleware.d.ts.map +1 -0
  142. package/dist/middleware/rate-limit.middleware.js +124 -0
  143. package/dist/middleware/security-headers.middleware.d.ts +76 -0
  144. package/dist/middleware/security-headers.middleware.d.ts.map +1 -0
  145. package/dist/middleware/security-headers.middleware.js +123 -0
  146. package/dist/middleware/timeout.middleware.d.ts +25 -0
  147. package/dist/middleware/timeout.middleware.d.ts.map +1 -0
  148. package/dist/middleware/timeout.middleware.js +74 -0
  149. package/dist/middleware.d.ts +13 -0
  150. package/dist/middleware.d.ts.map +1 -0
  151. package/dist/middleware.js +47 -0
  152. package/dist/pipes/pipe.d.ts +50 -0
  153. package/dist/pipes/pipe.d.ts.map +1 -0
  154. package/dist/pipes/pipe.js +96 -0
  155. package/dist/pipes/validation.pipe.d.ts +6 -0
  156. package/dist/pipes/validation.pipe.d.ts.map +1 -0
  157. package/dist/pipes/validation.pipe.js +61 -0
  158. package/dist/request-context.d.ts +17 -0
  159. package/dist/request-context.d.ts.map +1 -0
  160. package/dist/request-context.js +2 -0
  161. package/dist/request-parser.d.ts +7 -0
  162. package/dist/request-parser.d.ts.map +1 -0
  163. package/dist/request-parser.js +60 -0
  164. package/dist/router.d.ts +33 -0
  165. package/dist/router.d.ts.map +1 -0
  166. package/dist/router.js +426 -0
  167. package/dist/routing/route-matcher.d.ts +39 -0
  168. package/dist/routing/route-matcher.d.ts.map +1 -0
  169. package/dist/routing/route-matcher.js +93 -0
  170. package/dist/routing/version.decorator.d.ts +36 -0
  171. package/dist/routing/version.decorator.d.ts.map +1 -0
  172. package/dist/routing/version.decorator.js +89 -0
  173. package/dist/service.d.ts +9 -0
  174. package/dist/service.d.ts.map +1 -0
  175. package/dist/service.js +39 -0
  176. package/dist/shutdown.d.ts +32 -0
  177. package/dist/shutdown.d.ts.map +1 -0
  178. package/dist/shutdown.js +109 -0
  179. package/dist/testing/testing.module.d.ts +83 -0
  180. package/dist/testing/testing.module.d.ts.map +1 -0
  181. package/dist/testing/testing.module.js +164 -0
  182. package/dist/types.d.ts +76 -0
  183. package/dist/types.d.ts.map +1 -0
  184. package/dist/types.js +2 -0
  185. package/dist/upload/file-upload.d.ts +75 -0
  186. package/dist/upload/file-upload.d.ts.map +1 -0
  187. package/dist/upload/file-upload.js +261 -0
  188. package/dist/utils/sanitize.d.ts +45 -0
  189. package/dist/utils/sanitize.d.ts.map +1 -0
  190. package/dist/utils/sanitize.js +165 -0
  191. package/dist/validator.d.ts +7 -0
  192. package/dist/validator.d.ts.map +1 -0
  193. package/dist/validator.js +119 -0
  194. package/package.json +65 -0
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const security_headers_middleware_1 = require("../../middleware/security-headers.middleware");
4
+ describe('SecurityHeadersMiddleware', () => {
5
+ let mockReq;
6
+ let mockRes;
7
+ let nextFn;
8
+ beforeEach(() => {
9
+ mockReq = {
10
+ method: 'GET',
11
+ url: '/test',
12
+ headers: {},
13
+ };
14
+ mockRes = {
15
+ setHeader: jest.fn(),
16
+ status: jest.fn().mockReturnThis(),
17
+ json: jest.fn(),
18
+ };
19
+ nextFn = jest.fn();
20
+ });
21
+ describe('default options', () => {
22
+ it('should set default security headers', () => {
23
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware();
24
+ middleware.use(mockReq, mockRes, nextFn);
25
+ expect(mockRes.setHeader).toHaveBeenCalledWith('X-Content-Type-Options', 'nosniff');
26
+ expect(mockRes.setHeader).toHaveBeenCalledWith('X-Frame-Options', 'DENY');
27
+ expect(mockRes.setHeader).toHaveBeenCalledWith('X-XSS-Protection', '1; mode=block');
28
+ expect(mockRes.setHeader).toHaveBeenCalledWith('X-Powered-By', '');
29
+ expect(nextFn).toHaveBeenCalled();
30
+ });
31
+ });
32
+ describe('X-Content-Type-Options', () => {
33
+ it('should set nosniff header when enabled', () => {
34
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({ noSniff: true });
35
+ middleware.use(mockReq, mockRes, nextFn);
36
+ expect(mockRes.setHeader).toHaveBeenCalledWith('X-Content-Type-Options', 'nosniff');
37
+ });
38
+ it('should not set nosniff header when disabled', () => {
39
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({ noSniff: false });
40
+ middleware.use(mockReq, mockRes, nextFn);
41
+ expect(mockRes.setHeader).not.toHaveBeenCalledWith('X-Content-Type-Options', 'nosniff');
42
+ });
43
+ });
44
+ describe('X-Frame-Options', () => {
45
+ it('should set DENY by default', () => {
46
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware();
47
+ middleware.use(mockReq, mockRes, nextFn);
48
+ expect(mockRes.setHeader).toHaveBeenCalledWith('X-Frame-Options', 'DENY');
49
+ });
50
+ it('should set SAMEORIGIN when specified', () => {
51
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({ frameOptions: 'SAMEORIGIN' });
52
+ middleware.use(mockReq, mockRes, nextFn);
53
+ expect(mockRes.setHeader).toHaveBeenCalledWith('X-Frame-Options', 'SAMEORIGIN');
54
+ });
55
+ it('should set custom value', () => {
56
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({ frameOptions: 'ALLOW-FROM https://example.com' });
57
+ middleware.use(mockReq, mockRes, nextFn);
58
+ expect(mockRes.setHeader).toHaveBeenCalledWith('X-Frame-Options', 'ALLOW-FROM https://example.com');
59
+ });
60
+ });
61
+ describe('X-XSS-Protection', () => {
62
+ it('should set XSS protection header when enabled', () => {
63
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({ xssProtection: true });
64
+ middleware.use(mockReq, mockRes, nextFn);
65
+ expect(mockRes.setHeader).toHaveBeenCalledWith('X-XSS-Protection', '1; mode=block');
66
+ });
67
+ it('should not set XSS protection header when disabled', () => {
68
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({ xssProtection: false });
69
+ middleware.use(mockReq, mockRes, nextFn);
70
+ expect(mockRes.setHeader).not.toHaveBeenCalledWith('X-XSS-Protection', expect.any(String));
71
+ });
72
+ });
73
+ describe('Strict-Transport-Security (HSTS)', () => {
74
+ it('should set HSTS header in production', () => {
75
+ const originalEnv = process.env.NODE_ENV;
76
+ process.env.NODE_ENV = 'production';
77
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware();
78
+ middleware.use(mockReq, mockRes, nextFn);
79
+ expect(mockRes.setHeader).toHaveBeenCalledWith('Strict-Transport-Security', expect.stringContaining('max-age=31536000'));
80
+ process.env.NODE_ENV = originalEnv;
81
+ });
82
+ it('should set HSTS with custom max-age', () => {
83
+ const originalEnv = process.env.NODE_ENV;
84
+ process.env.NODE_ENV = 'production';
85
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({
86
+ hsts: { maxAge: 7200 },
87
+ });
88
+ middleware.use(mockReq, mockRes, nextFn);
89
+ expect(mockRes.setHeader).toHaveBeenCalledWith('Strict-Transport-Security', expect.stringContaining('max-age=7200'));
90
+ process.env.NODE_ENV = originalEnv;
91
+ });
92
+ it('should include includeSubDomains when specified', () => {
93
+ const originalEnv = process.env.NODE_ENV;
94
+ process.env.NODE_ENV = 'production';
95
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({
96
+ hsts: { includeSubDomains: true },
97
+ });
98
+ middleware.use(mockReq, mockRes, nextFn);
99
+ expect(mockRes.setHeader).toHaveBeenCalledWith('Strict-Transport-Security', expect.stringContaining('includeSubDomains'));
100
+ process.env.NODE_ENV = originalEnv;
101
+ });
102
+ it('should include preload when specified', () => {
103
+ const originalEnv = process.env.NODE_ENV;
104
+ process.env.NODE_ENV = 'production';
105
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({
106
+ hsts: { preload: true },
107
+ });
108
+ middleware.use(mockReq, mockRes, nextFn);
109
+ expect(mockRes.setHeader).toHaveBeenCalledWith('Strict-Transport-Security', expect.stringContaining('preload'));
110
+ process.env.NODE_ENV = originalEnv;
111
+ });
112
+ it('should set HSTS for HTTPS requests', () => {
113
+ mockReq.headers = { 'x-forwarded-proto': 'https' };
114
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware();
115
+ middleware.use(mockReq, mockRes, nextFn);
116
+ expect(mockRes.setHeader).toHaveBeenCalledWith('Strict-Transport-Security', expect.any(String));
117
+ });
118
+ });
119
+ describe('Content-Security-Policy', () => {
120
+ it('should set CSP from string', () => {
121
+ const csp = "default-src 'self'; script-src 'self' 'unsafe-inline'";
122
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({
123
+ contentSecurityPolicy: csp,
124
+ });
125
+ middleware.use(mockReq, mockRes, nextFn);
126
+ expect(mockRes.setHeader).toHaveBeenCalledWith('Content-Security-Policy', csp);
127
+ });
128
+ it('should build CSP from object', () => {
129
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({
130
+ contentSecurityPolicy: {
131
+ defaultSrc: ["'self'"],
132
+ scriptSrc: ["'self'", "'unsafe-inline'"],
133
+ },
134
+ });
135
+ middleware.use(mockReq, mockRes, nextFn);
136
+ expect(mockRes.setHeader).toHaveBeenCalledWith('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline'");
137
+ });
138
+ it('should include all CSP directives', () => {
139
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({
140
+ contentSecurityPolicy: {
141
+ defaultSrc: ["'self'"],
142
+ scriptSrc: ["'self'"],
143
+ styleSrc: ["'self'"],
144
+ imgSrc: ["'self'", 'data:'],
145
+ connectSrc: ["'self'"],
146
+ fontSrc: ["'self'"],
147
+ objectSrc: ["'none'"],
148
+ mediaSrc: ["'self'"],
149
+ frameSrc: ["'none'"],
150
+ baseUri: ["'self'"],
151
+ formAction: ["'self'"],
152
+ frameAncestors: ["'none'"],
153
+ upgradeInsecureRequests: true,
154
+ },
155
+ });
156
+ middleware.use(mockReq, mockRes, nextFn);
157
+ const cspCall = mockRes.setHeader.mock.calls.find((call) => call[0] === 'Content-Security-Policy');
158
+ expect(cspCall).toBeDefined();
159
+ expect(cspCall[1]).toContain('default-src');
160
+ expect(cspCall[1]).toContain('script-src');
161
+ expect(cspCall[1]).toContain('upgrade-insecure-requests');
162
+ });
163
+ });
164
+ describe('Referrer-Policy', () => {
165
+ it('should set referrer policy', () => {
166
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({
167
+ referrerPolicy: 'no-referrer',
168
+ });
169
+ middleware.use(mockReq, mockRes, nextFn);
170
+ expect(mockRes.setHeader).toHaveBeenCalledWith('Referrer-Policy', 'no-referrer');
171
+ });
172
+ it('should support different referrer policies', () => {
173
+ const policies = [
174
+ 'no-referrer',
175
+ 'no-referrer-when-downgrade',
176
+ 'origin',
177
+ 'origin-when-cross-origin',
178
+ 'same-origin',
179
+ 'strict-origin',
180
+ 'strict-origin-when-cross-origin',
181
+ 'unsafe-url',
182
+ ];
183
+ policies.forEach((policy) => {
184
+ jest.clearAllMocks();
185
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({ referrerPolicy: policy });
186
+ middleware.use(mockReq, mockRes, nextFn);
187
+ expect(mockRes.setHeader).toHaveBeenCalledWith('Referrer-Policy', policy);
188
+ });
189
+ });
190
+ });
191
+ describe('Permissions-Policy', () => {
192
+ it('should set permissions policy', () => {
193
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({
194
+ permissionsPolicy: {
195
+ geolocation: [],
196
+ camera: ["'self'"],
197
+ },
198
+ });
199
+ middleware.use(mockReq, mockRes, nextFn);
200
+ expect(mockRes.setHeader).toHaveBeenCalledWith('Permissions-Policy', "geolocation=(), camera=('self')");
201
+ });
202
+ it('should handle multiple permissions', () => {
203
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({
204
+ permissionsPolicy: {
205
+ geolocation: [],
206
+ microphone: [],
207
+ camera: ["'self'"],
208
+ },
209
+ });
210
+ middleware.use(mockReq, mockRes, nextFn);
211
+ const permissionsCall = mockRes.setHeader.mock.calls.find((call) => call[0] === 'Permissions-Policy');
212
+ expect(permissionsCall[1]).toContain('geolocation=()');
213
+ expect(permissionsCall[1]).toContain('microphone=()');
214
+ expect(permissionsCall[1]).toContain("camera=('self')");
215
+ });
216
+ });
217
+ describe('X-Powered-By', () => {
218
+ it('should hide X-Powered-By by default', () => {
219
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware();
220
+ middleware.use(mockReq, mockRes, nextFn);
221
+ expect(mockRes.setHeader).toHaveBeenCalledWith('X-Powered-By', '');
222
+ });
223
+ it('should not hide X-Powered-By when disabled', () => {
224
+ const middleware = new security_headers_middleware_1.SecurityHeadersMiddleware({ hidePoweredBy: false });
225
+ middleware.use(mockReq, mockRes, nextFn);
226
+ expect(mockRes.setHeader).not.toHaveBeenCalledWith('X-Powered-By', '');
227
+ });
228
+ });
229
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=timeout.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeout.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/middleware/timeout.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const timeout_middleware_1 = require("../../middleware/timeout.middleware");
4
+ // Mock logger
5
+ jest.mock('../../logger', () => ({
6
+ warn: jest.fn(),
7
+ error: jest.fn(),
8
+ }));
9
+ describe('TimeoutMiddleware', () => {
10
+ let mockReq;
11
+ let mockRes;
12
+ let nextFn;
13
+ beforeEach(() => {
14
+ jest.useFakeTimers();
15
+ mockReq = {
16
+ method: 'GET',
17
+ url: '/test',
18
+ };
19
+ mockRes = {
20
+ status: jest.fn().mockReturnThis(),
21
+ json: jest.fn(),
22
+ end: jest.fn(),
23
+ setHeader: jest.fn(),
24
+ };
25
+ nextFn = jest.fn();
26
+ });
27
+ afterEach(() => {
28
+ jest.useRealTimers();
29
+ });
30
+ describe('constructor', () => {
31
+ it('should use default timeout of 30 seconds', () => {
32
+ const middleware = new timeout_middleware_1.TimeoutMiddleware();
33
+ expect(middleware).toBeDefined();
34
+ });
35
+ it('should accept custom timeout', () => {
36
+ const middleware = new timeout_middleware_1.TimeoutMiddleware({ timeout: 5000 });
37
+ expect(middleware).toBeDefined();
38
+ });
39
+ it('should accept custom message', () => {
40
+ const middleware = new timeout_middleware_1.TimeoutMiddleware({ message: 'Custom timeout' });
41
+ expect(middleware).toBeDefined();
42
+ });
43
+ });
44
+ describe('handle', () => {
45
+ it('should call next if request completes before timeout', () => {
46
+ const middleware = new timeout_middleware_1.TimeoutMiddleware({ timeout: 1000 });
47
+ middleware.handle(mockReq, mockRes, nextFn);
48
+ expect(nextFn).toHaveBeenCalled();
49
+ expect(mockRes.status).not.toHaveBeenCalled();
50
+ });
51
+ it('should send 408 response on timeout', () => {
52
+ const middleware = new timeout_middleware_1.TimeoutMiddleware({ timeout: 1000 });
53
+ middleware.handle(mockReq, mockRes, nextFn);
54
+ jest.advanceTimersByTime(1000);
55
+ expect(mockRes.status).toHaveBeenCalledWith(408);
56
+ expect(mockRes.json).toHaveBeenCalledWith({
57
+ statusCode: 408,
58
+ message: 'Request timeout',
59
+ error: 'Request Timeout',
60
+ });
61
+ });
62
+ it('should use custom timeout message', () => {
63
+ const middleware = new timeout_middleware_1.TimeoutMiddleware({
64
+ timeout: 1000,
65
+ message: 'Custom timeout message',
66
+ });
67
+ middleware.handle(mockReq, mockRes, nextFn);
68
+ jest.advanceTimersByTime(1000);
69
+ expect(mockRes.json).toHaveBeenCalledWith({
70
+ statusCode: 408,
71
+ message: 'Custom timeout message',
72
+ error: 'Request Timeout',
73
+ });
74
+ });
75
+ it('should call onTimeout callback when timeout occurs', () => {
76
+ const onTimeoutMock = jest.fn();
77
+ const middleware = new timeout_middleware_1.TimeoutMiddleware({
78
+ timeout: 1000,
79
+ onTimeout: onTimeoutMock,
80
+ });
81
+ middleware.handle(mockReq, mockRes, nextFn);
82
+ jest.advanceTimersByTime(1000);
83
+ expect(onTimeoutMock).toHaveBeenCalledWith(mockReq);
84
+ });
85
+ it('should handle errors in onTimeout callback gracefully', () => {
86
+ const onTimeoutMock = jest.fn(() => {
87
+ throw new Error('Callback error');
88
+ });
89
+ const middleware = new timeout_middleware_1.TimeoutMiddleware({
90
+ timeout: 1000,
91
+ onTimeout: onTimeoutMock,
92
+ });
93
+ middleware.handle(mockReq, mockRes, nextFn);
94
+ jest.advanceTimersByTime(1000);
95
+ // Should still send timeout response despite callback error
96
+ expect(mockRes.status).toHaveBeenCalledWith(408);
97
+ });
98
+ it('should clear timeout when response ends', () => {
99
+ const middleware = new timeout_middleware_1.TimeoutMiddleware({ timeout: 5000 });
100
+ middleware.handle(mockReq, mockRes, nextFn);
101
+ // Simulate response ending
102
+ mockRes.end();
103
+ // Advance past timeout
104
+ jest.advanceTimersByTime(6000);
105
+ // Should not send timeout response
106
+ expect(mockRes.status).not.toHaveBeenCalled();
107
+ });
108
+ it('should wrap res.end to clear timeout', () => {
109
+ const originalEnd = mockRes.end;
110
+ const middleware = new timeout_middleware_1.TimeoutMiddleware({ timeout: 1000 });
111
+ middleware.handle(mockReq, mockRes, nextFn);
112
+ expect(mockRes.end).not.toBe(originalEnd);
113
+ });
114
+ });
115
+ describe('create static method', () => {
116
+ it('should create middleware function', () => {
117
+ const middlewareFn = timeout_middleware_1.TimeoutMiddleware.create({ timeout: 1000 });
118
+ expect(typeof middlewareFn).toBe('function');
119
+ });
120
+ it('should create working middleware', () => {
121
+ const middlewareFn = timeout_middleware_1.TimeoutMiddleware.create({ timeout: 1000 });
122
+ middlewareFn(mockReq, mockRes, nextFn);
123
+ expect(nextFn).toHaveBeenCalled();
124
+ });
125
+ it('should trigger timeout with created middleware', () => {
126
+ const middlewareFn = timeout_middleware_1.TimeoutMiddleware.create({ timeout: 500 });
127
+ middlewareFn(mockReq, mockRes, nextFn);
128
+ jest.advanceTimersByTime(500);
129
+ expect(mockRes.status).toHaveBeenCalledWith(408);
130
+ });
131
+ });
132
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=middleware.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/middleware.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const middleware_1 = require("../middleware");
4
+ const container_1 = require("../container");
5
+ // Mock logger
6
+ jest.mock('../logger', () => ({
7
+ info: jest.fn(),
8
+ debug: jest.fn(),
9
+ warn: jest.fn(),
10
+ error: jest.fn(),
11
+ isDebugEnabled: jest.fn().mockReturnValue(false),
12
+ }));
13
+ describe('MiddlewareHandler', () => {
14
+ let handler;
15
+ let container;
16
+ let context;
17
+ beforeEach(() => {
18
+ container = container_1.Container.createTestInstance();
19
+ handler = new middleware_1.MiddlewareHandler(container);
20
+ context = {
21
+ method: 'GET',
22
+ url: '/test',
23
+ headers: {},
24
+ params: {},
25
+ query: {},
26
+ body: {},
27
+ };
28
+ });
29
+ describe('executeMiddlewareChain', () => {
30
+ it('should execute final handler when no middlewares', async () => {
31
+ const finalHandler = jest.fn().mockResolvedValue({ data: 'result' });
32
+ const result = await handler.executeMiddlewareChain([], context, finalHandler);
33
+ expect(finalHandler).toHaveBeenCalled();
34
+ expect(result).toEqual({ data: 'result' });
35
+ });
36
+ it('should execute single middleware', async () => {
37
+ class TestMiddleware {
38
+ async use(ctx, next) {
39
+ return next();
40
+ }
41
+ }
42
+ container.registerProvider({ token: TestMiddleware, useClass: TestMiddleware });
43
+ const finalHandler = jest.fn().mockResolvedValue({ data: 'result' });
44
+ const result = await handler.executeMiddlewareChain([TestMiddleware], context, finalHandler);
45
+ expect(result).toEqual({ data: 'result' });
46
+ });
47
+ it('should execute multiple middlewares in order', async () => {
48
+ const executionOrder = [];
49
+ class Middleware1 {
50
+ async use(ctx, next) {
51
+ executionOrder.push(1);
52
+ const result = await next();
53
+ executionOrder.push(4);
54
+ return result;
55
+ }
56
+ }
57
+ class Middleware2 {
58
+ async use(ctx, next) {
59
+ executionOrder.push(2);
60
+ const result = await next();
61
+ executionOrder.push(3);
62
+ return result;
63
+ }
64
+ }
65
+ container.registerProvider({ token: Middleware1, useClass: Middleware1 });
66
+ container.registerProvider({ token: Middleware2, useClass: Middleware2 });
67
+ const finalHandler = jest.fn().mockResolvedValue({ data: 'result' });
68
+ await handler.executeMiddlewareChain([Middleware1, Middleware2], context, finalHandler);
69
+ expect(executionOrder).toEqual([1, 2, 3, 4]);
70
+ });
71
+ it('should pass context through middleware chain', async () => {
72
+ let capturedContext = null;
73
+ class TestMiddleware {
74
+ async use(ctx, next) {
75
+ capturedContext = ctx;
76
+ return next();
77
+ }
78
+ }
79
+ container.registerProvider({ token: TestMiddleware, useClass: TestMiddleware });
80
+ const finalHandler = jest.fn().mockResolvedValue({});
81
+ await handler.executeMiddlewareChain([TestMiddleware], context, finalHandler);
82
+ expect(capturedContext).toBe(context);
83
+ });
84
+ it('should allow middleware to modify result', async () => {
85
+ class TransformMiddleware {
86
+ async use(ctx, next) {
87
+ const result = (await next());
88
+ return { ...result, transformed: true };
89
+ }
90
+ }
91
+ container.registerProvider({ token: TransformMiddleware, useClass: TransformMiddleware });
92
+ const finalHandler = jest.fn().mockResolvedValue({ data: 'original' });
93
+ const result = await handler.executeMiddlewareChain([TransformMiddleware], context, finalHandler);
94
+ expect(result).toEqual({ data: 'original', transformed: true });
95
+ });
96
+ it('should handle middleware errors', async () => {
97
+ class ErrorMiddleware {
98
+ async use(_ctx, _next) {
99
+ throw new Error('Middleware error');
100
+ }
101
+ }
102
+ container.registerProvider({ token: ErrorMiddleware, useClass: ErrorMiddleware });
103
+ const finalHandler = jest.fn();
104
+ await expect(handler.executeMiddlewareChain([ErrorMiddleware], context, finalHandler)).rejects.toThrow('Middleware error');
105
+ });
106
+ it('should add status code to errors without one', async () => {
107
+ class ErrorMiddleware {
108
+ async use(_ctx, _next) {
109
+ const error = new Error('Test error');
110
+ throw error;
111
+ }
112
+ }
113
+ container.registerProvider({ token: ErrorMiddleware, useClass: ErrorMiddleware });
114
+ const finalHandler = jest.fn();
115
+ try {
116
+ await handler.executeMiddlewareChain([ErrorMiddleware], context, finalHandler);
117
+ fail('Should have thrown error');
118
+ }
119
+ catch (error) {
120
+ expect(error.status).toBe(500);
121
+ }
122
+ });
123
+ it('should preserve existing status code on errors', async () => {
124
+ class ErrorMiddleware {
125
+ async use(_ctx, _next) {
126
+ const error = new Error('Test error');
127
+ error.status = 400;
128
+ throw error;
129
+ }
130
+ }
131
+ container.registerProvider({ token: ErrorMiddleware, useClass: ErrorMiddleware });
132
+ const finalHandler = jest.fn();
133
+ try {
134
+ await handler.executeMiddlewareChain([ErrorMiddleware], context, finalHandler);
135
+ fail('Should have thrown error');
136
+ }
137
+ catch (error) {
138
+ expect(error.status).toBe(400);
139
+ }
140
+ });
141
+ it('should handle final handler errors', async () => {
142
+ const finalHandler = jest.fn().mockRejectedValue(new Error('Handler error'));
143
+ await expect(handler.executeMiddlewareChain([], context, finalHandler)).rejects.toThrow('Handler error');
144
+ });
145
+ it('should add status to final handler errors', async () => {
146
+ const finalHandler = jest.fn().mockRejectedValue(new Error('Handler error'));
147
+ try {
148
+ await handler.executeMiddlewareChain([], context, finalHandler);
149
+ fail('Should have thrown error');
150
+ }
151
+ catch (error) {
152
+ expect(error.status).toBe(500);
153
+ }
154
+ });
155
+ it('should allow middleware to short-circuit chain', async () => {
156
+ class ShortCircuitMiddleware {
157
+ async use(_ctx, _next) {
158
+ return { shortCircuited: true };
159
+ }
160
+ }
161
+ container.registerProvider({ token: ShortCircuitMiddleware, useClass: ShortCircuitMiddleware });
162
+ const finalHandler = jest.fn();
163
+ const result = await handler.executeMiddlewareChain([ShortCircuitMiddleware], context, finalHandler);
164
+ expect(result).toEqual({ shortCircuited: true });
165
+ expect(finalHandler).not.toHaveBeenCalled();
166
+ });
167
+ it('should handle async middleware', async () => {
168
+ class AsyncMiddleware {
169
+ async use(ctx, next) {
170
+ await new Promise((resolve) => setTimeout(resolve, 10));
171
+ return next();
172
+ }
173
+ }
174
+ container.registerProvider({ token: AsyncMiddleware, useClass: AsyncMiddleware });
175
+ const finalHandler = jest.fn().mockResolvedValue({ data: 'result' });
176
+ const result = await handler.executeMiddlewareChain([AsyncMiddleware], context, finalHandler);
177
+ expect(result).toEqual({ data: 'result' });
178
+ });
179
+ });
180
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pipe.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipe.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/pipes/pipe.test.ts"],"names":[],"mappings":""}