@zintrust/core 0.4.18 → 0.4.19

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 (49) hide show
  1. package/package.json +1 -1
  2. package/src/cli/commands/AddCommand.d.ts +16 -0
  3. package/src/cli/commands/AddCommand.d.ts.map +1 -1
  4. package/src/cli/commands/AddCommand.js +157 -28
  5. package/src/cli/commands/DockerCommand.d.ts.map +1 -1
  6. package/src/cli/commands/DockerCommand.js +32 -4
  7. package/src/cli/commands/StartCommand.d.ts +7 -0
  8. package/src/cli/commands/StartCommand.d.ts.map +1 -1
  9. package/src/cli/commands/StartCommand.js +109 -20
  10. package/src/config/middleware.d.ts +23 -0
  11. package/src/config/middleware.d.ts.map +1 -1
  12. package/src/config/middleware.js +66 -31
  13. package/src/index.d.ts +2 -0
  14. package/src/index.d.ts.map +1 -1
  15. package/src/index.js +5 -3
  16. package/src/middleware/AuthMiddleware.d.ts +2 -0
  17. package/src/middleware/AuthMiddleware.d.ts.map +1 -1
  18. package/src/middleware/AuthMiddleware.js +8 -1
  19. package/src/middleware/BulletproofAuthMiddleware.d.ts +2 -0
  20. package/src/middleware/BulletproofAuthMiddleware.d.ts.map +1 -1
  21. package/src/middleware/BulletproofAuthMiddleware.js +13 -5
  22. package/src/middleware/CsrfMiddleware.d.ts +2 -0
  23. package/src/middleware/CsrfMiddleware.d.ts.map +1 -1
  24. package/src/middleware/CsrfMiddleware.js +9 -3
  25. package/src/middleware/ErrorHandlerMiddleware.d.ts +5 -1
  26. package/src/middleware/ErrorHandlerMiddleware.d.ts.map +1 -1
  27. package/src/middleware/ErrorHandlerMiddleware.js +12 -2
  28. package/src/middleware/JwtAuthMiddleware.d.ts +2 -0
  29. package/src/middleware/JwtAuthMiddleware.d.ts.map +1 -1
  30. package/src/middleware/JwtAuthMiddleware.js +39 -4
  31. package/src/middleware/MiddlewareFailureResponder.d.ts +15 -0
  32. package/src/middleware/MiddlewareFailureResponder.d.ts.map +1 -0
  33. package/src/middleware/MiddlewareFailureResponder.js +15 -0
  34. package/src/middleware/RateLimiter.d.ts +2 -0
  35. package/src/middleware/RateLimiter.d.ts.map +1 -1
  36. package/src/middleware/RateLimiter.js +10 -4
  37. package/src/middleware/ValidationMiddleware.d.ts +11 -6
  38. package/src/middleware/ValidationMiddleware.d.ts.map +1 -1
  39. package/src/middleware/ValidationMiddleware.js +48 -19
  40. package/src/middleware/index.d.ts +1 -0
  41. package/src/middleware/index.d.ts.map +1 -1
  42. package/src/middleware/index.js +1 -0
  43. package/src/runtime/WorkersModule.d.ts.map +1 -1
  44. package/src/runtime/WorkersModule.js +4 -3
  45. package/src/security/Xss.d.ts +2 -2
  46. package/src/security/Xss.d.ts.map +1 -1
  47. package/src/security/Xss.js +3 -4
  48. package/src/templates/project/basic/app/Middleware/AuthFailureResponder.ts.tpl +10 -0
  49. package/src/templates/project/basic/config/middleware.ts.tpl +18 -0
@@ -4,6 +4,7 @@
4
4
  * Zero-dependency implementation
5
5
  */
6
6
  import type { IRequest } from '../http/Request';
7
+ import { type MiddlewareFailureResponder } from './MiddlewareFailureResponder';
7
8
  import type { Middleware } from './MiddlewareStack';
