@batkit/express-middleware 0.1.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -197,17 +197,6 @@ Wraps async route handlers to catch errors.
197
197
 
198
198
  ### Types
199
199
 
200
- #### `RequestContext`
201
-
202
- ```typescript
203
- interface RequestContext {
204
- requestId: string;
205
- logger: Logger;
206
- userId?: string;
207
- metadata: Record<string, unknown>;
208
- }
209
- ```
210
-
211
200
  #### `ErrorFormatter`
212
201
 
213
202
  ```typescript
@@ -1 +1 @@
1
- {"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../src/error-handler.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,sBAAsB,EAG5B,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAM/D,MAAM,WAAW,cAAc;IAI7B,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAKnC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CAAC;CAChD;AAKD,qBAAa,qBAAsB,YAAW,cAAc;IAC1D,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IASlC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB;IAmC9C,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,cAAc;CAevB;AAKD,MAAM,WAAW,mBAAmB;IAIlC,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAK9B,SAAS,CAAC,EAAE,OAAO,CAAC;IAKpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD;AAwBD,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAwB,GAChC,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAiFzE;AAsBD,wBAAgB,YAAY,CAC1B,EAAE,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,OAAO,CAAC,GACxE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAI3D"}
1
+ {"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../src/error-handler.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,sBAAsB,EAG5B,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAY/D,MAAM,WAAW,cAAc;IAI7B,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAKnC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CAAC;CAChD;AAKD,qBAAa,qBAAsB,YAAW,cAAc;IAC1D,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IASlC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB;IAmC9C,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,cAAc;CAevB;AAKD,MAAM,WAAW,mBAAmB;IAIlC,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAK9B,SAAS,CAAC,EAAE,OAAO,CAAC;IAKpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD;AA2ED,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAwB,GAEhC,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAiCzE;AAsBD,wBAAgB,YAAY,CAC1B,EAAE,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,OAAO,CAAC,GACxE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAI3D"}
@@ -2,6 +2,11 @@ import { isAppError } from "@batkit/errors";
2
2
  import { LoggerFacade } from "@batkit/logger";
3
3
  import { PROBLEM_DETAILS_CONTENT_TYPE, createExtendedProblemDetails, } from "@batkit/rfc9457";
4
4
  const logger = LoggerFacade.getLogger("error-handler");
5
+ const HttpStatus = {
6
+ BAD_GATEWAY: 502,
7
+ INTERNAL_SERVER_ERROR: 500,
8
+ UNPROCESSABLE_ENTITY: 422,
9
+ };
5
10
  export class DefaultErrorFormatter {
6
11
  canFormat(error) {
7
12
  return (isAppError(error) ||
@@ -21,17 +26,17 @@ export class DefaultErrorFormatter {
21
26
  }
22
27
  if (error instanceof Error) {
23
28
  return createExtendedProblemDetails({
24
- type: "error:internal",
25
- title: "Internal Server Error",
26
- status: 500,
27
29
  detail: error.message,
30
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
31
+ title: "Internal Server Error",
32
+ type: "error:internal",
28
33
  });
29
34
  }
30
35
  return createExtendedProblemDetails({
31
- type: "error:unknown",
32
- title: "Unknown Error",
33
- status: 500,
34
36
  detail: "An unknown error occurred",
37
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
38
+ title: "Unknown Error",
39
+ type: "error:unknown",
35
40
  });
36
41
  }
37
42
  isAxiosError(error) {
@@ -47,88 +52,87 @@ export class DefaultErrorFormatter {
47
52
  Array.isArray(error.issues));
48
53
  }
49
54
  formatAxiosError(error) {
50
- const status = error.response?.status || 502;
55
+ const status = error.response?.status || HttpStatus.BAD_GATEWAY;
51
56
  return createExtendedProblemDetails({
52
- type: "error:upstream",
53
- title: "Upstream Service Error",
54
- status,
55
57
  detail: error.message,
56
- upstreamUrl: error.config?.url,
58
+ status,
59
+ title: "Upstream Service Error",
60
+ type: "error:upstream",
57
61
  upstreamMethod: error.config?.method?.toUpperCase(),
58
62
  upstreamStatus: error.response?.status,
63
+ upstreamUrl: error.config?.url,
59
64
  });
60
65
  }
61
66
  formatZodError(error) {
62
67
  const validationErrors = error.issues.map((issue) => ({
68
+ code: issue.code,
63
69
  field: issue.path.join("."),
64
70
  message: issue.message,
65
- code: issue.code,
66
71
  }));
67
72
  return createExtendedProblemDetails({
68
- type: "error:validation",
69
- title: "Validation Error",
70
- status: 422,
71
73
  detail: "Request validation failed",
74
+ status: HttpStatus.UNPROCESSABLE_ENTITY,
75
+ title: "Validation Error",
76
+ type: "error:validation",
72
77
  validationErrors,
73
78
  });
74
79
  }
75
80
  }
81
+ function logHandledError(error, req, options) {
82
+ const { onError } = options;
83
+ if (onError) {
84
+ onError(error, req);
85
+ return;
86
+ }
87
+ if (isAppError(error) && error.isOperational) {
88
+ logger.warn("Operational error occurred", {
89
+ code: error.code,
90
+ error: error.message,
91
+ method: req.method,
92
+ path: req.path,
93
+ statusCode: error.statusCode,
94
+ });
95
+ return;
96
+ }
97
+ const contentType = req.headers?.["content-type"];
98
+ const isJsonContentType = typeof contentType === "string" && /^application\/(?:[^;]+\+)?json/iu.test(contentType);
99
+ const isBinaryBody = Buffer.isBuffer(req.body) || (contentType !== undefined && !isJsonContentType);
100
+ let bodyLength;
101
+ if (Buffer.isBuffer(req.body)) {
102
+ bodyLength = req.body.length;
103
+ }
104
+ else if (typeof req.body === "string") {
105
+ bodyLength = Buffer.byteLength(req.body);
106
+ }
107
+ logger.error(error, {
108
+ method: req.method,
109
+ path: req.path,
110
+ query: req.query,
111
+ ...(isBinaryBody ? { bodyContentType: contentType, bodyLength } : { body: req.body }),
112
+ });
113
+ }
114
+ function buildProblemDetails(error, formatters) {
115
+ const formatter = formatters.find((candidate) => candidate.canFormat(error));
116
+ return formatter
117
+ ? formatter.format(error)
118
+ : createExtendedProblemDetails({
119
+ detail: "An unexpected error occurred",
120
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
121
+ title: "Internal Server Error",
122
+ type: "error:internal",
123
+ });
124
+ }
76
125
  export function errorHandler(options = {}) {
77
- const { formatters = [new DefaultErrorFormatter()], logErrors = true, onError } = options;
126
+ const { formatters = [new DefaultErrorFormatter()], logErrors = true } = options;
78
127
  return (error, req, res, next) => {
79
128
  if (res.headersSent) {
80
129
  next(error);
81
130
  return;
82
131
  }
83
132
  if (logErrors) {
84
- if (onError) {
85
- onError(error, req);
86
- }
87
- else {
88
- if (isAppError(error) && error.isOperational) {
89
- logger.warn("Operational error occurred", {
90
- error: error.message,
91
- code: error.code,
92
- statusCode: error.statusCode,
93
- path: req.path,
94
- method: req.method,
95
- });
96
- }
97
- else {
98
- const contentType = req.headers?.["content-type"];
99
- const isJsonContentType = typeof contentType === "string" && /^application\/(?:[^;]+\+)?json/i.test(contentType);
100
- const isBinaryBody = Buffer.isBuffer(req.body) || (contentType !== undefined && !isJsonContentType);
101
- logger.error(error, {
102
- path: req.path,
103
- method: req.method,
104
- query: req.query,
105
- ...(isBinaryBody
106
- ? {
107
- bodyContentType: contentType,
108
- bodyLength: Buffer.isBuffer(req.body)
109
- ? req.body.length
110
- : typeof req.body === "string"
111
- ? Buffer.byteLength(req.body)
112
- : undefined,
113
- }
114
- : { body: req.body }),
115
- });
116
- }
117
- }
118
- }
119
- let problemDetails;
120
- const formatter = formatters.find((f) => f.canFormat(error));
121
- if (formatter) {
122
- problemDetails = formatter.format(error);
123
- }
124
- else {
125
- problemDetails = createExtendedProblemDetails({
126
- type: "error:internal",
127
- title: "Internal Server Error",
128
- status: 500,
129
- detail: "An unexpected error occurred",
130
- });
133
+ logHandledError(error, req, options);
131
134
  }
135
+ const problemDetails = buildProblemDetails(error, formatters);
132
136
  if (error.stack) {
133
137
  problemDetails.stack = error.stack.split("\n").map((line) => line.trim());
134
138
  }
@@ -136,7 +140,7 @@ export function errorHandler(options = {}) {
136
140
  problemDetails.instance = req.path;
137
141
  }
138
142
  res
139
- .status(problemDetails.status || 500)
143
+ .status(problemDetails.status || HttpStatus.INTERNAL_SERVER_ERROR)
140
144
  .set("Content-Type", PROBLEM_DETAILS_CONTENT_TYPE)
141
145
  .json(problemDetails);
142
146
  };
@@ -1 +1 @@
1
- {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../src/error-handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../src/error-handler.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -5,6 +5,11 @@ let _batkit_rfc9457 = require("@batkit/rfc9457");
5
5
  let _batkit_logger_async_local = require("@batkit/logger/async-local");
6
6
  //#region src/error-handler.ts
7
7
  const logger = _batkit_logger.LoggerFacade.getLogger("error-handler");
8
+ const HttpStatus = {
9
+ BAD_GATEWAY: 502,
10
+ INTERNAL_SERVER_ERROR: 500,
11
+ UNPROCESSABLE_ENTITY: 422
12
+ };
8
13
  /**
9
14
  * Default error formatter that handles common error types
10
15
  */
@@ -17,16 +22,16 @@ var DefaultErrorFormatter = class {
17
22
  if (this.isAxiosError(error)) return this.formatAxiosError(error);
18
23
  if (this.isZodError(error)) return this.formatZodError(error);
19
24
  if (error instanceof Error) return (0, _batkit_rfc9457.createExtendedProblemDetails)({
20
- type: "error:internal",
25
+ detail: error.message,
26
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
21
27
  title: "Internal Server Error",
22
- status: 500,
23
- detail: error.message
28
+ type: "error:internal"
24
29
  });
25
30
  return (0, _batkit_rfc9457.createExtendedProblemDetails)({
26
- type: "error:unknown",
31
+ detail: "An unknown error occurred",
32
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
27
33
  title: "Unknown Error",
28
- status: 500,
29
- detail: "An unknown error occurred"
34
+ type: "error:unknown"
30
35
  });
31
36
  }
32
37
  isAxiosError(error) {
@@ -36,30 +41,73 @@ var DefaultErrorFormatter = class {
36
41
  return typeof error === "object" && error !== null && "issues" in error && Array.isArray(error.issues);
37
42
  }
38
43
  formatAxiosError(error) {
44
+ const status = error.response?.status || HttpStatus.BAD_GATEWAY;
39
45
  return (0, _batkit_rfc9457.createExtendedProblemDetails)({
40
- type: "error:upstream",
41
- title: "Upstream Service Error",
42
- status: error.response?.status || 502,
43
46
  detail: error.message,
44
- upstreamUrl: error.config?.url,
47
+ status,
48
+ title: "Upstream Service Error",
49
+ type: "error:upstream",
45
50
  upstreamMethod: (error.config?.method)?.toUpperCase(),
46
- upstreamStatus: error.response?.status
51
+ upstreamStatus: error.response?.status,
52
+ upstreamUrl: error.config?.url
47
53
  });
48
54
  }
49
55
  formatZodError(error) {
56
+ const validationErrors = error.issues.map((issue) => ({
57
+ code: issue.code,
58
+ field: issue.path.join("."),
59
+ message: issue.message
60
+ }));
50
61
  return (0, _batkit_rfc9457.createExtendedProblemDetails)({
51
- type: "error:validation",
52
- title: "Validation Error",
53
- status: 422,
54
62
  detail: "Request validation failed",
55
- validationErrors: error.issues.map((issue) => ({
56
- field: issue.path.join("."),
57
- message: issue.message,
58
- code: issue.code
59
- }))
63
+ status: HttpStatus.UNPROCESSABLE_ENTITY,
64
+ title: "Validation Error",
65
+ type: "error:validation",
66
+ validationErrors
60
67
  });
61
68
  }
62
69
  };
70
+ function logHandledError(error, req, options) {
71
+ const { onError } = options;
72
+ if (onError) {
73
+ onError(error, req);
74
+ return;
75
+ }
76
+ if ((0, _batkit_errors.isAppError)(error) && error.isOperational) {
77
+ logger.warn("Operational error occurred", {
78
+ code: error.code,
79
+ error: error.message,
80
+ method: req.method,
81
+ path: req.path,
82
+ statusCode: error.statusCode
83
+ });
84
+ return;
85
+ }
86
+ const contentType = req.headers?.["content-type"];
87
+ const isJsonContentType = typeof contentType === "string" && /^application\/(?:[^;]+\+)?json/iu.test(contentType);
88
+ const isBinaryBody = Buffer.isBuffer(req.body) || contentType !== void 0 && !isJsonContentType;
89
+ let bodyLength;
90
+ if (Buffer.isBuffer(req.body)) bodyLength = req.body.length;
91
+ else if (typeof req.body === "string") bodyLength = Buffer.byteLength(req.body);
92
+ logger.error(error, {
93
+ method: req.method,
94
+ path: req.path,
95
+ query: req.query,
96
+ ...isBinaryBody ? {
97
+ bodyContentType: contentType,
98
+ bodyLength
99
+ } : { body: req.body }
100
+ });
101
+ }
102
+ function buildProblemDetails(error, formatters) {
103
+ const formatter = formatters.find((candidate) => candidate.canFormat(error));
104
+ return formatter ? formatter.format(error) : (0, _batkit_rfc9457.createExtendedProblemDetails)({
105
+ detail: "An unexpected error occurred",
106
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
107
+ title: "Internal Server Error",
108
+ type: "error:internal"
109
+ });
110
+ }
63
111
  /**
64
112
  * Express error handling middleware that converts errors to RFC 9457 format
65
113
  *
@@ -83,46 +131,17 @@ var DefaultErrorFormatter = class {
83
131
  * ```
