90dc-core 1.11.1 → 1.11.2
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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/middlewares/ErrorMiddleware.d.ts +3 -4
- package/dist/lib/middlewares/ErrorMiddleware.d.ts.map +1 -1
- package/dist/lib/middlewares/ErrorMiddleware.js +18 -29
- package/dist/lib/middlewares/ErrorMiddleware.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,6 @@ export { NotificationClient } from "./lib/utils/NotificationClient.js";
|
|
|
26
26
|
export { Log } from "./lib/utils/Logger.js";
|
|
27
27
|
export { ConfigValidator, BaseConfigSchema, CommonSchemas, createConfig, ConfigurationError, type BaseConfig } from "./lib/config/ConfigValidator.js";
|
|
28
28
|
export { AppError, ValidationError, AuthenticationError, ForbiddenError, NotFoundError, ConflictError, UnprocessableEntityError, RateLimitError, InternalServerError, ServiceUnavailableError, DatabaseError, ExternalAPIError, isAppError, isOperationalError, toAppError } from "./lib/Errors/AppError.js";
|
|
29
|
-
export {
|
|
29
|
+
export { ErrorMiddleware, } from "./lib/middlewares/ErrorMiddleware.js";
|
|
30
30
|
export { RedisClient } from "./lib/classes/Redis.js";
|
|
31
31
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wCAAwC,CAAC;AAGvD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,yBAAyB,CAAA;AACvC,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,oCAAoC,CAAA;AAClD,cAAc,0CAA0C,CAAA;AACxD,cAAc,oCAAoC,CAAA;AAClD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,mCAAmC,CAAA;AACjD,cAAc,uDAAuD,CAAA;AACrE,cAAc,2EAA2E,CAAA;AACzF,cAAc,8DAA8D,CAAA;AAC5E,cAAc,iEAAiE,CAAA;AAC/E,cAAc,2DAA2D,CAAA;AAGzE,OAAO,EAAC,kBAAkB,EAAC,MAAM,mCAAmC,CAAA;AACpE,OAAO,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAA;AAClE,OAAO,EAAC,kBAAkB,EAAC,MAAM,mCAAmC,CAAA;AACpE,OAAO,EAAC,GAAG,EAAC,MAAM,uBAAuB,CAAA;AAGzC,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,KAAK,UAAU,EAChB,MAAM,iCAAiC,CAAA;AAGxC,OAAO,EACL,QAAQ,EACR,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,aAAa,EACb,wBAAwB,EACxB,cAAc,EACd,mBAAmB,EACnB,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,UAAU,EACX,MAAM,0BAA0B,CAAA;AAGjC,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wCAAwC,CAAC;AAGvD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,yBAAyB,CAAA;AACvC,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,oCAAoC,CAAA;AAClD,cAAc,0CAA0C,CAAA;AACxD,cAAc,oCAAoC,CAAA;AAClD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,mCAAmC,CAAA;AACjD,cAAc,uDAAuD,CAAA;AACrE,cAAc,2EAA2E,CAAA;AACzF,cAAc,8DAA8D,CAAA;AAC5E,cAAc,iEAAiE,CAAA;AAC/E,cAAc,2DAA2D,CAAA;AAGzE,OAAO,EAAC,kBAAkB,EAAC,MAAM,mCAAmC,CAAA;AACpE,OAAO,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAA;AAClE,OAAO,EAAC,kBAAkB,EAAC,MAAM,mCAAmC,CAAA;AACpE,OAAO,EAAC,GAAG,EAAC,MAAM,uBAAuB,CAAA;AAGzC,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,KAAK,UAAU,EAChB,MAAM,iCAAiC,CAAA;AAGxC,OAAO,EACL,QAAQ,EACR,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,aAAa,EACb,wBAAwB,EACxB,cAAc,EACd,mBAAmB,EACnB,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,UAAU,EACX,MAAM,0BAA0B,CAAA;AAGjC,OAAO,EACL,eAAe,GAChB,MAAM,sCAAsC,CAAA;AAG7C,OAAO,EAAC,WAAW,EAAC,MAAM,wBAAwB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ export { ConfigValidator, BaseConfigSchema, CommonSchemas, createConfig, Configu
|
|
|
32
32
|
//Errors
|
|
33
33
|
export { AppError, ValidationError, AuthenticationError, ForbiddenError, NotFoundError, ConflictError, UnprocessableEntityError, RateLimitError, InternalServerError, ServiceUnavailableError, DatabaseError, ExternalAPIError, isAppError, isOperationalError, toAppError } from "./lib/Errors/AppError.js";
|
|
34
34
|
//Middlewares
|
|
35
|
-
export {
|
|
35
|
+
export { ErrorMiddleware } from "./lib/middlewares/ErrorMiddleware.js";
|
|
36
36
|
export { RedisClient } from "./lib/classes/Redis.js";
|
|
37
37
|
|
|
38
38
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["//Interfaces\nexport * from \"./lib/models/ProgramInterfaces.js\";\nexport * from \"./lib/models/ExerciseInterfaces.js\";\nexport * from \"./lib/models/WorkoutInterfaces.js\";\nexport * from \"./lib/models/UserInterfaces.js\";\nexport * from \"./lib/models/NotificationInterfaces.js\";\n\n//DB Models\nexport * from \"./lib/dbmodels/UsersFriends.js\"\nexport * from \"./lib/dbmodels/PersistedUser.js\"\nexport * from \"./lib/dbmodels/UserBadges.js\"\nexport * from \"./lib/dbmodels/UserStreaks.js\"\nexport * from \"./lib/dbmodels/Badge.js\"\nexport * from \"./lib/dbmodels/program/Program.js\"\nexport * from \"./lib/dbmodels/program/Workout.js\"\nexport * from \"./lib/dbmodels/program/Exercise.js\"\nexport * from \"./lib/dbmodels/program/ExerciseModels.js\"\nexport * from \"./lib/dbmodels/program/Superset.js\"\nexport * from \"./lib/dbmodels/Subscription.js\"\nexport * from \"./lib/dbmodels/SubscriptionLog.js\"\nexport * from \"./lib/dbmodels/nonconsprogram/NonConsumableProgram.js\"\nexport * from \"./lib/dbmodels/nonconsprogram/TranslatedNonConsumableProgramWebContent.js\"\nexport * from \"./lib/dbmodels/nonconsprogram/TranslatedConsumableProgram.js\"\nexport * from \"./lib/dbmodels/nonconsprogram/NonConsumableProgramWebContent.js\"\nexport * from \"./lib/dbmodels/nonconsprogram/UserNonConsumableProgram.js\"\n\n//Utils\nexport {AuthenticationUtil} from \"./lib/utils/AuthenticationUtil.js\"\nexport {NotificationsUtil} from \"./lib/utils/NotificationsUtil.js\"\nexport {NotificationClient} from \"./lib/utils/NotificationClient.js\"\nexport {Log} from \"./lib/utils/Logger.js\"\n\n//Config\nexport {\n ConfigValidator,\n BaseConfigSchema,\n CommonSchemas,\n createConfig,\n ConfigurationError,\n type BaseConfig\n} from \"./lib/config/ConfigValidator.js\"\n\n//Errors\nexport {\n AppError,\n ValidationError,\n AuthenticationError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n UnprocessableEntityError,\n RateLimitError,\n InternalServerError,\n ServiceUnavailableError,\n DatabaseError,\n ExternalAPIError,\n isAppError,\n isOperationalError,\n toAppError\n} from \"./lib/Errors/AppError.js\"\n\n//Middlewares\nexport {\n
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["//Interfaces\nexport * from \"./lib/models/ProgramInterfaces.js\";\nexport * from \"./lib/models/ExerciseInterfaces.js\";\nexport * from \"./lib/models/WorkoutInterfaces.js\";\nexport * from \"./lib/models/UserInterfaces.js\";\nexport * from \"./lib/models/NotificationInterfaces.js\";\n\n//DB Models\nexport * from \"./lib/dbmodels/UsersFriends.js\"\nexport * from \"./lib/dbmodels/PersistedUser.js\"\nexport * from \"./lib/dbmodels/UserBadges.js\"\nexport * from \"./lib/dbmodels/UserStreaks.js\"\nexport * from \"./lib/dbmodels/Badge.js\"\nexport * from \"./lib/dbmodels/program/Program.js\"\nexport * from \"./lib/dbmodels/program/Workout.js\"\nexport * from \"./lib/dbmodels/program/Exercise.js\"\nexport * from \"./lib/dbmodels/program/ExerciseModels.js\"\nexport * from \"./lib/dbmodels/program/Superset.js\"\nexport * from \"./lib/dbmodels/Subscription.js\"\nexport * from \"./lib/dbmodels/SubscriptionLog.js\"\nexport * from \"./lib/dbmodels/nonconsprogram/NonConsumableProgram.js\"\nexport * from \"./lib/dbmodels/nonconsprogram/TranslatedNonConsumableProgramWebContent.js\"\nexport * from \"./lib/dbmodels/nonconsprogram/TranslatedConsumableProgram.js\"\nexport * from \"./lib/dbmodels/nonconsprogram/NonConsumableProgramWebContent.js\"\nexport * from \"./lib/dbmodels/nonconsprogram/UserNonConsumableProgram.js\"\n\n//Utils\nexport {AuthenticationUtil} from \"./lib/utils/AuthenticationUtil.js\"\nexport {NotificationsUtil} from \"./lib/utils/NotificationsUtil.js\"\nexport {NotificationClient} from \"./lib/utils/NotificationClient.js\"\nexport {Log} from \"./lib/utils/Logger.js\"\n\n//Config\nexport {\n ConfigValidator,\n BaseConfigSchema,\n CommonSchemas,\n createConfig,\n ConfigurationError,\n type BaseConfig\n} from \"./lib/config/ConfigValidator.js\"\n\n//Errors\nexport {\n AppError,\n ValidationError,\n AuthenticationError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n UnprocessableEntityError,\n RateLimitError,\n InternalServerError,\n ServiceUnavailableError,\n DatabaseError,\n ExternalAPIError,\n isAppError,\n isOperationalError,\n toAppError\n} from \"./lib/Errors/AppError.js\"\n\n//Middlewares\nexport {\n ErrorMiddleware,\n} from \"./lib/middlewares/ErrorMiddleware.js\"\n\n\nexport {RedisClient} from \"./lib/classes/Redis.js\""],"names":["AuthenticationUtil","NotificationsUtil","NotificationClient","Log","ConfigValidator","BaseConfigSchema","CommonSchemas","createConfig","ConfigurationError","AppError","ValidationError","AuthenticationError","ForbiddenError","NotFoundError","ConflictError","UnprocessableEntityError","RateLimitError","InternalServerError","ServiceUnavailableError","DatabaseError","ExternalAPIError","isAppError","isOperationalError","toAppError","ErrorMiddleware","RedisClient"],"mappings":"AAAA,YAAY;AACZ,cAAc,oCAAoC;AAClD,cAAc,qCAAqC;AACnD,cAAc,oCAAoC;AAClD,cAAc,iCAAiC;AAC/C,cAAc,yCAAyC;AAEvD,WAAW;AACX,cAAc,iCAAgC;AAC9C,cAAc,kCAAiC;AAC/C,cAAc,+BAA8B;AAC5C,cAAc,gCAA+B;AAC7C,cAAc,0BAAyB;AACvC,cAAc,oCAAmC;AACjD,cAAc,oCAAmC;AACjD,cAAc,qCAAoC;AAClD,cAAc,2CAA0C;AACxD,cAAc,qCAAoC;AAClD,cAAc,iCAAgC;AAC9C,cAAc,oCAAmC;AACjD,cAAc,wDAAuD;AACrE,cAAc,4EAA2E;AACzF,cAAc,+DAA8D;AAC5E,cAAc,kEAAiE;AAC/E,cAAc,4DAA2D;AAEzE,OAAO;AACP,SAAQA,kBAAkB,QAAO,oCAAmC;AACpE,SAAQC,iBAAiB,QAAO,mCAAkC;AAClE,SAAQC,kBAAkB,QAAO,oCAAmC;AACpE,SAAQC,GAAG,QAAO,wBAAuB;AAEzC,QAAQ;AACR,SACEC,eAAe,EACfC,gBAAgB,EAChBC,aAAa,EACbC,YAAY,EACZC,kBAAkB,QAEb,kCAAiC;AAExC,QAAQ;AACR,SACEC,QAAQ,EACRC,eAAe,EACfC,mBAAmB,EACnBC,cAAc,EACdC,aAAa,EACbC,aAAa,EACbC,wBAAwB,EACxBC,cAAc,EACdC,mBAAmB,EACnBC,uBAAuB,EACvBC,aAAa,EACbC,gBAAgB,EAChBC,UAAU,EACVC,kBAAkB,EAClBC,UAAU,QACL,2BAA0B;AAEjC,aAAa;AACb,SACEC,eAAe,QACV,uCAAsC;AAG7C,SAAQC,WAAW,QAAO,yBAAwB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Context, Next } from
|
|
2
|
-
import { z } from
|
|
1
|
+
import type { Context, Next } from "koa";
|
|
2
|
+
import { z } from "zod";
|
|
3
3
|
import { AppError } from "../Errors/AppError.js";
|
|
4
4
|
export interface ErrorMiddlewareConfig {
|
|
5
5
|
exposeErrorDetails?: boolean;
|
|
@@ -7,7 +7,7 @@ export interface ErrorMiddlewareConfig {
|
|
|
7
7
|
logger?: (error: Error, ctx: Context) => void;
|
|
8
8
|
formatter?: (error: AppError, ctx: Context) => unknown;
|
|
9
9
|
}
|
|
10
|
-
export declare function
|
|
10
|
+
export declare function ErrorMiddleware(config?: ErrorMiddlewareConfig): (ctx: Context, next: Next) => Promise<void>;
|
|
11
11
|
export declare function formatZodErrors(error: z.ZodError): {
|
|
12
12
|
validationErrors: {
|
|
13
13
|
path: string;
|
|
@@ -15,5 +15,4 @@ export declare function formatZodErrors(error: z.ZodError): {
|
|
|
15
15
|
code: string;
|
|
16
16
|
}[];
|
|
17
17
|
};
|
|
18
|
-
export declare function koaErrorMiddleware(config?: ErrorMiddlewareConfig): (ctx: Context, next: Next) => Promise<void>;
|
|
19
18
|
//# sourceMappingURL=ErrorMiddleware.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorMiddleware.d.ts","sourceRoot":"","sources":["../../../src/lib/middlewares/ErrorMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,
|
|
1
|
+
{"version":3,"file":"ErrorMiddleware.d.ts","sourceRoot":"","sources":["../../../src/lib/middlewares/ErrorMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAc,MAAM,uBAAuB,CAAC;AAE7D,MAAM,WAAW,qBAAqB;IACpC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;CACxD;AAED,wBAAgB,eAAe,CAAC,MAAM,GAAE,qBAA0B,IAQlD,KAAK,OAAO,EAAE,MAAM,IAAI,mBAqCvC;AAgED,wBAAgB,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG;IAClD,gBAAgB,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACrE,CAQA"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AppError, toAppError } from "../Errors/AppError.js";
|
|
3
|
-
export function
|
|
3
|
+
export function ErrorMiddleware(config = {}) {
|
|
4
4
|
const { exposeErrorDetails = false, logErrors = true, logger, formatter } = config;
|
|
5
5
|
return async (ctx, next)=>{
|
|
6
6
|
try {
|
|
7
7
|
await next();
|
|
8
|
-
} catch (
|
|
8
|
+
} catch (err) {
|
|
9
9
|
let appError;
|
|
10
|
-
if (
|
|
11
|
-
appError = new AppError(
|
|
10
|
+
if (err instanceof z.ZodError) {
|
|
11
|
+
appError = new AppError("VALIDATION_ERROR", "Request validation failed", 400, formatZodErrors(err));
|
|
12
12
|
} else {
|
|
13
|
-
appError = toAppError(
|
|
13
|
+
appError = toAppError(err);
|
|
14
14
|
}
|
|
15
15
|
if (logErrors) {
|
|
16
16
|
if (logger) {
|
|
@@ -20,17 +20,16 @@ export function createErrorMiddleware(config = {}) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
ctx.status = appError.statusCode;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
ctx.set('X-Error-Code', appError.code);
|
|
29
|
-
ctx.app.emit('error', appError, ctx);
|
|
23
|
+
ctx.set("X-Error-Code", appError.code);
|
|
24
|
+
ctx.type = "application/json";
|
|
25
|
+
ctx.body = formatter ? formatter(appError, ctx) : formatErrorResponse(appError, exposeErrorDetails);
|
|
26
|
+
// optional: only emit for 5xx to avoid noisy app-level listeners
|
|
27
|
+
ctx.app.emit("error", appError, ctx);
|
|
30
28
|
}
|
|
31
29
|
};
|
|
32
30
|
}
|
|
33
31
|
function defaultErrorLogger(error, ctx) {
|
|
32
|
+
const safeEmail = typeof ctx.state.user?.email === "string" ? "***@***" : undefined;
|
|
34
33
|
const logData = {
|
|
35
34
|
error: {
|
|
36
35
|
code: error.code,
|
|
@@ -41,28 +40,23 @@ function defaultErrorLogger(error, ctx) {
|
|
|
41
40
|
request: {
|
|
42
41
|
method: ctx.method,
|
|
43
42
|
path: ctx.path,
|
|
44
|
-
query: ctx.query,
|
|
45
43
|
ip: ctx.ip,
|
|
46
|
-
userAgent: ctx.get(
|
|
44
|
+
userAgent: ctx.get("user-agent")
|
|
47
45
|
},
|
|
48
46
|
user: {
|
|
49
47
|
id: ctx.state.user?.userUuid,
|
|
50
|
-
email:
|
|
48
|
+
email: safeEmail
|
|
51
49
|
},
|
|
52
50
|
traceId: ctx.state.traceId
|
|
53
51
|
};
|
|
54
52
|
if (error.statusCode >= 500) {
|
|
55
|
-
console.error(
|
|
56
|
-
if (error.stack)
|
|
57
|
-
console.error('Stack trace:', error.stack);
|
|
58
|
-
}
|
|
53
|
+
console.error("❌ Server Error:", JSON.stringify(logData, null, 2));
|
|
54
|
+
if (error.stack) console.error("Stack trace:", error.stack);
|
|
59
55
|
} else {
|
|
60
|
-
console.warn(
|
|
56
|
+
console.warn("⚠️ Client Error:", JSON.stringify(logData, null, 2));
|
|
61
57
|
}
|
|
62
58
|
}
|
|
63
|
-
|
|
64
|
-
* Format error for API response
|
|
65
|
-
*/ function formatErrorResponse(error, exposeDetails) {
|
|
59
|
+
function formatErrorResponse(error, exposeDetails) {
|
|
66
60
|
const response = {
|
|
67
61
|
success: false,
|
|
68
62
|
error: {
|
|
@@ -70,13 +64,11 @@ function defaultErrorLogger(error, ctx) {
|
|
|
70
64
|
message: error.message
|
|
71
65
|
}
|
|
72
66
|
};
|
|
73
|
-
// Add details if configured or if client error (4xx)
|
|
74
67
|
if (exposeDetails || error.statusCode < 500) {
|
|
75
|
-
if (error.details) {
|
|
68
|
+
if (error.details !== undefined) {
|
|
76
69
|
response.error.details = error.details;
|
|
77
70
|
}
|
|
78
71
|
}
|
|
79
|
-
// Never expose stack traces in production
|
|
80
72
|
if (exposeDetails && error.stack) {
|
|
81
73
|
response.error.stack = error.stack;
|
|
82
74
|
}
|
|
@@ -91,8 +83,5 @@ export function formatZodErrors(error) {
|
|
|
91
83
|
}))
|
|
92
84
|
};
|
|
93
85
|
}
|
|
94
|
-
export function koaErrorMiddleware(config = {}) {
|
|
95
|
-
return createErrorMiddleware(config);
|
|
96
|
-
}
|
|
97
86
|
|
|
98
87
|
//# sourceMappingURL=ErrorMiddleware.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/middlewares/ErrorMiddleware.ts"],"sourcesContent":["import type { Context, Next } from
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/middlewares/ErrorMiddleware.ts"],"sourcesContent":["import type { Context, Next } from \"koa\";\nimport { z } from \"zod\";\nimport { AppError, toAppError } from \"../Errors/AppError.js\";\n\nexport interface ErrorMiddlewareConfig {\n exposeErrorDetails?: boolean;\n logErrors?: boolean;\n logger?: (error: Error, ctx: Context) => void;\n formatter?: (error: AppError, ctx: Context) => unknown;\n}\n\nexport function ErrorMiddleware(config: ErrorMiddlewareConfig = {}) {\n const {\n exposeErrorDetails = false,\n logErrors = true,\n logger,\n formatter,\n } = config;\n\n return async (ctx: Context, next: Next) => {\n try {\n await next();\n } catch (err) {\n let appError: AppError;\n\n if (err instanceof z.ZodError) {\n appError = new AppError(\n \"VALIDATION_ERROR\",\n \"Request validation failed\",\n 400,\n formatZodErrors(err)\n );\n } else {\n appError = toAppError(err);\n }\n\n if (logErrors) {\n if (logger) {\n logger(appError, ctx);\n } else {\n defaultErrorLogger(appError, ctx);\n }\n }\n\n ctx.status = appError.statusCode;\n ctx.set(\"X-Error-Code\", appError.code);\n ctx.type = \"application/json\";\n\n ctx.body = formatter\n ? formatter(appError, ctx)\n : formatErrorResponse(appError, exposeErrorDetails);\n\n // optional: only emit for 5xx to avoid noisy app-level listeners\n ctx.app.emit(\"error\", appError, ctx);\n }\n };\n}\n\nfunction defaultErrorLogger(error: AppError, ctx: Context): void {\n const safeEmail =\n typeof ctx.state.user?.email === \"string\" ? \"***@***\" : undefined;\n\n const logData = {\n error: {\n code: error.code,\n message: error.message,\n statusCode: error.statusCode,\n isOperational: error.isOperational,\n },\n request: {\n method: ctx.method,\n path: ctx.path,\n ip: ctx.ip,\n userAgent: ctx.get(\"user-agent\"),\n },\n user: {\n id: ctx.state.user?.userUuid,\n email: safeEmail,\n },\n traceId: ctx.state.traceId,\n };\n\n if (error.statusCode >= 500) {\n console.error(\"❌ Server Error:\", JSON.stringify(logData, null, 2));\n if (error.stack) console.error(\"Stack trace:\", error.stack);\n } else {\n console.warn(\"⚠️ Client Error:\", JSON.stringify(logData, null, 2));\n }\n}\n\nfunction formatErrorResponse(error: AppError, exposeDetails: boolean): unknown {\n const response: {\n success: false;\n error: {\n code: string;\n message: string;\n details?: unknown;\n stack?: string;\n };\n } = {\n success: false,\n error: {\n code: error.code,\n message: error.message,\n },\n };\n\n if (exposeDetails || error.statusCode < 500) {\n if (error.details !== undefined) {\n response.error.details = error.details;\n }\n }\n\n if (exposeDetails && error.stack) {\n response.error.stack = error.stack;\n }\n\n return response;\n}\n\nexport function formatZodErrors(error: z.ZodError): {\n validationErrors: { path: string; message: string; code: string }[];\n} {\n return {\n validationErrors: error.issues.map((issue) => ({\n path: issue.path.join(\".\"),\n message: issue.message,\n code: issue.code,\n })),\n };\n}"],"names":["z","AppError","toAppError","ErrorMiddleware","config","exposeErrorDetails","logErrors","logger","formatter","ctx","next","err","appError","ZodError","formatZodErrors","defaultErrorLogger","status","statusCode","set","code","type","body","formatErrorResponse","app","emit","error","safeEmail","state","user","email","undefined","logData","message","isOperational","request","method","path","ip","userAgent","get","id","userUuid","traceId","console","JSON","stringify","stack","warn","exposeDetails","response","success","details","validationErrors","issues","map","issue","join"],"mappings":"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"}
|