@scpxl/nodejs-framework 1.0.24 → 1.0.25

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 (101) hide show
  1. package/README.md +65 -17
  2. package/dist/api-requester/api-requester.d.ts.map +1 -1
  3. package/dist/api-requester/api-requester.js +2 -1
  4. package/dist/api-requester/api-requester.js.map +2 -2
  5. package/dist/application/base-application.d.ts.map +1 -1
  6. package/dist/application/base-application.js +4 -3
  7. package/dist/application/base-application.js.map +2 -2
  8. package/dist/cache/manager.d.ts.map +1 -1
  9. package/dist/cache/manager.js +2 -1
  10. package/dist/cache/manager.js.map +2 -2
  11. package/dist/cli/index.js +7019 -83
  12. package/dist/cli/index.js.map +4 -4
  13. package/dist/cluster/cluster-manager.d.ts +3 -0
  14. package/dist/cluster/cluster-manager.d.ts.map +1 -1
  15. package/dist/cluster/cluster-manager.js +45 -8
  16. package/dist/cluster/cluster-manager.js.map +2 -2
  17. package/dist/database/dynamic-entity-form-decorators.d.ts +2 -2
  18. package/dist/database/dynamic-entity-form-decorators.d.ts.map +1 -1
  19. package/dist/database/dynamic-entity-form-decorators.js.map +1 -1
  20. package/dist/database/dynamic-entity.d.ts +7 -4
  21. package/dist/database/dynamic-entity.d.ts.map +1 -1
  22. package/dist/database/dynamic-entity.js +11 -1
  23. package/dist/database/dynamic-entity.js.map +2 -2
  24. package/dist/database/manager.d.ts.map +1 -1
  25. package/dist/database/manager.js +3 -2
  26. package/dist/database/manager.js.map +2 -2
  27. package/dist/error/error-reporter.d.ts +20 -7
  28. package/dist/error/error-reporter.d.ts.map +1 -1
  29. package/dist/error/error-reporter.js +32 -29
  30. package/dist/error/error-reporter.js.map +2 -2
  31. package/dist/error/index.d.ts +1 -1
  32. package/dist/error/index.d.ts.map +1 -1
  33. package/dist/error/index.js +3 -2
  34. package/dist/error/index.js.map +2 -2
  35. package/dist/event/controller/base.d.ts.map +1 -1
  36. package/dist/event/controller/base.js +2 -1
  37. package/dist/event/controller/base.js.map +2 -2
  38. package/dist/event/manager.d.ts.map +1 -1
  39. package/dist/event/manager.js +5 -4
  40. package/dist/event/manager.js.map +2 -2
  41. package/dist/lifecycle/exit.d.ts.map +1 -1
  42. package/dist/lifecycle/exit.js.map +2 -2
  43. package/dist/logger/logger.d.ts.map +1 -1
  44. package/dist/logger/logger.js +3 -2
  45. package/dist/logger/logger.js.map +2 -2
  46. package/dist/performance/performance-monitor.d.ts.map +1 -1
  47. package/dist/performance/performance-monitor.js +10 -3
  48. package/dist/performance/performance-monitor.js.map +2 -2
  49. package/dist/queue/processor/base.d.ts.map +1 -1
  50. package/dist/queue/processor/base.js +2 -1
  51. package/dist/queue/processor/base.js.map +2 -2
  52. package/dist/redis/manager.d.ts.map +1 -1
  53. package/dist/redis/manager.js +3 -2
  54. package/dist/redis/manager.js.map +2 -2
  55. package/dist/schemas/common.d.ts +197 -0
  56. package/dist/schemas/common.d.ts.map +1 -0
  57. package/dist/schemas/common.js +108 -0
  58. package/dist/schemas/common.js.map +7 -0
  59. package/dist/schemas/index.d.ts +6 -0
  60. package/dist/schemas/index.d.ts.map +1 -0
  61. package/dist/schemas/index.js +2 -0
  62. package/dist/schemas/index.js.map +7 -0
  63. package/dist/util/loader.d.ts.map +1 -1
  64. package/dist/util/loader.js.map +2 -2
  65. package/dist/webserver/controller/base.d.ts.map +1 -1
  66. package/dist/webserver/controller/base.js +4 -4
  67. package/dist/webserver/controller/base.js.map +2 -2
  68. package/dist/webserver/controller/entity.js.map +2 -2
  69. package/dist/webserver/controller/health.d.ts +0 -2
  70. package/dist/webserver/controller/health.d.ts.map +1 -1
  71. package/dist/webserver/controller/health.js +0 -14
  72. package/dist/webserver/controller/health.js.map +2 -2
  73. package/dist/webserver/webserver.d.ts.map +1 -1
  74. package/dist/webserver/webserver.interface.d.ts +2 -2
  75. package/dist/webserver/webserver.interface.d.ts.map +1 -1
  76. package/dist/webserver/webserver.interface.js.map +1 -1
  77. package/dist/webserver/webserver.js +2 -2
  78. package/dist/webserver/webserver.js.map +2 -2
  79. package/dist/websocket/index.d.ts +2 -0
  80. package/dist/websocket/index.d.ts.map +1 -1
  81. package/dist/websocket/index.js +2 -0
  82. package/dist/websocket/index.js.map +2 -2
  83. package/dist/websocket/websocket-auth.d.ts +17 -0
  84. package/dist/websocket/websocket-auth.d.ts.map +1 -0
  85. package/dist/websocket/websocket-auth.js +46 -0
  86. package/dist/websocket/websocket-auth.js.map +7 -0
  87. package/dist/websocket/websocket-client-manager.d.ts.map +1 -1
  88. package/dist/websocket/websocket-client-manager.js +6 -5
  89. package/dist/websocket/websocket-client-manager.js.map +2 -2
  90. package/dist/websocket/websocket-client.d.ts +29 -0
  91. package/dist/websocket/websocket-client.d.ts.map +1 -1
  92. package/dist/websocket/websocket-client.js +97 -3
  93. package/dist/websocket/websocket-client.js.map +2 -2
  94. package/dist/websocket/websocket-server.d.ts +10 -0
  95. package/dist/websocket/websocket-server.d.ts.map +1 -1
  96. package/dist/websocket/websocket-server.js +40 -52
  97. package/dist/websocket/websocket-server.js.map +2 -2
  98. package/dist/websocket/websocket.interface.d.ts +13 -0
  99. package/dist/websocket/websocket.interface.d.ts.map +1 -1
  100. package/dist/websocket/websocket.interface.js.map +2 -2
  101. package/package.json +9 -12