84
132
  */
85
133
  function errorHandler(options = {}) {
86
- const { formatters = [new DefaultErrorFormatter()], logErrors = true, onError } = options;
134
+ const { formatters = [new DefaultErrorFormatter()], logErrors = true } = options;
87
135
  return (error, req, res, next) => {
88
136
  if (res.headersSent) {
89
137
  next(error);
90
138
  return;
91
139
  }
92
- if (logErrors) if (onError) onError(error, req);
93
- else if ((0, _batkit_errors.isAppError)(error) && error.isOperational) logger.warn("Operational error occurred", {
94
- error: error.message,
95
- code: error.code,
96
- statusCode: error.statusCode,
97
- path: req.path,
98
- method: req.method
99
- });
100
- else {
101
- const contentType = req.headers?.["content-type"];
102
- const isJsonContentType = typeof contentType === "string" && /^application\/(?:[^;]+\+)?json/i.test(contentType);
103
- const isBinaryBody = Buffer.isBuffer(req.body) || contentType !== void 0 && !isJsonContentType;
104
- logger.error(error, {
105
- path: req.path,
106
- method: req.method,
107
- query: req.query,
108
- ...isBinaryBody ? {
109
- bodyContentType: contentType,
110
- bodyLength: Buffer.isBuffer(req.body) ? req.body.length : typeof req.body === "string" ? Buffer.byteLength(req.body) : void 0
111
- } : { body: req.body }
112
- });
113
- }
114
- let problemDetails;
115
- const formatter = formatters.find((f) => f.canFormat(error));
116
- if (formatter) problemDetails = formatter.format(error);
117
- else problemDetails = (0, _batkit_rfc9457.createExtendedProblemDetails)({
118
- type: "error:internal",
119
- title: "Internal Server Error",
120
- status: 500,
121
- detail: "An unexpected error occurred"
122
- });
140
+ if (logErrors) logHandledError(error, req, options);
141
+ const problemDetails = buildProblemDetails(error, formatters);
123
142
  if (error.stack) problemDetails.stack = error.stack.split("\n").map((line) => line.trim());
124
143
  if (!problemDetails.instance) problemDetails.instance = req.path;
125
- res.status(problemDetails.status || 500).set("Content-Type", _batkit_rfc9457.PROBLEM_DETAILS_CONTENT_TYPE).json(problemDetails);
144
+ res.status(problemDetails.status || HttpStatus.INTERNAL_SERVER_ERROR).set("Content-Type", _batkit_rfc9457.PROBLEM_DETAILS_CONTENT_TYPE).json(problemDetails);
126
145
  };
127
146
  }