8
9
  export interface RateLimitOptions {
9
10
  windowMs: number;
@@ -20,6 +21,7 @@ export interface RateLimitOptions {
20
21
  * - 'db' uses Cache.store('mongodb')
21
22
  */
22
23
  store?: RateLimitStoreName;
24
+ onFailure?: MiddlewareFailureResponder;
23
25
  }
24
26
  export type RateLimitStoreName = 'memory' | 'redis' | 'kv' | 'db';
25
27
  export declare const RateLimiter: Readonly<{
@@ -1 +1 @@
1
- {"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../../src/middleware/RateLimiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,MAAM,CAAC;IAEzC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,kBAAkB,CAAC;CAC5B;AAED,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC;AAqKlE,eAAO,MAAM,WAAW;IACtB;;;OAGG;uBACgB;QAAE,KAAK,CAAC,EAAE,kBAAkB,CAAA;KAAE,GAAG,IAAI;IAKxD;;;;OAIG;iBACgB,MAAM,eAAe,MAAM,gBAAgB,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYvF;;OAEG;yBACwB,MAAM,eAAe,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQzE;;;OAGG;cACa,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQxC;;OAEG;eACc,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC;;OAEG;qBACa,gBAAgB,GAAqB,UAAU;EAgF/D,CAAC"}
1
+ {"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../../src/middleware/RateLimiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,wCAAwC,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,MAAM,CAAC;IAEzC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACxC;AAED,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC;AAqKlE,eAAO,MAAM,WAAW;IACtB;;;OAGG;uBACgB;QAAE,KAAK,CAAC,EAAE,kBAAkB,CAAA;KAAE,GAAG,IAAI;IAKxD;;;;OAIG;iBACgB,MAAM,eAAe,MAAM,gBAAgB,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYvF;;OAEG;yBACwB,MAAM,eAAe,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQzE;;;OAGG;cACa,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQxC;;OAEG;eACc,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC;;OAEG;qBACa,gBAAgB,GAAqB,UAAU;EAqF/D,CAAC"}
@@ -6,6 +6,7 @@
6
6
  import { Cache } from '../cache/Cache.js';
7
7
  import { Env } from '../config/env.js';
8
8
  import { Logger } from '../config/logger.js';
9
+ import { respondWithMiddlewareFailure, } from './MiddlewareFailureResponder.js';
9
10
  const createMemoryStore = () => {
10
11
  const entries = new Map();
11
12
  let nextCleanupAt = Date.now() + 60_000;
@@ -257,10 +258,15 @@ export const RateLimiter = Object.freeze({
257
258
  // Check limit
258
259
  if (count > config.max) {
259
260
  Logger.warn(`Rate limit exceeded for IP: ${key}`);
260
- res.setStatus(config.statusCode ?? 429);
261
- res.json({
262
- error: 'Too Many Requests',
263
- message: config.message,
261
+ await respondWithMiddlewareFailure(req, res, config.onFailure, {
262
+ middleware: 'rateLimit',
263
+ reason: 'rate_limit_exceeded',
264
+ statusCode: config.statusCode ?? 429,
265
+ message: config.message ?? 'Too many requests',
266
+ body: {
267
+ error: 'Too Many Requests',
268
+ message: config.message,
269
+ },
264
270
  });
265
271
  return;
266
272
  }
@@ -1,12 +1,17 @@
1
+ import { type MiddlewareFailureResponder } from './MiddlewareFailureResponder';
1
2
  import type { Middleware } from './MiddlewareStack';
2
3
  import type { ISchema, TypedSchema } from '../validation/Validator';
4
+ type ValidationMiddlewareOptions = Readonly<{
5
+ onFailure?: MiddlewareFailureResponder;
6
+ middlewareKey?: string;
7
+ }>;
3
8
  type FieldSanitizers = Readonly<Record<string, (value: unknown) => unknown>>;
4
9
  export declare const ValidationMiddleware: Readonly<{
5
- create(schema: ISchema): Middleware;
6
- createBody<TSchema extends TypedSchema<unknown>>(schema: TSchema): Middleware;
7
- createBodyWithSanitization<TSchema extends TypedSchema<unknown>>(schema: TSchema, sanitizers?: FieldSanitizers): Middleware;
8
- createQuery<TSchema extends TypedSchema<unknown>>(schema: TSchema): Middleware;
9
- createParams<TSchema extends TypedSchema<unknown>>(schema: TSchema): Middleware;
10
+ create(schema: ISchema, options?: ValidationMiddlewareOptions): Middleware;
11
+ createBody<TSchema extends TypedSchema<unknown>>(schema: TSchema, options?: ValidationMiddlewareOptions): Middleware;
12
+ createBodyWithSanitization<TSchema extends TypedSchema<unknown>>(schema: TSchema, sanitizers?: FieldSanitizers, options?: ValidationMiddlewareOptions): Middleware;
13
+ createQuery<TSchema extends TypedSchema<unknown>>(schema: TSchema, options?: ValidationMiddlewareOptions): Middleware;
14
+ createParams<TSchema extends TypedSchema<unknown>>(schema: TSchema, options?: ValidationMiddlewareOptions): Middleware;
10
15
  /**
11
16
  * Create body validation middleware with bulletproof sanitization error handling.
12
17
  * Automatically converts SanitizerError to 422 validation response.
@@ -19,7 +24,7 @@ export declare const ValidationMiddleware: Readonly<{
19
24
  * @param sanitizers - Optional field sanitizers to apply before validation
20
25
  * @returns Middleware with bulletproof error handling
21
26
  */
22
- createBodyWithBulletproofSanitization<TSchema extends TypedSchema<unknown>>(schema: TSchema, sanitizers?: FieldSanitizers): Middleware;
27
+ createBodyWithBulletproofSanitization<TSchema extends TypedSchema<unknown>>(schema: TSchema, sanitizers?: FieldSanitizers, options?: ValidationMiddlewareOptions): Middleware;
23
28
  }>;
24
29
  export {};
25
30
  //# sourceMappingURL=ValidationMiddleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ValidationMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/ValidationMiddleware.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,KAAK,EAAe,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAW/E,KAAK,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC;AAqG7E,eAAO,MAAM,oBAAoB;mBAChB,OAAO,GAAG,UAAU;eAwBxB,OAAO,SAAS,WAAW,CAAC,OAAO,CAAC,UAAU,OAAO,GAAG,UAAU;+BA0BlD,OAAO,SAAS,WAAW,CAAC,OAAO,CAAC,UACrD,OAAO,eACF,eAAe,GAC3B,UAAU;gBA6BD,OAAO,SAAS,WAAW,CAAC,OAAO,CAAC,UAAU,OAAO,GAAG,UAAU;iBAejE,OAAO,SAAS,WAAW,CAAC,OAAO,CAAC,UAAU,OAAO,GAAG,UAAU;IAe/E;;;;;;;;;;;OAWG;0CACmC,OAAO,SAAS,WAAW,CAAC,OAAO,CAAC,UAChE,OAAO,eACF,eAAe,GAC3B,UAAU;EAqCb,CAAC"}
1
+ {"version":3,"file":"ValidationMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/ValidationMiddleware.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,wCAAwC,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,KAAK,EAAe,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAI/E,KAAK,2BAA2B,GAAG,QAAQ,CAAC;IAC1C,SAAS,CAAC,EAAE,0BAA0B,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC,CAAC;AAQH,KAAK,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC;AA+H7E,eAAO,MAAM,oBAAoB;mBAChB,OAAO,YAAW,2BAA2B,GAAQ,UAAU;eAwBnE,OAAO,SAAS,WAAW,CAAC,OAAO,CAAC,UACrC,OAAO,YACN,2BAA2B,GACnC,UAAU;+BA0Bc,OAAO,SAAS,WAAW,CAAC,OAAO,CAAC,UACrD,OAAO,eACF,eAAe,YACnB,2BAA2B,GACnC,UAAU;gBA6BD,OAAO,SAAS,WAAW,CAAC,OAAO,CAAC,UACtC,OAAO,YACN,2BAA2B,GACnC,UAAU;iBAeA,OAAO,SAAS,WAAW,CAAC,OAAO,CAAC,UACvC,OAAO,YACN,2BAA2B,GACnC,UAAU;IAeb;;;;;;;;;;;OAWG;0CACmC,OAAO,SAAS,WAAW,CAAC,OAAO,CAAC,UAChE,OAAO,eACF,eAAe,YACnB,2BAA2B,GACnC,UAAU;EA4Cb,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { Env } from '../config/env.js';
2
2
  import { Logger } from '../config/logger.js';
3
+ import { respondWithMiddlewareFailure, } from './MiddlewareFailureResponder.js';
3
4
  import { Xss } from '../security/Xss.js';
4
5
  import { Validator } from '../validation/Validator.js';
5
6
  const toRecord = (value) => {
@@ -73,7 +74,7 @@ const getBodyForValidation = (req) => {
73
74
  const raw = safeCall(() => req.getBody?.());
74
75
  return toBodyRecord(raw);
75
76
  };
76
- const handleValidationError = (res, error) => {
77
+ const handleValidationError = async (req, res, error, options) => {
77
78
  // Temporary: log validation error details to help debugging failing requests.
78
79
  // Remove this detailed debug logging once the issue is investigated.
79
80
  Logger.warn('Validation failed');
@@ -88,21 +89,42 @@ const handleValidationError = (res, error) => {
88
89
  // best-effort: fall back to direct log
89
90
  Logger.debug('[Validation] errors (toObject threw):', err);
90
91
  }
91
- res.setStatus(422).json({ errors: err.toObject() });
92
+ await respondWithMiddlewareFailure(req, res, options.onFailure, {
93
+ middleware: options.middlewareKey ?? 'validation',
94
+ reason: 'validation_error',
95
+ statusCode: 422,
96
+ message: 'Validation failed',
97
+ body: { errors: err.toObject() },
98
+ error,
99
+ });
92
100
  return;
93
101
  }
94
102
  // Fallback: log raw error
95
103
  Logger.debug('[Validation] error:', err);
96
- res.setStatus(400).json({ error: 'Invalid request body' });
104
+ await respondWithMiddlewareFailure(req, res, options.onFailure, {
105
+ middleware: options.middlewareKey ?? 'validation',
106
+ reason: 'invalid_request_body',
107
+ statusCode: 400,
108
+ message: 'Invalid request body',
109
+ body: { error: 'Invalid request body' },
110
+ error,
111
+ });
97
112
  }
98
113
  catch (error_) {
99
114
  // Ensure we don't throw while handling validation errors
100
115
  Logger.debug('[Validation] failed to log error details:', error_);
101
- res.setStatus(400).json({ error: 'Invalid request body' });
116
+ await respondWithMiddlewareFailure(req, res, options.onFailure, {
117
+ middleware: options.middlewareKey ?? 'validation',
118
+ reason: 'invalid_request_body',
119
+ statusCode: 400,
120
+ message: 'Invalid request body',
121
+ body: { error: 'Invalid request body' },
122
+ error,
123
+ });
102
124
  }
103
125
  };
104
126
  export const ValidationMiddleware = Object.freeze({
105
- create(schema) {
127
+ create(schema, options = {}) {
106
128
  return async (req, res, next) => {
107
129
  const method = req.getMethod();
108
130
  if (method === 'GET' || method === 'DELETE') {
@@ -120,11 +142,11 @@ export const ValidationMiddleware = Object.freeze({
120
142
  await next();
121
143
  }
122
144
  catch (error) {
123
- handleValidationError(res, error);
145
+ await handleValidationError(req, res, error, options);
124
146
  }
125
147
  };
126
148
  },
127
- createBody(schema) {
149
+ createBody(schema, options = {}) {
128
150
  return async (req, res, next) => {
129
151
  const method = req.getMethod();
130
152
  if (method === 'GET' || method === 'DELETE') {
@@ -142,11 +164,11 @@ export const ValidationMiddleware = Object.freeze({
142
164
  await next();
143
165
  }
144
166
  catch (error) {
145
- handleValidationError(res, error);
167
+ await handleValidationError(req, res, error, options);
146
168
  }
147
169
  };
148
170
  },
149
- createBodyWithSanitization(schema, sanitizers) {
171
+ createBodyWithSanitization(schema, sanitizers, options = {}) {
150
172
  return async (req, res, next) => {
151
173
  const method = req.getMethod();
152
174
  if (method === 'GET' || method === 'DELETE') {
@@ -165,11 +187,11 @@ export const ValidationMiddleware = Object.freeze({
165
187
  await next();
166
188
  }
167
189
  catch (error) {
168
- handleValidationError(res, error);
190
+ await handleValidationError(req, res, error, options);
169
191
  }
170
192
  };
171
193
  },
172
- createQuery(schema) {
194
+ createQuery(schema, options = {}) {
173
195
  return async (req, res, next) => {
174
196
  try {
175
197
  const query = toRecord(req.getQuery());
@@ -178,11 +200,11 @@ export const ValidationMiddleware = Object.freeze({
178
200
  await next();
179
201
  }
180
202
  catch (error) {
181
- handleValidationError(res, error);
203
+ await handleValidationError(req, res, error, options);
182
204
  }
183
205
  };
184
206
  },
185
- createParams(schema) {
207
+ createParams(schema, options = {}) {
186
208
  return async (req, res, next) => {
187
209
  try {
188
210
  const params = toRecord(req.getParams());
@@ -191,7 +213,7 @@ export const ValidationMiddleware = Object.freeze({
191
213
  await next();
192
214
  }
193
215
  catch (error) {
194
- handleValidationError(res, error);
216
+ await handleValidationError(req, res, error, options);
195
217
  }
196
218
  };
197
219
  },
@@ -207,7 +229,7 @@ export const ValidationMiddleware = Object.freeze({
207
229
  * @param sanitizers - Optional field sanitizers to apply before validation
208
230
  * @returns Middleware with bulletproof error handling
209
231
  */
210
- createBodyWithBulletproofSanitization(schema, sanitizers) {
232
+ createBodyWithBulletproofSanitization(schema, sanitizers, options = {}) {
211
233
  return async (req, res, next) => {
212
234
  const method = req.getMethod();
213
235
  if (method === 'GET' || method === 'DELETE') {
@@ -228,14 +250,21 @@ export const ValidationMiddleware = Object.freeze({
228
250
  catch (error) {
229
251
  // Handle SanitizerError by converting to validation error format
230
252
  if (isSanitizerError(error)) {
231
- res.setStatus(422).json({
232
- errors: {
233
- sanitization: [error.message],
253
+ await respondWithMiddlewareFailure(req, res, options.onFailure, {
254
+ middleware: options.middlewareKey ?? 'validation',
255
+ reason: 'sanitization_error',
256
+ statusCode: 422,
257
+ message: error.message,
258
+ body: {
259
+ errors: {
260
+ sanitization: [error.message],
261
+ },
234
262
  },
263
+ error,
235
264
  });
236
265
  return;
237
266
  }
238
- handleValidationError(res, error);
267
+ await handleValidationError(req, res, error, options);
239
268
  }
240
269
  };
241
270
  },
@@ -5,6 +5,7 @@
5
5
  export * from './CsrfMiddleware';
6
6
  export * from './ErrorHandlerMiddleware';
7
7
  export * from './LoggingMiddleware';
8
+ export * from './MiddlewareFailureResponder';
8
9
  export * from './MiddlewareStack';
9
10
  export * from './RateLimiter';
10
11
  export * from './SecurityMiddleware';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/middleware/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/middleware/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC"}
@@ -5,6 +5,7 @@
5
5
  export * from './CsrfMiddleware.js';
6
6
  export * from './ErrorHandlerMiddleware.js';
7
7
  export * from './LoggingMiddleware.js';
8
+ export * from './MiddlewareFailureResponder.js';
8
9
  export * from './MiddlewareStack.js';
9
10
  export * from './RateLimiter.js';
10
11
  export * from './SecurityMiddleware.js';
@@ -1 +1 @@
1
- {"version":3,"file":"WorkersModule.d.ts","sourceRoot":"","sources":["../../../src/runtime/WorkersModule.ts"],"names":[],"mappings":"AAOA,KAAK,aAAa,GAAG,cAAc,mBAAmB,CAAC,CAAC;AACxD,KAAK,kBAAkB,GAAG,cAAc,yBAAyB,CAAC,CAAC;AA4WnE,eAAO,MAAM,iBAAiB,QAAa,OAAO,CAAC,aAAa,CAwB/D,CAAC;AA4CF,eAAO,MAAM,sBAAsB,QAAa,OAAO,CAAC,kBAAkB,CAkBzE,CAAC"}
1
+ {"version":3,"file":"WorkersModule.d.ts","sourceRoot":"","sources":["../../../src/runtime/WorkersModule.ts"],"names":[],"mappings":"AAOA,KAAK,aAAa,GAAG,cAAc,mBAAmB,CAAC,CAAC;AACxD,KAAK,kBAAkB,GAAG,cAAc,yBAAyB,CAAC,CAAC;AA8WnE,eAAO,MAAM,iBAAiB,QAAa,OAAO,CAAC,aAAa,CAwB/D,CAAC;AA4CF,eAAO,MAAM,sBAAsB,QAAa,OAAO,CAAC,kBAAkB,CAkBzE,CAAC"}
@@ -268,6 +268,7 @@ const isMissingOptionalWorkersModuleError = (error) => {
268
268
  });
269
269
  };
270
270
  const handleImportFailure = async (error) => {
271
+ let finalError = error;
271
272
  if (shouldRetryAfterFailure(error)) {
272
273
  patchAfterFailureAttempted = true;
273
274
  const { replacements, filesChanged } = patchWorkersDist();
@@ -281,7 +282,7 @@ const handleImportFailure = async (error) => {
281
282
  return await workersModulePromise;
282
283
  }
283
284
  catch (retryError) {
284
- error = retryError;
285
+ finalError = retryError;
285
286
  }
286
287
  }
287
288
  }
@@ -290,12 +291,12 @@ const handleImportFailure = async (error) => {
290
291
  workersModulePromise = Promise.resolve(localFallback);
291
292
  return localFallback;
292
293
  }
293
- if (isMissingOptionalWorkersModuleError(error)) {
294
+ if (isMissingOptionalWorkersModuleError(finalError)) {
294
295
  Logger.info('Optional @zintrust/workers package is unavailable; worker routes are disabled.');
295
296
  workersModulePromise = Promise.resolve(createDisabledWorkersModule());
296
297
  return workersModulePromise;
297
298
  }
298
- throw error;
299
+ throw finalError;
299
300
  };
300
301
  const tryLocalFallback = async () => {
301
302
  const localFallback = await importLocalWorkersModule();
@@ -2,8 +2,8 @@
2
2
  * XSS Sanitizer
3
3
  * Recursive, zero-dependency input sanitization utility.
4
4
  *
5
- * This is intentionally conservative:
6
- * - Strings: strip tags, then escape HTML entities.
5
+ * This is intentionally conservative for request-body handling:
6
+ * - Strings: strip markup tags but preserve plain text characters.
7
7
  * - Arrays/Objects: sanitize recursively.
8
8
  */
9
9
  export interface IXss {
@@ -1 +1 @@
1
- {"version":3,"file":"Xss.d.ts","sourceRoot":"","sources":["../../../src/security/Xss.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAwDH,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;CACnC;AAED,eAAO,MAAM,GAAG,EAAE,IAIhB,CAAC;AAEH,eAAe,GAAG,CAAC"}
1
+ {"version":3,"file":"Xss.d.ts","sourceRoot":"","sources":["../../../src/security/Xss.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsDH,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;CACnC;AAED,eAAO,MAAM,GAAG,EAAE,IAIhB,CAAC;AAEH,eAAe,GAAG,CAAC"}
@@ -2,11 +2,10 @@
2
2
  * XSS Sanitizer
3
3
  * Recursive, zero-dependency input sanitization utility.
4
4
  *
5
- * This is intentionally conservative:
6
- * - Strings: strip tags, then escape HTML entities.
5
+ * This is intentionally conservative for request-body handling:
6
+ * - Strings: strip markup tags but preserve plain text characters.
7
7
  * - Arrays/Objects: sanitize recursively.
8
8
  */
9
- import { XssProtection } from './XssProtection.js';
10
9
  const stripTags = (value) => {
11
10
  // Remove all HTML tags in linear time (no regex backtracking / ReDoS risk).
12
11
  let out = '';
@@ -28,7 +27,7 @@ const stripTags = (value) => {
28
27
  };
29
28
  const sanitizeRecursive = (input, seen) => {
30
29
  if (typeof input === 'string') {
31
- return XssProtection.escape(stripTags(input));
30
+ return stripTags(input);
32
31
  }
33
32
  if (Array.isArray(input)) {
34
33
  if (seen.has(input))
@@ -0,0 +1,10 @@
1
+ import type { MiddlewareFailureResponder } from '@zintrust/core';
2
+
3
+ export const authFailureResponder: MiddlewareFailureResponder = async (_req, res, context) => {
4
+ res.setStatus(context.statusCode).json({
5
+ error: {
6
+ code: context.reason,
7
+ message: context.message,
8
+ },
9
+ });
10
+ };
@@ -9,6 +9,12 @@ import type { MiddlewaresType } from '@zintrust/core';
9
9
  * 2. Import it below.
10
10
  * 3. Register route middleware under `route` or append global middleware under `global`.
11
11
  * 4. Use the route key in `routes/*.ts`.
12
+ * 5. Use `responders` when you only want to reshape built-in failure payloads.
13
+ *
14
+ * Built-in middleware keys are overrideable by reusing the same key under `route`.
15
+ * For example, `route.jwt = MyJwtMiddleware` replaces the framework `jwt` middleware
16
+ * anywhere that key is used, including shared global slots such as `log`, `error`,
17
+ * `security`, `rateLimit`, `csrf`, and `sanitizeBody`.
12
18
  *
13
19
  * For custom route keys, extend the framework type locally in your route file:
14
20
  * `type AppMiddlewareKey = MiddlewareKey | 'yourMiddleware';`
@@ -16,6 +22,8 @@ import type { MiddlewaresType } from '@zintrust/core';
16
22
 
17
23
  // Example custom middleware import:
18
24
  // import { AuthMiddleware } from '@app/Middleware/AuthMiddleware';
25
+ // import { authFailureResponder } from '@app/Middleware/AuthFailureResponder';
26
+ // import { JwtAuthOverrideMiddleware } from '@app/Middleware/JwtAuthOverrideMiddleware';
19
27
 
20
28
  export default {
21
29
  skipPaths: Env.get('CSRF_SKIP_PATHS', '')
@@ -37,10 +45,20 @@ export default {
37
45
  max: 20,
38
46
  message: 'Too many user mutation requests, please try again later.',
39
47
  },
48
+ responders: {
49
+ // auth: authFailureResponder,
50
+ // jwt: authFailureResponder,
51
+ // bulletproof: authFailureResponder,
52
+ // csrf: authFailureResponder,
53
+ // rateLimit: authFailureResponder,
54
+ // error: authFailureResponder,
55
+ },
40
56
  global: [
41
57
  // AuthMiddleware,
42
58
  ],
43
59
  route: {
44
60
  // authMiddleware: AuthMiddleware,
61
+ // Plug-and-play built-in override example:
62
+ // jwt: JwtAuthOverrideMiddleware,
45
63
  },
46
64
  } as MiddlewaresType;