@@ -5,6 +5,9 @@ export default class ClusterManager {
5
5
  private stopApplicationCallback;
6
6
  private shutdownSignals;
7
7
  private isShuttingDown;
8
+ private initialWorkerCount;
9
+ private shutdownTimeout;
10
+ private shutdownTimer?;
8
11
  constructor({ config, startApplicationCallback, stopApplicationCallback }: ClusterManagerProps);
9
12
  start(): void;
10
13
  private setupPrimary;
@@ -1 +1 @@
1
- {"version":3,"file":"cluster-manager.d.ts","sourceRoot":"","sources":["../../src/cluster/cluster-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,mBAAmB,EAEpB,MAAM,gCAAgC,CAAC;AAIxC,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAE9C,OAAO,CAAC,wBAAwB,CAAsB;IACtD,OAAO,CAAC,uBAAuB,CAAsB;IAErD,OAAO,CAAC,eAAe,CAA2C;IAClE,OAAO,CAAC,cAAc,CAAS;gBAEnB,EAAE,MAAM,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,EAAE,mBAAmB;IAOvF,KAAK,IAAI,IAAI;IAUpB,OAAO,CAAC,YAAY;YAqCN,WAAW;IAkBzB,OAAO,CAAC,cAAc;YAMR,gBAAgB;CA6B/B"}
1
+ {"version":3,"file":"cluster-manager.d.ts","sourceRoot":"","sources":["../../src/cluster/cluster-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,mBAAmB,EAEpB,MAAM,gCAAgC,CAAC;AAIxC,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAE9C,OAAO,CAAC,wBAAwB,CAAsB;IACtD,OAAO,CAAC,uBAAuB,CAAsB;IAErD,OAAO,CAAC,eAAe,CAA2C;IAClE,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,aAAa,CAAC,CAAiB;gBAE3B,EAAE,MAAM,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,EAAE,mBAAmB;IAOvF,KAAK,IAAI,IAAI;IAUpB,OAAO,CAAC,YAAY;YAiDN,WAAW;IAkBzB,OAAO,CAAC,cAAc;YAMR,gBAAgB;CA2D/B"}
@@ -13,6 +13,10 @@ class ClusterManager {
13
13
  stopApplicationCallback;
14
14
  shutdownSignals = ["SIGTERM", "SIGINT"];
15
15
  isShuttingDown = false;
16
+ initialWorkerCount = 0;
17
+ shutdownTimeout = 3e4;
18
+ // 30 seconds
19
+ shutdownTimer;
16
20
  constructor({ config, startApplicationCallback, stopApplicationCallback }) {
17
21
  this.config = config;
18
22
  this.startApplicationCallback = startApplicationCallback;
@@ -29,6 +33,7 @@ class ClusterManager {
29
33
  setupPrimary() {
30
34
  const numCPUs = cpus().length;
31
35
  const numClusterWorkers = this.config.workerMode === "auto" ? numCPUs : this.config.workerCount;
36
+ this.initialWorkerCount = numClusterWorkers;
32
37
  for (let workerIndex = 0; workerIndex < numClusterWorkers; workerIndex++) {
33
38
  cluster.fork();
34
39
  }
@@ -41,8 +46,17 @@ class ClusterManager {
41
46
  }
42
47
  });
43
48
  });
44
- cluster.on("exit", () => {
49
+ cluster.on("exit", (worker, code, signal) => {
45
50
  if (!this.isShuttingDown) {
51
+ Logger.warn({
52
+ message: "Cluster worker died unexpectedly, restarting",
53
+ meta: {
54
+ ID: worker.id,
55
+ PID: worker.process.pid,
56
+ exitCode: code,
57
+ signal
58
+ }
59
+ });
46
60
  cluster.fork();
47
61
  }
48
62
  });
@@ -80,18 +94,41 @@ class ClusterManager {
80
94
  }
81
95
  this.isShuttingDown = true;
82
96
  if (cluster.isPrimary) {
83
- Object.values(cluster.workers ?? {}).forEach((worker) => {
84
- if (worker) {
85
- worker.send("shutdown");
86
- }
97
+ Logger.info({
98
+ message: "Initiating cluster shutdown",
99
+ meta: { workerCount: this.initialWorkerCount }
87
100
  });
88
101
  let exitedWorkers = 0;
89
- cluster.on("exit", () => {
102
+ const exitHandler = /* @__PURE__ */ __name(() => {
90
103
  exitedWorkers++;
91
- const numClusterWorkers = Object.values(cluster.workers ?? {}).filter(Boolean).length;
92
- if (exitedWorkers === numClusterWorkers) {
104
+ Logger.debug({
105
+ message: "Cluster worker exited during shutdown",
106
+ meta: { exitedWorkers, totalWorkers: this.initialWorkerCount }
107
+ });
108
+ if (exitedWorkers === this.initialWorkerCount) {
109
+ if (this.shutdownTimer) {
110
+ clearTimeout(this.shutdownTimer);
111
+ }
112
+ Logger.info({ message: "All cluster workers exited gracefully" });
93
113
  requestExit({ code: 0, reason: "cluster-workers-exited" });
94
114
  }
115
+ }, "exitHandler");
116
+ cluster.on("exit", exitHandler);
117
+ this.shutdownTimer = setTimeout(() => {
118
+ Logger.warn({
119
+ message: "Cluster shutdown timeout reached, forcing exit",
120
+ meta: {
121
+ exitedWorkers,
122
+ totalWorkers: this.initialWorkerCount,
123
+ timeoutMs: this.shutdownTimeout
124
+ }
125
+ });
126
+ requestExit({ code: 1, reason: "cluster-shutdown-timeout" });
127
+ }, this.shutdownTimeout);
128
+ Object.values(cluster.workers ?? {}).forEach((worker) => {
129
+ if (worker) {
130
+ worker.send("shutdown");
131
+ }
95
132
  });
96
133
  } else {
97
134
  await this.stopApplicationCallback();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cluster/cluster-manager.ts"],
4
- "sourcesContent": ["import cluster from 'node:cluster';\nimport { cpus } from 'node:os';\nimport type {\n ClusterManagerConfig,\n ClusterManagerProps,\n ClusterManagerWorkerModeManualConfig,\n} from './cluster-manager.interface.js';\nimport { Logger } from '../logger/index.js';\nimport { requestExit } from '../lifecycle/exit.js';\n\nexport default class ClusterManager {\n private readonly config: ClusterManagerConfig;\n\n private startApplicationCallback: () => Promise<void>;\n private stopApplicationCallback: () => Promise<void>;\n\n private shutdownSignals: NodeJS.Signals[] = ['SIGTERM', 'SIGINT'];\n private isShuttingDown = false;\n\n constructor({ config, startApplicationCallback, stopApplicationCallback }: ClusterManagerProps) {\n this.config = config;\n\n this.startApplicationCallback = startApplicationCallback;\n this.stopApplicationCallback = stopApplicationCallback;\n }\n\n public start(): void {\n if (cluster.isPrimary) {\n this.setupPrimary();\n } else {\n this.setupWorker();\n }\n\n this.handleShutdown();\n }\n\n private setupPrimary(): void {\n const numCPUs: number = cpus().length;\n\n const numClusterWorkers =\n this.config.workerMode === 'auto' ? numCPUs : (this.config as ClusterManagerWorkerModeManualConfig).workerCount;\n\n for (let workerIndex = 0; workerIndex < numClusterWorkers; workerIndex++) {\n cluster.fork();\n }\n\n cluster.on('online', worker => {\n Logger.debug({\n message: 'Started cluster worker',\n meta: {\n ID: worker.id,\n PID: worker.process.pid,\n },\n });\n });\n\n cluster.on('exit', () => {\n if (!this.isShuttingDown) {\n // Restart worker on unexpected exit\n cluster.fork();\n }\n });\n\n Logger.debug({\n message: 'Started cluster master',\n meta: {\n Mode: this.config.workerMode,\n 'Worker Count': numClusterWorkers,\n CPUs: numCPUs,\n },\n });\n }\n\n private async setupWorker(): Promise<void> {\n await this.startApplicationCallback();\n\n process.on('message', async message => {\n if (message === 'shutdown') {\n Logger.debug({\n message: 'Worker received shutdown message, stopping...',\n meta: {\n PID: process.pid,\n },\n });\n\n // Stop application\n await this.stopApplicationCallback();\n }\n });\n }\n\n private handleShutdown(): void {\n this.shutdownSignals.forEach(signal => {\n process.on(signal, async () => await this.initiateShutdown());\n });\n }\n\n private async initiateShutdown(): Promise<void> {\n if (this.isShuttingDown) {\n return;\n }\n\n this.isShuttingDown = true;\n\n if (cluster.isPrimary) {\n Object.values(cluster.workers ?? {}).forEach(worker => {\n if (worker) {\n worker.send('shutdown');\n }\n });\n\n let exitedWorkers = 0;\n\n cluster.on('exit', () => {\n exitedWorkers++;\n\n const numClusterWorkers = Object.values(cluster.workers ?? {}).filter(Boolean).length;\n\n if (exitedWorkers === numClusterWorkers) {\n requestExit({ code: 0, reason: 'cluster-workers-exited' });\n }\n });\n } else {\n await this.stopApplicationCallback();\n }\n }\n}\n"],
5
- "mappings": ";;AAAA,OAAO,aAAa;AACpB,SAAS,YAAY;AAMrB,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAE5B,MAAO,eAA6B;AAAA,EAVpC,OAUoC;AAAA;AAAA;AAAA,EACjB;AAAA,EAET;AAAA,EACA;AAAA,EAEA,kBAAoC,CAAC,WAAW,QAAQ;AAAA,EACxD,iBAAiB;AAAA,EAEzB,YAAY,EAAE,QAAQ,0BAA0B,wBAAwB,GAAwB;AAC9F,SAAK,SAAS;AAEd,SAAK,2BAA2B;AAChC,SAAK,0BAA0B;AAAA,EACjC;AAAA,EAEO,QAAc;AACnB,QAAI,QAAQ,WAAW;AACrB,WAAK,aAAa;AAAA,IACpB,OAAO;AACL,WAAK,YAAY;AAAA,IACnB;AAEA,SAAK,eAAe;AAAA,EACtB;AAAA,EAEQ,eAAqB;AAC3B,UAAM,UAAkB,KAAK,EAAE;AAE/B,UAAM,oBACJ,KAAK,OAAO,eAAe,SAAS,UAAW,KAAK,OAAgD;AAEtG,aAAS,cAAc,GAAG,cAAc,mBAAmB,eAAe;AACxE,cAAQ,KAAK;AAAA,IACf;AAEA,YAAQ,GAAG,UAAU,YAAU;AAC7B,aAAO,MAAM;AAAA,QACX,SAAS;AAAA,QACT,MAAM;AAAA,UACJ,IAAI,OAAO;AAAA,UACX,KAAK,OAAO,QAAQ;AAAA,QACtB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,YAAQ,GAAG,QAAQ,MAAM;AACvB,UAAI,CAAC,KAAK,gBAAgB;AAExB,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AAAA,MACX,SAAS;AAAA,MACT,MAAM;AAAA,QACJ,MAAM,KAAK,OAAO;AAAA,QAClB,gBAAgB;AAAA,QAChB,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,cAA6B;AACzC,UAAM,KAAK,yBAAyB;AAEpC,YAAQ,GAAG,WAAW,OAAM,YAAW;AACrC,UAAI,YAAY,YAAY;AAC1B,eAAO,MAAM;AAAA,UACX,SAAS;AAAA,UACT,MAAM;AAAA,YACJ,KAAK,QAAQ;AAAA,UACf;AAAA,QACF,CAAC;AAGD,cAAM,KAAK,wBAAwB;AAAA,MACrC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,iBAAuB;AAC7B,SAAK,gBAAgB,QAAQ,YAAU;AACrC,cAAQ,GAAG,QAAQ,YAAY,MAAM,KAAK,iBAAiB,CAAC;AAAA,IAC9D,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,mBAAkC;AAC9C,QAAI,KAAK,gBAAgB;AACvB;AAAA,IACF;AAEA,SAAK,iBAAiB;AAEtB,QAAI,QAAQ,WAAW;AACrB,aAAO,OAAO,QAAQ,WAAW,CAAC,CAAC,EAAE,QAAQ,YAAU;AACrD,YAAI,QAAQ;AACV,iBAAO,KAAK,UAAU;AAAA,QACxB;AAAA,MACF,CAAC;AAED,UAAI,gBAAgB;AAEpB,cAAQ,GAAG,QAAQ,MAAM;AACvB;AAEA,cAAM,oBAAoB,OAAO,OAAO,QAAQ,WAAW,CAAC,CAAC,EAAE,OAAO,OAAO,EAAE;AAE/E,YAAI,kBAAkB,mBAAmB;AACvC,sBAAY,EAAE,MAAM,GAAG,QAAQ,yBAAyB,CAAC;AAAA,QAC3D;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AACL,YAAM,KAAK,wBAAwB;AAAA,IACrC;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import cluster from 'node:cluster';\nimport { cpus } from 'node:os';\nimport type {\n ClusterManagerConfig,\n ClusterManagerProps,\n ClusterManagerWorkerModeManualConfig,\n} from './cluster-manager.interface.js';\nimport { Logger } from '../logger/index.js';\nimport { requestExit } from '../lifecycle/exit.js';\n\nexport default class ClusterManager {\n private readonly config: ClusterManagerConfig;\n\n private startApplicationCallback: () => Promise<void>;\n private stopApplicationCallback: () => Promise<void>;\n\n private shutdownSignals: NodeJS.Signals[] = ['SIGTERM', 'SIGINT'];\n private isShuttingDown = false;\n private initialWorkerCount = 0;\n private shutdownTimeout = 30000; // 30 seconds\n private shutdownTimer?: NodeJS.Timeout;\n\n constructor({ config, startApplicationCallback, stopApplicationCallback }: ClusterManagerProps) {\n this.config = config;\n\n this.startApplicationCallback = startApplicationCallback;\n this.stopApplicationCallback = stopApplicationCallback;\n }\n\n public start(): void {\n if (cluster.isPrimary) {\n this.setupPrimary();\n } else {\n this.setupWorker();\n }\n\n this.handleShutdown();\n }\n\n private setupPrimary(): void {\n const numCPUs: number = cpus().length;\n\n const numClusterWorkers =\n this.config.workerMode === 'auto' ? numCPUs : (this.config as ClusterManagerWorkerModeManualConfig).workerCount;\n\n // Track initial worker count for shutdown\n this.initialWorkerCount = numClusterWorkers;\n\n for (let workerIndex = 0; workerIndex < numClusterWorkers; workerIndex++) {\n cluster.fork();\n }\n\n cluster.on('online', worker => {\n Logger.debug({\n message: 'Started cluster worker',\n meta: {\n ID: worker.id,\n PID: worker.process.pid,\n },\n });\n });\n\n cluster.on('exit', (worker, code, signal) => {\n if (!this.isShuttingDown) {\n // Restart worker on unexpected exit\n Logger.warn({\n message: 'Cluster worker died unexpectedly, restarting',\n meta: {\n ID: worker.id,\n PID: worker.process.pid,\n exitCode: code,\n signal,\n },\n });\n cluster.fork();\n }\n });\n\n Logger.debug({\n message: 'Started cluster master',\n meta: {\n Mode: this.config.workerMode,\n 'Worker Count': numClusterWorkers,\n CPUs: numCPUs,\n },\n });\n }\n\n private async setupWorker(): Promise<void> {\n await this.startApplicationCallback();\n\n process.on('message', async message => {\n if (message === 'shutdown') {\n Logger.debug({\n message: 'Worker received shutdown message, stopping...',\n meta: {\n PID: process.pid,\n },\n });\n\n // Stop application\n await this.stopApplicationCallback();\n }\n });\n }\n\n private handleShutdown(): void {\n this.shutdownSignals.forEach(signal => {\n process.on(signal, async () => await this.initiateShutdown());\n });\n }\n\n private async initiateShutdown(): Promise<void> {\n if (this.isShuttingDown) {\n return;\n }\n\n this.isShuttingDown = true;\n\n if (cluster.isPrimary) {\n Logger.info({\n message: 'Initiating cluster shutdown',\n meta: { workerCount: this.initialWorkerCount },\n });\n\n let exitedWorkers = 0;\n\n // Set up exit handler BEFORE sending shutdown messages to avoid race condition\n const exitHandler = () => {\n exitedWorkers++;\n\n Logger.debug({\n message: 'Cluster worker exited during shutdown',\n meta: { exitedWorkers, totalWorkers: this.initialWorkerCount },\n });\n\n if (exitedWorkers === this.initialWorkerCount) {\n if (this.shutdownTimer) {\n clearTimeout(this.shutdownTimer);\n }\n Logger.info({ message: 'All cluster workers exited gracefully' });\n requestExit({ code: 0, reason: 'cluster-workers-exited' });\n }\n };\n\n // Attach exit listener first\n cluster.on('exit', exitHandler);\n\n // Set shutdown timeout\n this.shutdownTimer = setTimeout(() => {\n Logger.warn({\n message: 'Cluster shutdown timeout reached, forcing exit',\n meta: {\n exitedWorkers,\n totalWorkers: this.initialWorkerCount,\n timeoutMs: this.shutdownTimeout,\n },\n });\n requestExit({ code: 1, reason: 'cluster-shutdown-timeout' });\n }, this.shutdownTimeout);\n\n // Now send shutdown messages to all workers\n Object.values(cluster.workers ?? {}).forEach(worker => {\n if (worker) {\n worker.send('shutdown');\n }\n });\n } else {\n await this.stopApplicationCallback();\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,4 @@
1
- import type Joi from 'joi';
1
+ import type { z } from 'zod';
2
2
  import 'reflect-metadata';
3
3
  export declare enum FormFieldType {
4
4
  Text = "text",
@@ -22,7 +22,7 @@ export interface FormFieldOptions {
22
22
  }
23
23
  export interface FormFieldOptionsExtended extends FormFieldOptions {
24
24
  name: string;
25
- validation: Joi.PartialSchemaMap | null;
25
+ validation: z.ZodSchema | null;
26
26
  }
27
27
  export declare const FormField: (options: FormFieldOptions) => (target: any, propertyKey: string) => void;
28
28
  export declare const generateFormFields: ({ model }: {
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-entity-form-decorators.d.ts","sourceRoot":"","sources":["../../src/database/dynamic-entity-form-decorators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,kBAAkB,CAAC;AAS1B,oBAAY,aAAa;IACvB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,KAAK,UAAU;IACf,YAAY,iBAAiB;IAC7B,QAAQ,aAAa;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,UAAU,CAAC,EAAE,GAAG,CAAC;CAClB;AAED,MAAM,WAAW,wBAAyB,SAAQ,gBAAgB;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,GAAG,CAAC,gBAAgB,GAAG,IAAI,CAAC;CACzC;AAED,eAAO,MAAM,SAAS,GAAI,SAAS,gBAAgB,MACzC,QAAQ,GAAG,EAAE,aAAa,MAAM,SAgBzC,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,WAAW;IAAE,KAAK,EAAE,GAAG,CAAA;CAAE,KAAG,wBAAwB,EAqCtF,CAAC"}
1
+ {"version":3,"file":"dynamic-entity-form-decorators.d.ts","sourceRoot":"","sources":["../../src/database/dynamic-entity-form-decorators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,kBAAkB,CAAC;AAS1B,oBAAY,aAAa;IACvB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,KAAK,UAAU;IACf,YAAY,iBAAiB;IAC7B,QAAQ,aAAa;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,UAAU,CAAC,EAAE,GAAG,CAAC;CAClB;AAED,MAAM,WAAW,wBAAyB,SAAQ,gBAAgB;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC;CAChC;AAED,eAAO,MAAM,SAAS,GAAI,SAAS,gBAAgB,MACzC,QAAQ,GAAG,EAAE,aAAa,MAAM,SAgBzC,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,WAAW;IAAE,KAAK,EAAE,GAAG,CAAA;CAAE,KAAG,wBAAwB,EAqCtF,CAAC"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/database/dynamic-entity-form-decorators.ts"],
4
- "sourcesContent": ["import type Joi from 'joi';\nimport 'reflect-metadata';\n\n// @FormField({\n// type: FormFieldType.DynamicInput,\n// label: 'Keywords',\n// typeOptions: { defaultMessage: 'Add Keyword' },\n// typeValues: [{ key: 'keyword', type: FormFieldType.Text, label: 'Keyword' }],\n// })\n\nexport enum FormFieldType {\n Text = 'text',\n Email = 'email',\n Password = 'password',\n Number = 'number',\n Date = 'date',\n Select = 'select',\n Checkbox = 'checkbox',\n Textarea = 'textarea',\n Image = 'image',\n DynamicInput = 'dynamicInput',\n ReadOnly = 'readonly',\n}\n\nexport interface FormFieldOptions {\n type: FormFieldType;\n label: string;\n placeholder?: string;\n typeOptions?: any;\n typeValues?: any;\n}\n\nexport interface FormFieldOptionsExtended extends FormFieldOptions {\n name: string;\n validation: Joi.PartialSchemaMap | null;\n}\n\nexport const FormField = (options: FormFieldOptions) => {\n return (target: any, propertyKey: string) => {\n Reflect.defineMetadata('custom:formFieldType', options.type, target, propertyKey);\n Reflect.defineMetadata('custom:formFieldLabel', options.label, target, propertyKey);\n\n if (options.placeholder) {\n Reflect.defineMetadata('custom:formFieldPlaceholder', options.placeholder, target, propertyKey);\n }\n\n if (options.typeOptions) {\n Reflect.defineMetadata('custom:formFieldTypeOptions', options.typeOptions, target, propertyKey);\n }\n\n if (options.typeValues) {\n Reflect.defineMetadata('custom:formFieldTypeValues', options.typeValues, target, propertyKey);\n }\n };\n};\n\nexport const generateFormFields = ({ model }: { model: any }): FormFieldOptionsExtended[] => {\n const formFields: FormFieldOptionsExtended[] = [];\n\n const { prototype } = model;\n\n for (const propertyKey of Object.getOwnPropertyNames(prototype)) {\n const formFieldType = Reflect.getMetadata('custom:formFieldType', prototype, propertyKey);\n const formFieldLabel = Reflect.getMetadata('custom:formFieldLabel', prototype, propertyKey);\n const formFieldPlaceholder = Reflect.getMetadata('custom:formFieldPlaceholder', prototype, propertyKey);\n const formFieldTypeOptions = Reflect.getMetadata('custom:formFieldTypeOptions', prototype, propertyKey);\n const formFieldTypeValues = Reflect.getMetadata('custom:formFieldTypeValues', prototype, propertyKey);\n\n const validationRules = null;\n\n // if (schema && schema.describe) {\n // const schemaDescription = schema.describe();\n // const propertySchema = schemaDescription.keys?.[propertyKey];\n\n // if (propertySchema) {\n // validationRules = propertySchema;\n // }\n // }\n\n if (formFieldType && formFieldLabel) {\n formFields.push({\n name: propertyKey,\n type: formFieldType,\n label: formFieldLabel,\n placeholder: formFieldPlaceholder,\n validation: validationRules,\n typeOptions: formFieldTypeOptions,\n typeValues: formFieldTypeValues,\n });\n }\n }\n\n return formFields;\n};\n"],
4
+ "sourcesContent": ["import type { z } from 'zod';\nimport 'reflect-metadata';\n\n// @FormField({\n// type: FormFieldType.DynamicInput,\n// label: 'Keywords',\n// typeOptions: { defaultMessage: 'Add Keyword' },\n// typeValues: [{ key: 'keyword', type: FormFieldType.Text, label: 'Keyword' }],\n// })\n\nexport enum FormFieldType {\n Text = 'text',\n Email = 'email',\n Password = 'password',\n Number = 'number',\n Date = 'date',\n Select = 'select',\n Checkbox = 'checkbox',\n Textarea = 'textarea',\n Image = 'image',\n DynamicInput = 'dynamicInput',\n ReadOnly = 'readonly',\n}\n\nexport interface FormFieldOptions {\n type: FormFieldType;\n label: string;\n placeholder?: string;\n typeOptions?: any;\n typeValues?: any;\n}\n\nexport interface FormFieldOptionsExtended extends FormFieldOptions {\n name: string;\n validation: z.ZodSchema | null;\n}\n\nexport const FormField = (options: FormFieldOptions) => {\n return (target: any, propertyKey: string) => {\n Reflect.defineMetadata('custom:formFieldType', options.type, target, propertyKey);\n Reflect.defineMetadata('custom:formFieldLabel', options.label, target, propertyKey);\n\n if (options.placeholder) {\n Reflect.defineMetadata('custom:formFieldPlaceholder', options.placeholder, target, propertyKey);\n }\n\n if (options.typeOptions) {\n Reflect.defineMetadata('custom:formFieldTypeOptions', options.typeOptions, target, propertyKey);\n }\n\n if (options.typeValues) {\n Reflect.defineMetadata('custom:formFieldTypeValues', options.typeValues, target, propertyKey);\n }\n };\n};\n\nexport const generateFormFields = ({ model }: { model: any }): FormFieldOptionsExtended[] => {\n const formFields: FormFieldOptionsExtended[] = [];\n\n const { prototype } = model;\n\n for (const propertyKey of Object.getOwnPropertyNames(prototype)) {\n const formFieldType = Reflect.getMetadata('custom:formFieldType', prototype, propertyKey);\n const formFieldLabel = Reflect.getMetadata('custom:formFieldLabel', prototype, propertyKey);\n const formFieldPlaceholder = Reflect.getMetadata('custom:formFieldPlaceholder', prototype, propertyKey);\n const formFieldTypeOptions = Reflect.getMetadata('custom:formFieldTypeOptions', prototype, propertyKey);\n const formFieldTypeValues = Reflect.getMetadata('custom:formFieldTypeValues', prototype, propertyKey);\n\n const validationRules = null;\n\n // if (schema && schema.describe) {\n // const schemaDescription = schema.describe();\n // const propertySchema = schemaDescription.keys?.[propertyKey];\n\n // if (propertySchema) {\n // validationRules = propertySchema;\n // }\n // }\n\n if (formFieldType && formFieldLabel) {\n formFields.push({\n name: propertyKey,\n type: formFieldType,\n label: formFieldLabel,\n placeholder: formFieldPlaceholder,\n validation: validationRules,\n typeOptions: formFieldTypeOptions,\n typeValues: formFieldTypeValues,\n });\n }\n }\n\n return formFields;\n};\n"],
5
5
  "mappings": ";;AACA,OAAO;AASA,IAAK,gBAAL,kBAAKA,mBAAL;AACL,EAAAA,eAAA,UAAO;AACP,EAAAA,eAAA,WAAQ;AACR,EAAAA,eAAA,cAAW;AACX,EAAAA,eAAA,YAAS;AACT,EAAAA,eAAA,UAAO;AACP,EAAAA,eAAA,YAAS;AACT,EAAAA,eAAA,cAAW;AACX,EAAAA,eAAA,cAAW;AACX,EAAAA,eAAA,WAAQ;AACR,EAAAA,eAAA,kBAAe;AACf,EAAAA,eAAA,cAAW;AAXD,SAAAA;AAAA,GAAA;AA2BL,MAAM,YAAY,wBAAC,YAA8B;AACtD,SAAO,CAAC,QAAa,gBAAwB;AAC3C,YAAQ,eAAe,wBAAwB,QAAQ,MAAM,QAAQ,WAAW;AAChF,YAAQ,eAAe,yBAAyB,QAAQ,OAAO,QAAQ,WAAW;AAElF,QAAI,QAAQ,aAAa;AACvB,cAAQ,eAAe,+BAA+B,QAAQ,aAAa,QAAQ,WAAW;AAAA,IAChG;AAEA,QAAI,QAAQ,aAAa;AACvB,cAAQ,eAAe,+BAA+B,QAAQ,aAAa,QAAQ,WAAW;AAAA,IAChG;AAEA,QAAI,QAAQ,YAAY;AACtB,cAAQ,eAAe,8BAA8B,QAAQ,YAAY,QAAQ,WAAW;AAAA,IAC9F;AAAA,EACF;AACF,GAjByB;AAmBlB,MAAM,qBAAqB,wBAAC,EAAE,MAAM,MAAkD;AAC3F,QAAM,aAAyC,CAAC;AAEhD,QAAM,EAAE,UAAU,IAAI;AAEtB,aAAW,eAAe,OAAO,oBAAoB,SAAS,GAAG;AAC/D,UAAM,gBAAgB,QAAQ,YAAY,wBAAwB,WAAW,WAAW;AACxF,UAAM,iBAAiB,QAAQ,YAAY,yBAAyB,WAAW,WAAW;AAC1F,UAAM,uBAAuB,QAAQ,YAAY,+BAA+B,WAAW,WAAW;AACtG,UAAM,uBAAuB,QAAQ,YAAY,+BAA+B,WAAW,WAAW;AACtG,UAAM,sBAAsB,QAAQ,YAAY,8BAA8B,WAAW,WAAW;AAEpG,UAAM,kBAAkB;AAWxB,QAAI,iBAAiB,gBAAgB;AACnC,iBAAW,KAAK;AAAA,QACd,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT,GArCkC;",
6
6
  "names": ["FormFieldType"]
7
7
  }
@@ -1,15 +1,18 @@
1
1
  import { BaseEntity } from '@mikro-orm/core';
2
- import type { Schema, ValidationResult } from 'joi';
2
+ import { z } from 'zod';
3
3
  export declare abstract class DynamicEntity extends BaseEntity {
4
- static schema: Schema;
5
- static schemaUpdate: Schema;
4
+ static schema: z.ZodSchema;
5
+ static schemaUpdate: z.ZodSchema;
6
6
  static get singularName(): string;
7
7
  static get pluralName(): string;
8
8
  static get singularNameLowerCase(): string;
9
9
  static get pluralNameLowerCase(): string;
10
10
  static get singularNameCapitalized(): string;
11
11
  static get pluralNameCapitalized(): string;
12
- static validate<T>(item: T, isCreating: boolean): ValidationResult;
12
+ static validate<T>(item: T, isCreating: boolean): {
13
+ error?: Error;
14
+ value?: T;
15
+ };
13
16
  static getSearchFields(): string[];
14
17
  }
15
18
  //# sourceMappingURL=dynamic-entity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-entity.d.ts","sourceRoot":"","sources":["../../src/database/dynamic-entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAC;AAEpD,8BAAsB,aAAc,SAAQ,UAAU;IACpD,OAAc,MAAM,EAAE,MAAM,CAAC;IAC7B,OAAc,YAAY,EAAE,MAAM,CAAC;IAEnC,WAAkB,YAAY,IAAI,MAAM,CAEvC;IAED,WAAkB,UAAU,IAAI,MAAM,CAErC;IAED,WAAkB,qBAAqB,IAAI,MAAM,CAEhD;IAED,WAAkB,mBAAmB,IAAI,MAAM,CAE9C;IAED,WAAkB,uBAAuB,IAAI,MAAM,CAElD;IAED,WAAkB,qBAAqB,IAAI,MAAM,CAEhD;WAEa,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,OAAO,GAAG,gBAAgB;WAa3D,eAAe,IAAI,MAAM,EAAE;CAG1C"}
1
+ {"version":3,"file":"dynamic-entity.d.ts","sourceRoot":"","sources":["../../src/database/dynamic-entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8BAAsB,aAAc,SAAQ,UAAU;IACpD,OAAc,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC;IAClC,OAAc,YAAY,EAAE,CAAC,CAAC,SAAS,CAAC;IAExC,WAAkB,YAAY,IAAI,MAAM,CAEvC;IAED,WAAkB,UAAU,IAAI,MAAM,CAErC;IAED,WAAkB,qBAAqB,IAAI,MAAM,CAEhD;IAED,WAAkB,mBAAmB,IAAI,MAAM,CAE9C;IAED,WAAkB,uBAAuB,IAAI,MAAM,CAElD;IAED,WAAkB,qBAAqB,IAAI,MAAM,CAEhD;WAEa,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,OAAO,GAAG;QAAE,KAAK,CAAC,EAAE,KAAK,CAAC;QAAC,KAAK,CAAC,EAAE,CAAC,CAAA;KAAE;WAuBvE,eAAe,IAAI,MAAM,EAAE;CAG1C"}
@@ -1,6 +1,7 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
  import { BaseEntity } from "@mikro-orm/core";
4
+ import { z } from "zod";
4
5
  class DynamicEntity extends BaseEntity {
5
6
  static {
6
7
  __name(this, "DynamicEntity");
@@ -34,7 +35,16 @@ class DynamicEntity extends BaseEntity {
34
35
  if (!selectedSchema) {
35
36
  throw new Error("Schema not defined in entity.");
36
37
  }
37
- return selectedSchema.validate(item, { abortEarly: false });
38
+ try {
39
+ const value = selectedSchema.parse(item);
40
+ return { value };
41
+ } catch (err) {
42
+ if (err instanceof z.ZodError) {
43
+ const error = new Error(err.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", "));
44
+ return { error };
45
+ }
46
+ return { error: err };
47
+ }
38
48
  }
39
49
  static getSearchFields() {
40
50
  return [];
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/database/dynamic-entity.ts"],
4
- "sourcesContent": ["import { BaseEntity } from '@mikro-orm/core';\nimport type { Schema, ValidationResult } from 'joi';\n\nexport abstract class DynamicEntity extends BaseEntity {\n public static schema: Schema;\n public static schemaUpdate: Schema;\n\n public static get singularName(): string {\n return 'Item';\n }\n\n public static get pluralName(): string {\n return 'Items';\n }\n\n public static get singularNameLowerCase(): string {\n return this.singularName.toLowerCase();\n }\n\n public static get pluralNameLowerCase(): string {\n return this.pluralName.toLowerCase();\n }\n\n public static get singularNameCapitalized(): string {\n return this.singularName.charAt(0).toUpperCase() + this.singularName.slice(1).toLowerCase();\n }\n\n public static get pluralNameCapitalized(): string {\n return this.pluralName.charAt(0).toUpperCase() + this.pluralName.slice(1).toLowerCase();\n }\n\n public static validate<T>(item: T, isCreating: boolean): ValidationResult {\n const schemaName = isCreating ? 'schema' : 'schemaUpdate';\n // Explicit whitelist of schema properties to prevent object injection\n if (!['schema', 'schemaUpdate'].includes(schemaName)) {\n throw new Error('Invalid schema reference');\n }\n const selectedSchema: Schema | undefined = schemaName === 'schema' ? this.schema : this.schemaUpdate;\n if (!selectedSchema) {\n throw new Error('Schema not defined in entity.');\n }\n return selectedSchema.validate(item, { abortEarly: false });\n }\n\n public static getSearchFields(): string[] {\n return [];\n }\n}\n"],
5
- "mappings": ";;AAAA,SAAS,kBAAkB;AAGpB,MAAe,sBAAsB,WAAW;AAAA,EAHvD,OAGuD;AAAA;AAAA;AAAA,EACrD,OAAc;AAAA,EACd,OAAc;AAAA,EAEd,WAAkB,eAAuB;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,WAAkB,aAAqB;AACrC,WAAO;AAAA,EACT;AAAA,EAEA,WAAkB,wBAAgC;AAChD,WAAO,KAAK,aAAa,YAAY;AAAA,EACvC;AAAA,EAEA,WAAkB,sBAA8B;AAC9C,WAAO,KAAK,WAAW,YAAY;AAAA,EACrC;AAAA,EAEA,WAAkB,0BAAkC;AAClD,WAAO,KAAK,aAAa,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,aAAa,MAAM,CAAC,EAAE,YAAY;AAAA,EAC5F;AAAA,EAEA,WAAkB,wBAAgC;AAChD,WAAO,KAAK,WAAW,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,WAAW,MAAM,CAAC,EAAE,YAAY;AAAA,EACxF;AAAA,EAEA,OAAc,SAAY,MAAS,YAAuC;AACxE,UAAM,aAAa,aAAa,WAAW;AAE3C,QAAI,CAAC,CAAC,UAAU,cAAc,EAAE,SAAS,UAAU,GAAG;AACpD,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AACA,UAAM,iBAAqC,eAAe,WAAW,KAAK,SAAS,KAAK;AACxF,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AACA,WAAO,eAAe,SAAS,MAAM,EAAE,YAAY,MAAM,CAAC;AAAA,EAC5D;AAAA,EAEA,OAAc,kBAA4B;AACxC,WAAO,CAAC;AAAA,EACV;AACF;",
4
+ "sourcesContent": ["import { BaseEntity } from '@mikro-orm/core';\nimport { z } from 'zod';\n\nexport abstract class DynamicEntity extends BaseEntity {\n public static schema: z.ZodSchema;\n public static schemaUpdate: z.ZodSchema;\n\n public static get singularName(): string {\n return 'Item';\n }\n\n public static get pluralName(): string {\n return 'Items';\n }\n\n public static get singularNameLowerCase(): string {\n return this.singularName.toLowerCase();\n }\n\n public static get pluralNameLowerCase(): string {\n return this.pluralName.toLowerCase();\n }\n\n public static get singularNameCapitalized(): string {\n return this.singularName.charAt(0).toUpperCase() + this.singularName.slice(1).toLowerCase();\n }\n\n public static get pluralNameCapitalized(): string {\n return this.pluralName.charAt(0).toUpperCase() + this.pluralName.slice(1).toLowerCase();\n }\n\n public static validate<T>(item: T, isCreating: boolean): { error?: Error; value?: T } {\n const schemaName = isCreating ? 'schema' : 'schemaUpdate';\n // Explicit whitelist of schema properties to prevent object injection\n if (!['schema', 'schemaUpdate'].includes(schemaName)) {\n throw new Error('Invalid schema reference');\n }\n const selectedSchema: z.ZodSchema | undefined = schemaName === 'schema' ? this.schema : this.schemaUpdate;\n if (!selectedSchema) {\n throw new Error('Schema not defined in entity.');\n }\n\n try {\n const value = selectedSchema.parse(item);\n return { value: value as T };\n } catch (err) {\n if (err instanceof z.ZodError) {\n const error = new Error(err.issues.map((e: z.ZodIssue) => `${e.path.join('.')}: ${e.message}`).join(', '));\n return { error };\n }\n return { error: err as Error };\n }\n }\n\n public static getSearchFields(): string[] {\n return [];\n }\n}\n"],
5
+ "mappings": ";;AAAA,SAAS,kBAAkB;AAC3B,SAAS,SAAS;AAEX,MAAe,sBAAsB,WAAW;AAAA,EAHvD,OAGuD;AAAA;AAAA;AAAA,EACrD,OAAc;AAAA,EACd,OAAc;AAAA,EAEd,WAAkB,eAAuB;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,WAAkB,aAAqB;AACrC,WAAO;AAAA,EACT;AAAA,EAEA,WAAkB,wBAAgC;AAChD,WAAO,KAAK,aAAa,YAAY;AAAA,EACvC;AAAA,EAEA,WAAkB,sBAA8B;AAC9C,WAAO,KAAK,WAAW,YAAY;AAAA,EACrC;AAAA,EAEA,WAAkB,0BAAkC;AAClD,WAAO,KAAK,aAAa,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,aAAa,MAAM,CAAC,EAAE,YAAY;AAAA,EAC5F;AAAA,EAEA,WAAkB,wBAAgC;AAChD,WAAO,KAAK,WAAW,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,WAAW,MAAM,CAAC,EAAE,YAAY;AAAA,EACxF;AAAA,EAEA,OAAc,SAAY,MAAS,YAAmD;AACpF,UAAM,aAAa,aAAa,WAAW;AAE3C,QAAI,CAAC,CAAC,UAAU,cAAc,EAAE,SAAS,UAAU,GAAG;AACpD,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AACA,UAAM,iBAA0C,eAAe,WAAW,KAAK,SAAS,KAAK;AAC7F,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AAEA,QAAI;AACF,YAAM,QAAQ,eAAe,MAAM,IAAI;AACvC,aAAO,EAAE,MAAkB;AAAA,IAC7B,SAAS,KAAK;AACZ,UAAI,eAAe,EAAE,UAAU;AAC7B,cAAM,QAAQ,IAAI,MAAM,IAAI,OAAO,IAAI,CAAC,MAAkB,GAAG,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC;AACzG,eAAO,EAAE,MAAM;AAAA,MACjB;AACA,aAAO,EAAE,OAAO,IAAa;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,OAAc,kBAA4B;AACxC,WAAO,CAAC;AAAA,EACV;AACF;",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/database/manager.ts"],"names":[],"mappings":"AACA,OAAO,gBAAgB,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAIzE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;IAClC,OAAO,CAAC,MAAM,CAAyB;IAEvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IAErD,OAAO,CAAC,SAAS,CAA0B;IAE3C;;OAEG;gBACS,OAAO,EAAE,0BAA0B;IAI/C;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAiDjD;;OAEG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2CxC;;OAEG;IACI,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGlE"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/database/manager.ts"],"names":[],"mappings":"AACA,OAAO,gBAAgB,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAKzE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;IAClC,OAAO,CAAC,MAAM,CAAyB;IAEvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IAErD,OAAO,CAAC,SAAS,CAA0B;IAE3C;;OAEG;gBACS,OAAO,EAAE,0BAA0B;IAI/C;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAiDjD;;OAEG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2CxC;;OAEG;IACI,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGlE"}
@@ -4,6 +4,7 @@ import { MikroORM } from "@mikro-orm/postgresql";
4
4
  import DatabaseInstance from "./instance.js";
5
5
  import { Logger } from "../logger/index.js";
6
6
  import { DatabasePerformanceWrapper } from "../performance/index.js";
7
+ import { safeSerializeError } from "../error/error-reporter.js";
7
8
  class DatabaseManager {
8
9
  static {
9
10
  __name(this, "DatabaseManager");
@@ -48,7 +49,7 @@ class DatabaseManager {
48
49
  } catch (error) {
49
50
  const duration = performance.now() - startTime;
50
51
  this.logger.error({
51
- error: error instanceof Error ? error : new Error(String(error)),
52
+ error: error instanceof Error ? error : new Error(safeSerializeError(error)),
52
53
  message: "Database connection failed",
53
54
  meta: {
54
55
  Host: this.options.host,
@@ -86,7 +87,7 @@ class DatabaseManager {
86
87
  } catch (error) {
87
88
  const duration = performance.now() - startTime;
88
89
  this.logger.error({
89
- error: error instanceof Error ? error : new Error(String(error)),
90
+ error: error instanceof Error ? error : new Error(safeSerializeError(error)),
90
91
  message: "Database disconnection failed",
91
92
  meta: {
92
93
  Host: this.options.host,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/database/manager.ts"],
4
- "sourcesContent": ["import { MikroORM } from '@mikro-orm/postgresql';\nimport DatabaseInstance from './instance.js';\nimport type { ApplicationDatabaseOptions } from './manager.interface.js';\nimport { Logger } from '../logger/index.js';\nimport { DatabasePerformanceWrapper } from '../performance/index.js';\n\n/**\n * Database manager\n */\nexport default class DatabaseManager {\n private logger: typeof Logger = Logger;\n\n private readonly options: ApplicationDatabaseOptions;\n\n private instances: DatabaseInstance[] = [];\n\n /**\n * Database manager constructor\n */\n constructor(options: ApplicationDatabaseOptions) {\n this.options = options;\n }\n\n /**\n * Connect to database\n */\n public async connect(): Promise<DatabaseInstance> {\n return DatabasePerformanceWrapper.monitorConnection('connect', async () => {\n const startTime = performance.now();\n\n try {\n const orm = await MikroORM.init();\n\n const databaseInstance = new DatabaseInstance({\n databaseManager: this,\n applicationConfig: this.options.applicationConfig,\n orm,\n });\n\n this.instances.push(databaseInstance);\n\n const duration = performance.now() - startTime;\n const ormConfig = typeof orm.config?.getAll === 'function' ? orm.config.getAll() : undefined;\n const logMeta = {\n Host: ormConfig?.host ?? this.options.host,\n User: ormConfig?.user ?? this.options.username,\n Database: ormConfig?.dbName ?? this.options.databaseName,\n Duration: `${duration.toFixed(2)}ms`,\n };\n\n if (this.options.applicationConfig.log?.startUp) {\n this.log('Connected', logMeta);\n } else {\n this.logger.debug({ message: 'Database connected', meta: logMeta });\n }\n\n return databaseInstance;\n } catch (error) {\n const duration = performance.now() - startTime;\n\n this.logger.error({\n error: error instanceof Error ? error : new Error(String(error)),\n message: 'Database connection failed',\n meta: {\n Host: this.options.host,\n Database: this.options.databaseName,\n Duration: `${duration.toFixed(2)}ms`,\n },\n });\n\n throw error;\n }\n });\n }\n\n /**\n * Disconnect from database\n */\n public async disconnect(): Promise<void> {\n await DatabasePerformanceWrapper.monitorConnection('disconnect', async () => {\n const startTime = performance.now();\n const instanceCount = this.instances.length;\n\n try {\n await Promise.all(this.instances.map(instance => instance.disconnect()));\n\n const duration = performance.now() - startTime;\n\n if (instanceCount > 0) {\n const meta = {\n Host: this.options.host,\n Instances: instanceCount,\n Duration: `${duration.toFixed(2)}ms`,\n };\n\n if (this.options.applicationConfig.log?.startUp) {\n this.log('Disconnected all database instances', meta);\n } else {\n this.logger.debug({ message: 'Database instances disconnected', meta });\n }\n }\n\n this.instances = [];\n } catch (error) {\n const duration = performance.now() - startTime;\n\n this.logger.error({\n error: error instanceof Error ? error : new Error(String(error)),\n message: 'Database disconnection failed',\n meta: {\n Host: this.options.host,\n Duration: `${duration.toFixed(2)}ms`,\n Instances: instanceCount,\n },\n });\n\n throw error;\n }\n });\n }\n\n /**\n * Log database message\n */\n public log(message: string, meta?: Record<string, unknown>): void {\n this.logger.custom({ level: 'database', message, meta });\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { MikroORM } from '@mikro-orm/postgresql';\nimport DatabaseInstance from './instance.js';\nimport type { ApplicationDatabaseOptions } from './manager.interface.js';\nimport { Logger } from '../logger/index.js';\nimport { DatabasePerformanceWrapper } from '../performance/index.js';\nimport { safeSerializeError } from '../error/error-reporter.js';\n\n/**\n * Database manager\n */\nexport default class DatabaseManager {\n private logger: typeof Logger = Logger;\n\n private readonly options: ApplicationDatabaseOptions;\n\n private instances: DatabaseInstance[] = [];\n\n /**\n * Database manager constructor\n */\n constructor(options: ApplicationDatabaseOptions) {\n this.options = options;\n }\n\n /**\n * Connect to database\n */\n public async connect(): Promise<DatabaseInstance> {\n return DatabasePerformanceWrapper.monitorConnection('connect', async () => {\n const startTime = performance.now();\n\n try {\n const orm = await MikroORM.init();\n\n const databaseInstance = new DatabaseInstance({\n databaseManager: this,\n applicationConfig: this.options.applicationConfig,\n orm,\n });\n\n this.instances.push(databaseInstance);\n\n const duration = performance.now() - startTime;\n const ormConfig = typeof orm.config?.getAll === 'function' ? orm.config.getAll() : undefined;\n const logMeta = {\n Host: ormConfig?.host ?? this.options.host,\n User: ormConfig?.user ?? this.options.username,\n Database: ormConfig?.dbName ?? this.options.databaseName,\n Duration: `${duration.toFixed(2)}ms`,\n };\n\n if (this.options.applicationConfig.log?.startUp) {\n this.log('Connected', logMeta);\n } else {\n this.logger.debug({ message: 'Database connected', meta: logMeta });\n }\n\n return databaseInstance;\n } catch (error) {\n const duration = performance.now() - startTime;\n\n this.logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Database connection failed',\n meta: {\n Host: this.options.host,\n Database: this.options.databaseName,\n Duration: `${duration.toFixed(2)}ms`,\n },\n });\n\n throw error;\n }\n });\n }\n\n /**\n * Disconnect from database\n */\n public async disconnect(): Promise<void> {\n await DatabasePerformanceWrapper.monitorConnection('disconnect', async () => {\n const startTime = performance.now();\n const instanceCount = this.instances.length;\n\n try {\n await Promise.all(this.instances.map(instance => instance.disconnect()));\n\n const duration = performance.now() - startTime;\n\n if (instanceCount > 0) {\n const meta = {\n Host: this.options.host,\n Instances: instanceCount,\n Duration: `${duration.toFixed(2)}ms`,\n };\n\n if (this.options.applicationConfig.log?.startUp) {\n this.log('Disconnected all database instances', meta);\n } else {\n this.logger.debug({ message: 'Database instances disconnected', meta });\n }\n }\n\n this.instances = [];\n } catch (error) {\n const duration = performance.now() - startTime;\n\n this.logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Database disconnection failed',\n meta: {\n Host: this.options.host,\n Duration: `${duration.toFixed(2)}ms`,\n Instances: instanceCount,\n },\n });\n\n throw error;\n }\n });\n }\n\n /**\n * Log database message\n */\n public log(message: string, meta?: Record<string, unknown>): void {\n this.logger.custom({ level: 'database', message, meta });\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,24 @@
1
1
  import { type ErrorEnvelope, type ErrorReportOptions } from './error.interface.js';
2
+ /**
3
+ * Safely serialize any error to a string, handling circular references gracefully
4
+ *
5
+ * This utility handles MikroORM errors and other complex error objects that may
6
+ * contain circular references which would cause String(error) or JSON.stringify
7
+ * to fail.
8
+ *
9
+ * @param error - The error to serialize
10
+ * @returns String representation of the error
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * // Safe for MikroORM errors with circular entity metadata
15
+ * const message = safeSerializeError(mikroOrmError);
16
+ *
17
+ * // Works with any error type
18
+ * const message = safeSerializeError(unknownError);
19
+ * ```
20
+ */
21
+ export declare function safeSerializeError(error: unknown): string;
2
22
  /**
3
23
  * Centralized error reporter for the framework
4
24
  *
@@ -83,13 +103,6 @@ export declare class ErrorReporter {
83
103
  * @returns Sentry severity level
84
104
  */
85
105
  private mapSeverityToSentryLevel;
86
- /**
87
- * Serialize unknown error types to string
88
- *
89
- * @param error - Unknown error
90
- * @returns String representation
91
- */
92
- private serializeUnknownError;
93
106
  }
94
107
  declare const _default: ErrorReporter;
95
108
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"error-reporter.d.ts","sourceRoot":"","sources":["../../src/error/error-reporter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAa,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAiB,MAAM,sBAAsB,CAAC;AAG7G;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgB;IAEvC,OAAO;IAIP;;OAEG;WACW,WAAW,IAAI,aAAa;IAO1C;;;;;;;;;;;;OAYG;IACI,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,aAAa;IAiBlF;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAyDtB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IA8BhB;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;IAmB7B;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IA+BvB;;;;;OAKG;IACH,OAAO,CAAC,wBAAwB;IAiBhC;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;CAyB9B;;AAGD,wBAA2C"}
1
+ {"version":3,"file":"error-reporter.d.ts","sourceRoot":"","sources":["../../src/error/error-reporter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAa,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAiB,MAAM,sBAAsB,CAAC;AAG7G;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAiCzD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgB;IAEvC,OAAO;IAIP;;OAEG;WACW,WAAW,IAAI,aAAa;IAO1C;;;;;;;;;;;;OAYG;IACI,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,aAAa;IAiBlF;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAyDtB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IA8BhB;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;IAmB7B;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IA+BvB;;;;;OAKG;IACH,OAAO,CAAC,wBAAwB;CAgBjC;;AAGD,wBAA2C"}
@@ -5,6 +5,35 @@ import { getRequestId } from "../request-context/index.js";
5
5
  import Logger from "../logger/logger.js";
6
6
  import { ErrorCode, ErrorSeverity } from "./error.interface.js";
7
7
  import { FrameworkError } from "./framework-errors.js";
8
+ function safeSerializeError(error) {
9
+ try {
10
+ if (error === null) return "null";
11
+ if (error === void 0) return "undefined";
12
+ if (typeof error === "object") {
13
+ if ("message" in error && typeof error.message === "string") {
14
+ return error.message;
15
+ }
16
+ if ("toString" in error && typeof error.toString === "function") {
17
+ try {
18
+ const str = error.toString();
19
+ if (str !== "[object Object]") {
20
+ return str;
21
+ }
22
+ } catch {
23
+ }
24
+ }
25
+ try {
26
+ return JSON.stringify(error);
27
+ } catch {
28
+ return "[object Object] (circular reference detected)";
29
+ }
30
+ }
31
+ return String(error);
32
+ } catch {
33
+ return "Unknown error (serialization failed)";
34
+ }
35
+ }
36
+ __name(safeSerializeError, "safeSerializeError");
8
37
  class ErrorReporter {
9
38
  static {
10
39
  __name(this, "ErrorReporter");
@@ -90,7 +119,7 @@ class ErrorReporter {
90
119
  };
91
120
  }
92
121
  return {
93
- message: this.serializeUnknownError(error),
122
+ message: safeSerializeError(error),
94
123
  code: options?.code ?? ErrorCode.UNKNOWN,
95
124
  severity: options?.severity ?? ErrorSeverity.ERROR,
96
125
  requestId,
@@ -192,37 +221,11 @@ class ErrorReporter {
192
221
  return "error";
193
222
  }
194
223
  }
195
- /**
196
- * Serialize unknown error types to string
197
- *
198
- * @param error - Unknown error
199
- * @returns String representation
200
- */
201
- serializeUnknownError(error) {
202
- try {
203
- if (error === null) return "null";
204
- if (error === void 0) return "undefined";
205
- if (typeof error === "object") {
206
- if ("message" in error && typeof error.message === "string") {
207
- return error.message;
208
- }
209
- if ("toString" in error && typeof error.toString === "function") {
210
- const str = error.toString();
211
- if (str !== "[object Object]") {
212
- return str;
213
- }
214
- }
215
- return JSON.stringify(error);
216
- }
217
- return String(error);
218
- } catch {
219
- return "Unknown error (serialization failed)";
220
- }
221
- }
222
224
  }
223
225
  var error_reporter_default = ErrorReporter.getInstance();
224
226
  export {
225
227
  ErrorReporter,
226
- error_reporter_default as default
228
+ error_reporter_default as default,
229
+ safeSerializeError
227
230
  };
228
231
  //# sourceMappingURL=error-reporter.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/error/error-reporter.ts"],
4
- "sourcesContent": ["import * as Sentry from '@sentry/node';\nimport { getRequestId } from '../request-context/index.js';\nimport Logger from '../logger/logger.js';\nimport { ErrorCode, type ErrorEnvelope, type ErrorReportOptions, ErrorSeverity } from './error.interface.js';\nimport { FrameworkError } from './framework-errors.js';\n\n/**\n * Centralized error reporter for the framework\n *\n * Provides a unified interface for error reporting, normalization, logging,\n * and external error tracking (Sentry). Eliminates inconsistent error handling\n * and ensures all errors are properly structured and correlated.\n *\n * @example\n * ```typescript\n * const errorReporter = ErrorReporter.getInstance();\n *\n * // Report an error\n * errorReporter.report(error, {\n * context: { userId: '123', operation: 'fetchUser' },\n * severity: ErrorSeverity.CRITICAL\n * });\n *\n * // Report with custom code\n * errorReporter.report(\n * new Error('Database connection lost'),\n * {\n * code: ErrorCode.DATABASE_CONNECTION_FAILED,\n * captureInSentry: true\n * }\n * );\n * ```\n */\nexport class ErrorReporter {\n private static instance: ErrorReporter;\n\n private constructor() {\n // Private constructor for singleton\n }\n\n /**\n * Get the singleton instance\n */\n public static getInstance(): ErrorReporter {\n if (!ErrorReporter.instance) {\n ErrorReporter.instance = new ErrorReporter();\n }\n return ErrorReporter.instance;\n }\n\n /**\n * Report an error through the centralized error pipeline\n *\n * This method:\n * 1. Normalizes the error into a standard envelope\n * 2. Logs the error with appropriate severity\n * 3. Optionally captures the error in Sentry\n * 4. Adds request correlation if available\n *\n * @param error - The error to report (Error, string, or unknown)\n * @param options - Reporting options (context, severity, etc.)\n * @returns Normalized error envelope\n */\n public report(error: Error | unknown, options?: ErrorReportOptions): ErrorEnvelope {\n // Normalize the error into an envelope\n const envelope = this.normalizeError(error, options);\n\n // Log the error (unless explicitly disabled)\n if (options?.log !== false) {\n this.logError(envelope);\n }\n\n // Capture in Sentry (if enabled and error is significant enough)\n if (this.shouldCaptureInSentry(envelope, options)) {\n this.captureInSentry(error, envelope);\n }\n\n return envelope;\n }\n\n /**\n * Normalize any error into a standardized ErrorEnvelope\n *\n * @param error - The error to normalize\n * @param options - Optional configuration\n * @returns Normalized error envelope\n */\n private normalizeError(error: Error | unknown, options?: ErrorReportOptions): ErrorEnvelope {\n // Extract request ID from context (if available)\n const requestId = getRequestId();\n\n // Handle FrameworkError instances\n if (error instanceof FrameworkError) {\n return {\n message: error.message,\n code: options?.code ?? error.code,\n severity: options?.severity ?? error.severity,\n stack: error.stack,\n requestId,\n context: { ...error.context, ...options?.context },\n cause: error.cause,\n timestamp: error.timestamp,\n name: error.name,\n };\n }\n\n // Handle standard Error instances\n if (error instanceof Error) {\n return {\n message: error.message,\n code: options?.code ?? ErrorCode.UNKNOWN,\n severity: options?.severity ?? ErrorSeverity.ERROR,\n stack: error.stack,\n requestId,\n context: options?.context,\n cause: error.cause,\n timestamp: new Date(),\n name: error.name,\n };\n }\n\n // Handle string errors\n if (typeof error === 'string') {\n return {\n message: error,\n code: options?.code ?? ErrorCode.UNKNOWN,\n severity: options?.severity ?? ErrorSeverity.ERROR,\n requestId,\n context: options?.context,\n timestamp: new Date(),\n };\n }\n\n // Handle unknown error types\n return {\n message: this.serializeUnknownError(error),\n code: options?.code ?? ErrorCode.UNKNOWN,\n severity: options?.severity ?? ErrorSeverity.ERROR,\n requestId,\n context: { ...options?.context, originalError: error },\n timestamp: new Date(),\n };\n }\n\n /**\n * Log the error with appropriate severity\n *\n * @param envelope - Normalized error envelope\n */\n private logError(envelope: ErrorEnvelope): void {\n const meta: Record<string, unknown> = {\n code: envelope.code,\n severity: envelope.severity,\n };\n\n if (envelope.requestId) {\n meta.requestId = envelope.requestId;\n }\n\n if (envelope.context) {\n Object.assign(meta, envelope.context);\n }\n\n // Map severity to logger level\n switch (envelope.severity) {\n case ErrorSeverity.FATAL:\n case ErrorSeverity.CRITICAL:\n case ErrorSeverity.ERROR:\n Logger.error({ error: envelope.message, meta });\n break;\n case ErrorSeverity.WARNING:\n Logger.warn({ message: envelope.message, meta });\n break;\n case ErrorSeverity.INFO:\n Logger.info({ message: envelope.message, meta });\n break;\n }\n }\n\n /**\n * Determine if error should be captured in Sentry\n *\n * @param envelope - Normalized error envelope\n * @param options - Reporting options\n * @returns Whether to capture in Sentry\n */\n private shouldCaptureInSentry(envelope: ErrorEnvelope, options?: ErrorReportOptions): boolean {\n // Explicitly disabled\n if (options?.captureInSentry === false) {\n return false;\n }\n\n // Explicitly enabled\n if (options?.captureInSentry === true) {\n return true;\n }\n\n // Auto-capture for errors and above (not warnings/info)\n return (\n envelope.severity === ErrorSeverity.FATAL ||\n envelope.severity === ErrorSeverity.CRITICAL ||\n envelope.severity === ErrorSeverity.ERROR\n );\n }\n\n /**\n * Capture error in Sentry with enriched context\n *\n * @param error - Original error\n * @param envelope - Normalized error envelope\n */\n private captureInSentry(error: Error | unknown, envelope: ErrorEnvelope): void {\n // Only capture if Sentry is initialized\n if (!Logger.isSentryInitialized) {\n return;\n }\n\n // Prepare Sentry scope with enriched context\n Sentry.withScope(scope => {\n // Add severity\n scope.setLevel(this.mapSeverityToSentryLevel(envelope.severity));\n\n // Add tags\n scope.setTag('error_code', envelope.code);\n if (envelope.requestId) {\n scope.setTag('request_id', envelope.requestId);\n }\n\n // Add context\n if (envelope.context) {\n scope.setContext('error_context', envelope.context);\n }\n\n // Capture the error\n if (error instanceof Error) {\n Sentry.captureException(error);\n } else {\n Sentry.captureMessage(envelope.message, 'error');\n }\n });\n }\n\n /**\n * Map framework error severity to Sentry severity level\n *\n * @param severity - Framework error severity\n * @returns Sentry severity level\n */\n private mapSeverityToSentryLevel(severity: ErrorSeverity): Sentry.SeverityLevel {\n switch (severity) {\n case ErrorSeverity.FATAL:\n return 'fatal';\n case ErrorSeverity.CRITICAL:\n return 'error';\n case ErrorSeverity.ERROR:\n return 'error';\n case ErrorSeverity.WARNING:\n return 'warning';\n case ErrorSeverity.INFO:\n return 'info';\n default:\n return 'error';\n }\n }\n\n /**\n * Serialize unknown error types to string\n *\n * @param error - Unknown error\n * @returns String representation\n */\n private serializeUnknownError(error: unknown): string {\n try {\n if (error === null) return 'null';\n if (error === undefined) return 'undefined';\n\n if (typeof error === 'object') {\n // Try to extract meaningful properties\n if ('message' in error && typeof error.message === 'string') {\n return error.message;\n }\n if ('toString' in error && typeof error.toString === 'function') {\n const str = error.toString();\n if (str !== '[object Object]') {\n return str;\n }\n }\n // Fallback to JSON stringification\n return JSON.stringify(error);\n }\n\n return String(error);\n } catch {\n return 'Unknown error (serialization failed)';\n }\n }\n}\n\n// Export singleton instance for convenience\nexport default ErrorReporter.getInstance();\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import * as Sentry from '@sentry/node';\nimport { getRequestId } from '../request-context/index.js';\nimport Logger from '../logger/logger.js';\nimport { ErrorCode, type ErrorEnvelope, type ErrorReportOptions, ErrorSeverity } from './error.interface.js';\nimport { FrameworkError } from './framework-errors.js';\n\n/**\n * Safely serialize any error to a string, handling circular references gracefully\n *\n * This utility handles MikroORM errors and other complex error objects that may\n * contain circular references which would cause String(error) or JSON.stringify\n * to fail.\n *\n * @param error - The error to serialize\n * @returns String representation of the error\n *\n * @example\n * ```typescript\n * // Safe for MikroORM errors with circular entity metadata\n * const message = safeSerializeError(mikroOrmError);\n *\n * // Works with any error type\n * const message = safeSerializeError(unknownError);\n * ```\n */\nexport function safeSerializeError(error: unknown): string {\n try {\n if (error === null) return 'null';\n if (error === undefined) return 'undefined';\n\n if (typeof error === 'object') {\n // Try to extract meaningful properties\n if ('message' in error && typeof error.message === 'string') {\n return error.message;\n }\n if ('toString' in error && typeof error.toString === 'function') {\n try {\n const str = error.toString();\n if (str !== '[object Object]') {\n return str;\n }\n } catch {\n // toString() itself may throw\n }\n }\n // Fallback to JSON stringification with circular reference handling\n try {\n return JSON.stringify(error);\n } catch {\n // JSON.stringify can fail on circular references\n return '[object Object] (circular reference detected)';\n }\n }\n\n return String(error);\n } catch {\n return 'Unknown error (serialization failed)';\n }\n}\n\n/**\n * Centralized error reporter for the framework\n *\n * Provides a unified interface for error reporting, normalization, logging,\n * and external error tracking (Sentry). Eliminates inconsistent error handling\n * and ensures all errors are properly structured and correlated.\n *\n * @example\n * ```typescript\n * const errorReporter = ErrorReporter.getInstance();\n *\n * // Report an error\n * errorReporter.report(error, {\n * context: { userId: '123', operation: 'fetchUser' },\n * severity: ErrorSeverity.CRITICAL\n * });\n *\n * // Report with custom code\n * errorReporter.report(\n * new Error('Database connection lost'),\n * {\n * code: ErrorCode.DATABASE_CONNECTION_FAILED,\n * captureInSentry: true\n * }\n * );\n * ```\n */\nexport class ErrorReporter {\n private static instance: ErrorReporter;\n\n private constructor() {\n // Private constructor for singleton\n }\n\n /**\n * Get the singleton instance\n */\n public static getInstance(): ErrorReporter {\n if (!ErrorReporter.instance) {\n ErrorReporter.instance = new ErrorReporter();\n }\n return ErrorReporter.instance;\n }\n\n /**\n * Report an error through the centralized error pipeline\n *\n * This method:\n * 1. Normalizes the error into a standard envelope\n * 2. Logs the error with appropriate severity\n * 3. Optionally captures the error in Sentry\n * 4. Adds request correlation if available\n *\n * @param error - The error to report (Error, string, or unknown)\n * @param options - Reporting options (context, severity, etc.)\n * @returns Normalized error envelope\n */\n public report(error: Error | unknown, options?: ErrorReportOptions): ErrorEnvelope {\n // Normalize the error into an envelope\n const envelope = this.normalizeError(error, options);\n\n // Log the error (unless explicitly disabled)\n if (options?.log !== false) {\n this.logError(envelope);\n }\n\n // Capture in Sentry (if enabled and error is significant enough)\n if (this.shouldCaptureInSentry(envelope, options)) {\n this.captureInSentry(error, envelope);\n }\n\n return envelope;\n }\n\n /**\n * Normalize any error into a standardized ErrorEnvelope\n *\n * @param error - The error to normalize\n * @param options - Optional configuration\n * @returns Normalized error envelope\n */\n private normalizeError(error: Error | unknown, options?: ErrorReportOptions): ErrorEnvelope {\n // Extract request ID from context (if available)\n const requestId = getRequestId();\n\n // Handle FrameworkError instances\n if (error instanceof FrameworkError) {\n return {\n message: error.message,\n code: options?.code ?? error.code,\n severity: options?.severity ?? error.severity,\n stack: error.stack,\n requestId,\n context: { ...error.context, ...options?.context },\n cause: error.cause,\n timestamp: error.timestamp,\n name: error.name,\n };\n }\n\n // Handle standard Error instances\n if (error instanceof Error) {\n return {\n message: error.message,\n code: options?.code ?? ErrorCode.UNKNOWN,\n severity: options?.severity ?? ErrorSeverity.ERROR,\n stack: error.stack,\n requestId,\n context: options?.context,\n cause: error.cause,\n timestamp: new Date(),\n name: error.name,\n };\n }\n\n // Handle string errors\n if (typeof error === 'string') {\n return {\n message: error,\n code: options?.code ?? ErrorCode.UNKNOWN,\n severity: options?.severity ?? ErrorSeverity.ERROR,\n requestId,\n context: options?.context,\n timestamp: new Date(),\n };\n }\n\n // Handle unknown error types\n return {\n message: safeSerializeError(error),\n code: options?.code ?? ErrorCode.UNKNOWN,\n severity: options?.severity ?? ErrorSeverity.ERROR,\n requestId,\n context: { ...options?.context, originalError: error },\n timestamp: new Date(),\n };\n }\n\n /**\n * Log the error with appropriate severity\n *\n * @param envelope - Normalized error envelope\n */\n private logError(envelope: ErrorEnvelope): void {\n const meta: Record<string, unknown> = {\n code: envelope.code,\n severity: envelope.severity,\n };\n\n if (envelope.requestId) {\n meta.requestId = envelope.requestId;\n }\n\n if (envelope.context) {\n Object.assign(meta, envelope.context);\n }\n\n // Map severity to logger level\n switch (envelope.severity) {\n case ErrorSeverity.FATAL:\n case ErrorSeverity.CRITICAL:\n case ErrorSeverity.ERROR:\n Logger.error({ error: envelope.message, meta });\n break;\n case ErrorSeverity.WARNING:\n Logger.warn({ message: envelope.message, meta });\n break;\n case ErrorSeverity.INFO:\n Logger.info({ message: envelope.message, meta });\n break;\n }\n }\n\n /**\n * Determine if error should be captured in Sentry\n *\n * @param envelope - Normalized error envelope\n * @param options - Reporting options\n * @returns Whether to capture in Sentry\n */\n private shouldCaptureInSentry(envelope: ErrorEnvelope, options?: ErrorReportOptions): boolean {\n // Explicitly disabled\n if (options?.captureInSentry === false) {\n return false;\n }\n\n // Explicitly enabled\n if (options?.captureInSentry === true) {\n return true;\n }\n\n // Auto-capture for errors and above (not warnings/info)\n return (\n envelope.severity === ErrorSeverity.FATAL ||\n envelope.severity === ErrorSeverity.CRITICAL ||\n envelope.severity === ErrorSeverity.ERROR\n );\n }\n\n /**\n * Capture error in Sentry with enriched context\n *\n * @param error - Original error\n * @param envelope - Normalized error envelope\n */\n private captureInSentry(error: Error | unknown, envelope: ErrorEnvelope): void {\n // Only capture if Sentry is initialized\n if (!Logger.isSentryInitialized) {\n return;\n }\n\n // Prepare Sentry scope with enriched context\n Sentry.withScope(scope => {\n // Add severity\n scope.setLevel(this.mapSeverityToSentryLevel(envelope.severity));\n\n // Add tags\n scope.setTag('error_code', envelope.code);\n if (envelope.requestId) {\n scope.setTag('request_id', envelope.requestId);\n }\n\n // Add context\n if (envelope.context) {\n scope.setContext('error_context', envelope.context);\n }\n\n // Capture the error\n if (error instanceof Error) {\n Sentry.captureException(error);\n } else {\n Sentry.captureMessage(envelope.message, 'error');\n }\n });\n }\n\n /**\n * Map framework error severity to Sentry severity level\n *\n * @param severity - Framework error severity\n * @returns Sentry severity level\n */\n private mapSeverityToSentryLevel(severity: ErrorSeverity): Sentry.SeverityLevel {\n switch (severity) {\n case ErrorSeverity.FATAL:\n return 'fatal';\n case ErrorSeverity.CRITICAL:\n return 'error';\n case ErrorSeverity.ERROR:\n return 'error';\n case ErrorSeverity.WARNING:\n return 'warning';\n case ErrorSeverity.INFO:\n return 'info';\n default:\n return 'error';\n }\n }\n}\n\n// Export singleton instance for convenience\nexport default ErrorReporter.getInstance();\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  export type { ErrorEnvelope, ErrorReportOptions } from './error.interface.js';
2
2
  export { ErrorCode, ErrorSeverity } from './error.interface.js';
3
- export { ErrorReporter } from './error-reporter.js';
3
+ export { ErrorReporter, safeSerializeError } from './error-reporter.js';
4
4
  export { FrameworkError, ConfigurationError, ValidationError, DatabaseError, RedisError, QueueError, WebServerError, WebSocketError, LifecycleError, ResourceNotFoundError, NotImplementedError, } from './framework-errors.js';
5
5
  export { default as errorReporter } from './error-reporter.js';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/error/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/error/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { ErrorCode, ErrorSeverity } from "./error.interface.js";
2
- import { ErrorReporter } from "./error-reporter.js";
2
+ import { ErrorReporter, safeSerializeError } from "./error-reporter.js";
3
3
  import {
4
4
  FrameworkError,
5
5
  ConfigurationError,
@@ -29,6 +29,7 @@ export {
29
29
  ValidationError,
30
30
  WebServerError,
31
31
  WebSocketError,
32
- default2 as errorReporter
32
+ default2 as errorReporter,
33
+ safeSerializeError
33
34
  };
34
35
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/error/index.ts"],
4
- "sourcesContent": ["export type { ErrorEnvelope, ErrorReportOptions } from './error.interface.js';\nexport { ErrorCode, ErrorSeverity } from './error.interface.js';\nexport { ErrorReporter } from './error-reporter.js';\nexport {\n FrameworkError,\n ConfigurationError,\n ValidationError,\n DatabaseError,\n RedisError,\n QueueError,\n WebServerError,\n WebSocketError,\n LifecycleError,\n ResourceNotFoundError,\n NotImplementedError,\n} from './framework-errors.js';\n\n// Export default instance for convenience\nexport { default as errorReporter } from './error-reporter.js';\n"],
5
- "mappings": "AACA,SAAS,WAAW,qBAAqB;AACzC,SAAS,qBAAqB;AAC9B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAoB,WAAXA,gBAAgC;",
4
+ "sourcesContent": ["export type { ErrorEnvelope, ErrorReportOptions } from './error.interface.js';\nexport { ErrorCode, ErrorSeverity } from './error.interface.js';\nexport { ErrorReporter, safeSerializeError } from './error-reporter.js';\nexport {\n FrameworkError,\n ConfigurationError,\n ValidationError,\n DatabaseError,\n RedisError,\n QueueError,\n WebServerError,\n WebSocketError,\n LifecycleError,\n ResourceNotFoundError,\n NotImplementedError,\n} from './framework-errors.js';\n\n// Export default instance for convenience\nexport { default as errorReporter } from './error-reporter.js';\n"],
5
+ "mappings": "AACA,SAAS,WAAW,qBAAqB;AACzC,SAAS,eAAe,0BAA0B;AAClD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAoB,WAAXA,gBAAgC;",
6
6
  "names": ["default"]
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/event/controller/base.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AAEzF,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,mBAAmB;IAC/C,SAAS,CAAC,MAAM,EAAE,OAAO,MAAM,CAAU;IAEzC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAEvC,SAAS,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAE/C,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IAEvC,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;gBAExC,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,EAAE,gCAAgC;IAUpG;;OAEG;IACI,GAAG;uBACO,KAAK,GAAG,OAAO,YAAY,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;wBAavE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;wBAI7C,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;yBAI5C,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;MAG9D;CACH"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/event/controller/base.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AAGzF,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,mBAAmB;IAC/C,SAAS,CAAC,MAAM,EAAE,OAAO,MAAM,CAAU;IAEzC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAEvC,SAAS,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAE/C,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IAEvC,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;gBAExC,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,EAAE,gCAAgC;IAUpG;;OAEG;IACI,GAAG;uBACO,KAAK,GAAG,OAAO,YAAY,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;wBAavE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;wBAI7C,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;yBAI5C,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;MAG9D;CACH"}