128
147
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["LoggerFacade","PROBLEM_DETAILS_CONTENT_TYPE"],"sources":["../src/error-handler.ts","../src/log-context-middleware.ts"],"sourcesContent":["import { isAppError } from \"@batkit/errors\";\nimport { LoggerFacade } from \"@batkit/logger\";\nimport {\n type ExtendedProblemDetails,\n PROBLEM_DETAILS_CONTENT_TYPE,\n createExtendedProblemDetails,\n} from \"@batkit/rfc9457\";\nimport type { NextFunction, Request, Response } from \"express\";\n\nconst logger = LoggerFacade.getLogger(\"error-handler\");\n/**\n * Interface for custom error formatters\n */\nexport interface ErrorFormatter {\n /**\n * Check if this formatter can handle the error\n */\n canFormat(error: unknown): boolean;\n\n /**\n * Format the error as RFC 9457 Problem Details\n */\n format(error: unknown): ExtendedProblemDetails;\n}\n\n/**\n * Default error formatter that handles common error types\n */\nexport class DefaultErrorFormatter implements ErrorFormatter {\n canFormat(error: unknown): boolean {\n return (\n isAppError(error) ||\n error instanceof Error ||\n this.isAxiosError(error) ||\n this.isZodError(error)\n );\n }\n\n format(error: unknown): ExtendedProblemDetails {\n // Handle AppError (from @batkit/errors)\n if (isAppError(error)) {\n return error.toRFC9457();\n }\n\n // Handle Axios errors\n if (this.isAxiosError(error)) {\n return this.formatAxiosError(error as Record<string, unknown>);\n }\n\n // Handle Zod validation errors\n if (this.isZodError(error)) {\n return this.formatZodError(error as Record<string, unknown>);\n }\n\n // Handle generic Error\n if (error instanceof Error) {\n return createExtendedProblemDetails({\n type: \"error:internal\",\n title: \"Internal Server Error\",\n status: 500,\n detail: error.message,\n });\n }\n\n // Unknown error type\n return createExtendedProblemDetails({\n type: \"error:unknown\",\n title: \"Unknown Error\",\n status: 500,\n detail: \"An unknown error occurred\",\n });\n }\n\n private isAxiosError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"isAxiosError\" in error &&\n error.isAxiosError === true\n );\n }\n\n private isZodError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"issues\" in error &&\n Array.isArray((error as Record<string, unknown>).issues)\n );\n }\n\n private formatAxiosError(error: Record<string, unknown>): ExtendedProblemDetails {\n const status = ((error.response as Record<string, unknown>)?.status as number) || 502;\n return createExtendedProblemDetails({\n type: \"error:upstream\",\n title: \"Upstream Service Error\",\n status,\n detail: error.message as string,\n upstreamUrl: (error.config as Record<string, unknown>)?.url as string | undefined,\n upstreamMethod: ((error.config as Record<string, unknown>)?.method as string)?.toUpperCase(),\n upstreamStatus: (error.response as Record<string, unknown>)?.status as number | undefined,\n });\n }\n\n private formatZodError(error: Record<string, unknown>): ExtendedProblemDetails {\n const validationErrors = (error.issues as Array<Record<string, unknown>>).map((issue) => ({\n field: (issue.path as unknown[]).join(\".\"),\n message: issue.message as string,\n code: issue.code as string,\n }));\n\n return createExtendedProblemDetails({\n type: \"error:validation\",\n title: \"Validation Error\",\n status: 422,\n detail: \"Request validation failed\",\n validationErrors,\n });\n }\n}\n\n/**\n * Options for error handler middleware\n */\nexport interface ErrorHandlerOptions {\n /**\n * Custom error formatters (in order of precedence)\n */\n formatters?: ErrorFormatter[];\n\n /**\n * Whether to log errors (default: true)\n */\n logErrors?: boolean;\n\n /**\n * Custom error logger function\n */\n onError?: (error: unknown, req: Request) => void;\n}\n\n/**\n * Express error handling middleware that converts errors to RFC 9457 format\n *\n * @param options - Configuration options\n * @returns Express error middleware function\n *\n * @example\n * ```ts\n * import { errorHandler } from '@batkit/express-middleware';\n * import { NotFoundError } from '@batkit/errors';\n * import express from 'express';\n *\n * const app = express();\n *\n * app.get('/users/:id', (req, res) => {\n * throw new NotFoundError('User', req.params.id);\n * });\n *\n * // Must be added AFTER all routes\n * app.use(errorHandler());\n * ```\n */\nexport function errorHandler(\n options: ErrorHandlerOptions = {},\n): (error: Error, req: Request, res: Response, next: NextFunction) => void {\n const { formatters = [new DefaultErrorFormatter()], logErrors = true, onError } = options;\n\n return (error: Error, req: Request, res: Response, next: NextFunction): void => {\n // If headers already sent, delegate to default Express error handler\n if (res.headersSent) {\n next(error);\n return;\n }\n\n // Log the error\n if (logErrors) {\n if (onError) {\n onError(error, req);\n } else {\n if (isAppError(error) && error.isOperational) {\n logger.warn(\"Operational error occurred\", {\n error: error.message,\n code: error.code,\n statusCode: error.statusCode,\n path: req.path,\n method: req.method,\n });\n } else {\n const contentType = req.headers?.[\"content-type\"];\n const isJsonContentType =\n typeof contentType === \"string\" && /^application\\/(?:[^;]+\\+)?json/i.test(contentType);\n const isBinaryBody =\n Buffer.isBuffer(req.body) || (contentType !== undefined && !isJsonContentType);\n\n logger.error(error, {\n path: req.path,\n method: req.method,\n query: req.query,\n ...(isBinaryBody\n ? {\n bodyContentType: contentType,\n bodyLength: Buffer.isBuffer(req.body)\n ? req.body.length\n : typeof req.body === \"string\"\n ? Buffer.byteLength(req.body)\n : undefined,\n }\n : { body: req.body }),\n });\n }\n }\n }\n\n // Format the error\n let problemDetails: ExtendedProblemDetails;\n\n const formatter = formatters.find((f) => f.canFormat(error));\n if (formatter) {\n problemDetails = formatter.format(error);\n } else {\n // Fallback to generic error\n problemDetails = createExtendedProblemDetails({\n type: \"error:internal\",\n title: \"Internal Server Error\",\n status: 500,\n detail: \"An unexpected error occurred\",\n });\n }\n\n // Add stack trace\n if (error.stack) {\n problemDetails.stack = error.stack.split(\"\\n\").map((line) => line.trim());\n }\n\n // Add instance (request path)\n if (!problemDetails.instance) {\n problemDetails.instance = req.path;\n }\n\n // Send RFC 9457 response\n res\n .status(problemDetails.status || 500)\n .set(\"Content-Type\", PROBLEM_DETAILS_CONTENT_TYPE)\n .json(problemDetails);\n };\n}\n\n/**\n * Express middleware to catch async errors\n * Wraps async route handlers to ensure errors are passed to error middleware\n *\n * @param fn - Async route handler\n * @returns Wrapped route handler\n *\n * @example\n * ```ts\n * import { asyncHandler } from '@batkit/express-middleware';\n *\n * app.get('/users/:id', asyncHandler(async (req, res) => {\n * const user = await db.users.findById(req.params.id);\n * if (!user) {\n * throw new NotFoundError('User', req.params.id);\n * }\n * res.json(user);\n * }));\n * ```\n */\nexport function asyncHandler(\n fn: (req: Request, res: Response, next: NextFunction) => Promise<unknown>,\n): (req: Request, res: Response, next: NextFunction) => void {\n return (req: Request, res: Response, next: NextFunction): void => {\n Promise.resolve(fn(req, res, next)).catch(next);\n };\n}\n","import type { LogValue } from \"@batkit/logger\";\nimport { runWithContext } from \"@batkit/logger/async-local\";\nimport type { NextFunction, Request, Response } from \"express\";\n\nexport type LogContextInitializer = (req: Request) => Record<string, LogValue>;\n\nexport interface LogContextMiddlewareOptions {\n /**\n * Build initial async-local log fields for this HTTP request.\n * @default () => ({})\n */\n initialContext?: LogContextInitializer;\n}\n\n/**\n * Runs each request inside {@link runWithContext} so later code can use\n * {@link mergeLogContext} and a {@link ContextualLoggerProvider} without\n * depending on Express (`req`) deep in the stack.\n *\n * Mount this **early** in the middleware chain. Use synchronous `next()` inside\n * the callback; avoid `async` middleware that calls `next` after an `await`\n * without keeping the rest of the work in the same async context.\n */\nexport function logContextMiddleware(\n options: LogContextMiddlewareOptions = {},\n): (req: Request, res: Response, next: NextFunction) => void {\n const initialContext = options.initialContext ?? (() => ({}));\n\n return (req: Request, _res: Response, next: NextFunction) => {\n runWithContext(initialContext(req), () => next());\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["LoggerFacade","PROBLEM_DETAILS_CONTENT_TYPE"],"sources":["../src/error-handler.ts","../src/log-context-middleware.ts"],"sourcesContent":["import { isAppError } from \"@batkit/errors\";\nimport { LoggerFacade } from \"@batkit/logger\";\nimport {\n type ExtendedProblemDetails,\n PROBLEM_DETAILS_CONTENT_TYPE,\n createExtendedProblemDetails,\n} from \"@batkit/rfc9457\";\nimport type { NextFunction, Request, Response } from \"express\";\n\nconst logger = LoggerFacade.getLogger(\"error-handler\");\n\nconst HttpStatus = {\n BAD_GATEWAY: 502,\n INTERNAL_SERVER_ERROR: 500,\n UNPROCESSABLE_ENTITY: 422,\n} as const;\n/**\n * Interface for custom error formatters\n */\nexport interface ErrorFormatter {\n /**\n * Check if this formatter can handle the error\n */\n canFormat(error: unknown): boolean;\n\n /**\n * Format the error as RFC 9457 Problem Details\n */\n format(error: unknown): ExtendedProblemDetails;\n}\n\n/**\n * Default error formatter that handles common error types\n */\nexport class DefaultErrorFormatter implements ErrorFormatter {\n canFormat(error: unknown): boolean {\n return (\n isAppError(error) ||\n error instanceof Error ||\n this.isAxiosError(error) ||\n this.isZodError(error)\n );\n }\n\n format(error: unknown): ExtendedProblemDetails {\n // Handle AppError (from @batkit/errors)\n if (isAppError(error)) {\n return error.toRFC9457();\n }\n\n // Handle Axios errors\n if (this.isAxiosError(error)) {\n return this.formatAxiosError(error as Record<string, unknown>);\n }\n\n // Handle Zod validation errors\n if (this.isZodError(error)) {\n return this.formatZodError(error as Record<string, unknown>);\n }\n\n // Handle generic Error\n if (error instanceof Error) {\n return createExtendedProblemDetails({\n detail: error.message,\n status: HttpStatus.INTERNAL_SERVER_ERROR,\n title: \"Internal Server Error\",\n type: \"error:internal\",\n });\n }\n\n // Unknown error type\n return createExtendedProblemDetails({\n detail: \"An unknown error occurred\",\n status: HttpStatus.INTERNAL_SERVER_ERROR,\n title: \"Unknown Error\",\n type: \"error:unknown\",\n });\n }\n\n private isAxiosError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"isAxiosError\" in error &&\n error.isAxiosError === true\n );\n }\n\n private isZodError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"issues\" in error &&\n Array.isArray((error as Record<string, unknown>).issues)\n );\n }\n\n private formatAxiosError(error: Record<string, unknown>): ExtendedProblemDetails {\n const status =\n ((error.response as Record<string, unknown>)?.status as number) || HttpStatus.BAD_GATEWAY;\n return createExtendedProblemDetails({\n detail: error.message as string,\n status,\n title: \"Upstream Service Error\",\n type: \"error:upstream\",\n upstreamMethod: ((error.config as Record<string, unknown>)?.method as string)?.toUpperCase(),\n upstreamStatus: (error.response as Record<string, unknown>)?.status as number | undefined,\n upstreamUrl: (error.config as Record<string, unknown>)?.url as string | undefined,\n });\n }\n\n private formatZodError(error: Record<string, unknown>): ExtendedProblemDetails {\n const validationErrors = (error.issues as Record<string, unknown>[]).map((issue) => ({\n code: issue.code as string,\n field: (issue.path as unknown[]).join(\".\"),\n message: issue.message as string,\n }));\n\n return createExtendedProblemDetails({\n detail: \"Request validation failed\",\n status: HttpStatus.UNPROCESSABLE_ENTITY,\n title: \"Validation Error\",\n type: \"error:validation\",\n validationErrors,\n });\n }\n}\n\n/**\n * Options for error handler middleware\n */\nexport interface ErrorHandlerOptions {\n /**\n * Custom error formatters (in order of precedence)\n */\n formatters?: ErrorFormatter[];\n\n /**\n * Whether to log errors (default: true)\n */\n logErrors?: boolean;\n\n /**\n * Custom error logger function\n */\n onError?: (error: unknown, req: Request) => void;\n}\n\nfunction logHandledError(error: Error, req: Request, options: ErrorHandlerOptions): void {\n const { onError } = options;\n if (onError) {\n onError(error, req);\n return;\n }\n\n if (isAppError(error) && error.isOperational) {\n logger.warn(\"Operational error occurred\", {\n code: error.code,\n error: error.message,\n method: req.method,\n path: req.path,\n statusCode: error.statusCode,\n });\n return;\n }\n\n const contentType = req.headers?.[\"content-type\"];\n const isJsonContentType =\n typeof contentType === \"string\" && /^application\\/(?:[^;]+\\+)?json/iu.test(contentType);\n const isBinaryBody =\n Buffer.isBuffer(req.body) || (contentType !== undefined && !isJsonContentType);\n\n let bodyLength: number | undefined;\n if (Buffer.isBuffer(req.body)) {\n bodyLength = req.body.length;\n } else if (typeof req.body === \"string\") {\n bodyLength = Buffer.byteLength(req.body);\n }\n\n logger.error(error, {\n method: req.method,\n path: req.path,\n query: req.query,\n ...(isBinaryBody ? { bodyContentType: contentType, bodyLength } : { body: req.body }),\n });\n}\n\nfunction buildProblemDetails(error: Error, formatters: ErrorFormatter[]): ExtendedProblemDetails {\n const formatter = formatters.find((candidate) => candidate.canFormat(error));\n return formatter\n ? formatter.format(error)\n : createExtendedProblemDetails({\n detail: \"An unexpected error occurred\",\n status: HttpStatus.INTERNAL_SERVER_ERROR,\n title: \"Internal Server Error\",\n type: \"error:internal\",\n });\n}\n\n/**\n * Express error handling middleware that converts errors to RFC 9457 format\n *\n * @param options - Configuration options\n * @returns Express error middleware function\n *\n * @example\n * ```ts\n * import { errorHandler } from '@batkit/express-middleware';\n * import { NotFoundError } from '@batkit/errors';\n * import express from 'express';\n *\n * const app = express();\n *\n * app.get('/users/:id', (req, res) => {\n * throw new NotFoundError('User', req.params.id);\n * });\n *\n * // Must be added AFTER all routes\n * app.use(errorHandler());\n * ```\n */\nexport function errorHandler(\n options: ErrorHandlerOptions = {},\n // oxlint-disable-next-line max-params -- Express detects error-handling middleware by function arity; this signature must stay exactly (error, req, res, next).\n): (error: Error, req: Request, res: Response, next: NextFunction) => void {\n const { formatters = [new DefaultErrorFormatter()], logErrors = true } = options;\n\n // oxlint-disable-next-line max-params -- see above, Express requires this exact arity.\n return (error: Error, req: Request, res: Response, next: NextFunction): void => {\n // If headers already sent, delegate to default Express error handler\n if (res.headersSent) {\n next(error);\n return;\n }\n\n if (logErrors) {\n logHandledError(error, req, options);\n }\n\n const problemDetails = buildProblemDetails(error, formatters);\n\n // Add stack trace\n if (error.stack) {\n problemDetails.stack = error.stack.split(\"\\n\").map((line) => line.trim());\n }\n\n // Add instance (request path)\n if (!problemDetails.instance) {\n problemDetails.instance = req.path;\n }\n\n // Send RFC 9457 response\n res\n .status(problemDetails.status || HttpStatus.INTERNAL_SERVER_ERROR)\n .set(\"Content-Type\", PROBLEM_DETAILS_CONTENT_TYPE)\n .json(problemDetails);\n };\n}\n\n/**\n * Express middleware to catch async errors\n * Wraps async route handlers to ensure errors are passed to error middleware\n *\n * @param fn - Async route handler\n * @returns Wrapped route handler\n *\n * @example\n * ```ts\n * import { asyncHandler } from '@batkit/express-middleware';\n *\n * app.get('/users/:id', asyncHandler(async (req, res) => {\n * const user = await db.users.findById(req.params.id);\n * if (!user) {\n * throw new NotFoundError('User', req.params.id);\n * }\n * res.json(user);\n * }));\n * ```\n */\nexport function asyncHandler(\n fn: (req: Request, res: Response, next: NextFunction) => Promise<unknown>,\n): (req: Request, res: Response, next: NextFunction) => void {\n return (req: Request, res: Response, next: NextFunction): void => {\n Promise.resolve(fn(req, res, next)).catch(next);\n };\n}\n","import type { LogValue } from \"@batkit/logger\";\nimport { runWithContext } from \"@batkit/logger/async-local\";\nimport type { NextFunction, Request, Response } from \"express\";\n\nexport type LogContextInitializer = (req: Request) => Record<string, LogValue>;\n\nexport interface LogContextMiddlewareOptions {\n /**\n * Build initial async-local log fields for this HTTP request.\n * @default () => ({})\n */\n initialContext?: LogContextInitializer;\n}\n\n/**\n * Runs each request inside {@link runWithContext} so later code can use\n * {@link mergeLogContext} and a {@link ContextualLoggerProvider} without\n * depending on Express (`req`) deep in the stack.\n *\n * Mount this **early** in the middleware chain. Use synchronous `next()` inside\n * the callback; avoid `async` middleware that calls `next` after an `await`\n * without keeping the rest of the work in the same async context.\n */\nexport function logContextMiddleware(\n options: LogContextMiddlewareOptions = {},\n): (req: Request, res: Response, next: NextFunction) => void {\n const initialContext = options.initialContext ?? (() => ({}));\n\n return (req: Request, _res: Response, next: NextFunction) => {\n runWithContext(initialContext(req), () => next());\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/error-handler.ts","../src/log-context-middleware.ts"],"mappings":";;;;;UAaiB,cAAA;EAIf,SAAA,CAAU,KAAA;EAKV,MAAA,CAAO,KAAA,YAAiB,sBAAsB;AAAA;AAAA,cAMnC,qBAAA,YAAiC,cAAc;EAC1D,SAAA,CAAU,KAAA;EASV,MAAA,CAAO,KAAA,YAAiB,sBAAA;EAAA,QAmChB,YAAA;EAAA,QASA,UAAA;EAAA,QASA,gBAAA;EAAA,QAaA,cAAA;AAAA;AAAA,UAoBO,mBAAA;EAIf,UAAA,GAAa,cAAA;EAKb,SAAA;EAKA,OAAA,IAAW,KAAA,WAAgB,GAAA,EAAK,OAAO;AAAA;AAAA,iBAyBzB,YAAA,CACd,OAAA,GAAS,mBAAA,IACP,KAAA,EAAO,KAAA,EAAO,GAAA,EAAK,OAAA,EAAS,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,YAAA;AAAA,iBAuGrC,YAAA,CACd,EAAA,GAAK,GAAA,EAAK,OAAA,EAAS,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,YAAA,KAAiB,OAAA,aACvD,GAAA,EAAK,OAAA,EAAS,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,YAAA;;;KC1Q3B,qBAAA,IAAyB,GAAA,EAAK,OAAA,KAAY,MAAA,SAAe,QAAA;AAAA,UAEpD,2BAAA;EAKf,cAAA,GAAiB,qBAAqB;AAAA;AAAA,iBAYxB,oBAAA,CACd,OAAA,GAAS,2BAAA,IACP,GAAA,EAAK,OAAA,EAAS,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,YAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/error-handler.ts","../src/log-context-middleware.ts"],"mappings":";;;;;UAmBiB,cAAA;EAIf,SAAA,CAAU,KAAA;EAKV,MAAA,CAAO,KAAA,YAAiB,sBAAsB;AAAA;AAAA,cAMnC,qBAAA,YAAiC,cAAc;EAC1D,SAAA,CAAU,KAAA;EASV,MAAA,CAAO,KAAA,YAAiB,sBAAA;EAAA,QAmChB,YAAA;EAAA,QASA,UAAA;EAAA,QASA,gBAAA;EAAA,QAcA,cAAA;AAAA;AAAA,UAoBO,mBAAA;EAIf,UAAA,GAAa,cAAA;EAKb,SAAA;EAKA,OAAA,IAAW,KAAA,WAAgB,GAAA,EAAK,OAAO;AAAA;AAAA,iBA4EzB,YAAA,CACd,OAAA,GAAS,mBAAA,IAEP,KAAA,EAAO,KAAA,EAAO,GAAA,EAAK,OAAA,EAAS,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,YAAA;AAAA,iBAuDrC,YAAA,CACd,EAAA,GAAK,GAAA,EAAK,OAAA,EAAS,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,YAAA,KAAiB,OAAA,aACvD,GAAA,EAAK,OAAA,EAAS,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,YAAA;;;KCrR3B,qBAAA,IAAyB,GAAA,EAAK,OAAA,KAAY,MAAA,SAAe,QAAA;AAAA,UAEpD,2BAAA;EAKf,cAAA,GAAiB,qBAAqB;AAAA;AAAA,iBAYxB,oBAAA,CACd,OAAA,GAAS,2BAAA,IACP,GAAA,EAAK,OAAA,EAAS,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,YAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@batkit/express-middleware",
3
- "version": "0.1.4",
3
+ "version": "1.0.0",
4
4
  "description": "Express middleware for error handling and request context (Node.js only)",
5
5
  "keywords": [
6
6
  "error-handling",
@@ -46,9 +46,9 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@batkit/errors": "0.1.2",
50
- "@batkit/rfc9457": "0.1.1",
51
- "@batkit/logger": "0.1.1"
49
+ "@batkit/errors": "1.0.0",
50
+ "@batkit/logger": "1.0.0",
51
+ "@batkit/rfc9457": "1.0.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@total-typescript/shoehorn": "^0.1.2",