@scpxl/nodejs-framework 1.0.17 → 1.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/dist/api-requester/api-requester.d.ts +27 -6
- package/dist/api-requester/api-requester.d.ts.map +1 -1
- package/dist/api-requester/api-requester.js +188 -26
- package/dist/api-requester/api-requester.js.map +2 -2
- package/dist/api-requester/index.d.ts +1 -0
- package/dist/api-requester/index.d.ts.map +1 -1
- package/dist/api-requester/index.js.map +1 -1
- package/dist/application/base-application.d.ts +15 -22
- package/dist/application/base-application.d.ts.map +1 -1
- package/dist/application/base-application.js +145 -111
- package/dist/application/base-application.js.map +2 -2
- package/dist/application/command-application.d.ts.map +1 -1
- package/dist/application/command-application.js +3 -4
- package/dist/application/command-application.js.map +2 -2
- package/dist/application/web-application.d.ts.map +1 -1
- package/dist/application/web-application.js +9 -2
- package/dist/application/web-application.js.map +2 -2
- package/dist/cache/manager.d.ts +87 -6
- package/dist/cache/manager.d.ts.map +1 -1
- package/dist/cache/manager.js +77 -30
- package/dist/cache/manager.js.map +2 -2
- package/dist/cluster/cluster-manager.d.ts.map +1 -1
- package/dist/cluster/cluster-manager.js +5 -8
- package/dist/cluster/cluster-manager.js.map +2 -2
- package/dist/config/env.d.ts +11 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +103 -0
- package/dist/config/env.js.map +7 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +7 -0
- package/dist/config/schema.d.ts +408 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +218 -0
- package/dist/config/schema.js.map +7 -0
- package/dist/database/dynamic-entity.d.ts.map +1 -1
- package/dist/database/dynamic-entity.js +6 -2
- package/dist/database/dynamic-entity.js.map +2 -2
- package/dist/database/instance.d.ts.map +1 -1
- package/dist/database/instance.js +0 -8
- package/dist/database/instance.js.map +2 -2
- package/dist/database/manager.d.ts.map +1 -1
- package/dist/database/manager.js +71 -9
- package/dist/database/manager.js.map +2 -2
- package/dist/error/error-reporter.d.ts +96 -0
- package/dist/error/error-reporter.d.ts.map +1 -0
- package/dist/error/error-reporter.js +228 -0
- package/dist/error/error-reporter.js.map +7 -0
- package/dist/error/error.interface.d.ts +126 -0
- package/dist/error/error.interface.d.ts.map +1 -0
- package/dist/error/error.interface.js +45 -0
- package/dist/error/error.interface.js.map +7 -0
- package/dist/error/framework-errors.d.ts +113 -0
- package/dist/error/framework-errors.d.ts.map +1 -0
- package/dist/error/framework-errors.js +176 -0
- package/dist/error/framework-errors.js.map +7 -0
- package/dist/error/index.d.ts +6 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/index.js +34 -0
- package/dist/error/index.js.map +7 -0
- package/dist/event/manager.d.ts.map +1 -1
- package/dist/event/manager.js +2 -9
- package/dist/event/manager.js.map +2 -2
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +2 -2
- package/dist/lifecycle/exit.d.ts +2 -1
- package/dist/lifecycle/exit.d.ts.map +1 -1
- package/dist/lifecycle/exit.js +6 -0
- package/dist/lifecycle/exit.js.map +2 -2
- package/dist/lifecycle/index.d.ts +7 -0
- package/dist/lifecycle/index.d.ts.map +1 -0
- package/dist/lifecycle/index.js +12 -0
- package/dist/lifecycle/index.js.map +7 -0
- package/dist/lifecycle/lifecycle-manager.d.ts +55 -2
- package/dist/lifecycle/lifecycle-manager.d.ts.map +1 -1
- package/dist/lifecycle/lifecycle-manager.js +233 -7
- package/dist/lifecycle/lifecycle-manager.js.map +3 -3
- package/dist/lifecycle/shutdown-controller.d.ts +15 -0
- package/dist/lifecycle/shutdown-controller.d.ts.map +1 -0
- package/dist/lifecycle/shutdown-controller.js +38 -0
- package/dist/lifecycle/shutdown-controller.js.map +7 -0
- package/dist/lifecycle/types.d.ts +28 -0
- package/dist/lifecycle/types.d.ts.map +1 -0
- package/dist/lifecycle/types.js +13 -0
- package/dist/lifecycle/types.js.map +7 -0
- package/dist/logger/logger.d.ts +2 -1
- package/dist/logger/logger.d.ts.map +1 -1
- package/dist/logger/logger.js +35 -11
- package/dist/logger/logger.js.map +2 -2
- package/dist/performance/cache-performance.d.ts +6 -0
- package/dist/performance/cache-performance.d.ts.map +1 -1
- package/dist/performance/cache-performance.js +16 -0
- package/dist/performance/cache-performance.js.map +2 -2
- package/dist/performance/index.d.ts +1 -0
- package/dist/performance/index.d.ts.map +1 -1
- package/dist/performance/index.js +1 -0
- package/dist/performance/index.js.map +2 -2
- package/dist/performance/performance-monitor.d.ts.map +1 -1
- package/dist/performance/performance-monitor.js +47 -18
- package/dist/performance/performance-monitor.js.map +2 -2
- package/dist/performance/performance-monitor.plugin.d.ts +24 -0
- package/dist/performance/performance-monitor.plugin.d.ts.map +1 -0
- package/dist/performance/performance-monitor.plugin.js +89 -0
- package/dist/performance/performance-monitor.plugin.js.map +7 -0
- package/dist/performance/webserver-performance.js +1 -1
- package/dist/performance/webserver-performance.js.map +2 -2
- package/dist/queue/manager.d.ts.map +1 -1
- package/dist/queue/manager.js +3 -10
- package/dist/queue/manager.js.map +2 -2
- package/dist/queue/worker.d.ts.map +1 -1
- package/dist/queue/worker.js +2 -2
- package/dist/queue/worker.js.map +2 -2
- package/dist/redis/manager.d.ts.map +1 -1
- package/dist/redis/manager.js +228 -33
- package/dist/redis/manager.js.map +2 -2
- package/dist/request-context/index.d.ts +3 -0
- package/dist/request-context/index.d.ts.map +1 -0
- package/dist/request-context/index.js +25 -0
- package/dist/request-context/index.js.map +7 -0
- package/dist/request-context/request-context.d.ts +108 -0
- package/dist/request-context/request-context.d.ts.map +1 -0
- package/dist/request-context/request-context.interface.d.ts +46 -0
- package/dist/request-context/request-context.interface.d.ts.map +1 -0
- package/dist/request-context/request-context.interface.js +1 -0
- package/dist/request-context/request-context.interface.js.map +7 -0
- package/dist/request-context/request-context.js +79 -0
- package/dist/request-context/request-context.js.map +7 -0
- package/dist/services/aws/s3.js +4 -6
- package/dist/services/aws/s3.js.map +2 -2
- package/dist/util/file.d.ts +13 -0
- package/dist/util/file.d.ts.map +1 -1
- package/dist/util/file.js +46 -9
- package/dist/util/file.js.map +2 -2
- package/dist/util/helper.d.ts +16 -1
- package/dist/util/helper.d.ts.map +1 -1
- package/dist/util/helper.js +19 -43
- package/dist/util/helper.js.map +2 -2
- package/dist/util/index.d.ts +1 -0
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +18 -16
- package/dist/util/index.js.map +2 -2
- package/dist/util/loader.d.ts.map +1 -1
- package/dist/util/loader.js +13 -2
- package/dist/util/loader.js.map +2 -2
- package/dist/util/os.d.ts.map +1 -1
- package/dist/util/os.js +8 -14
- package/dist/util/os.js.map +2 -2
- package/dist/util/time.d.ts +8 -2
- package/dist/util/time.d.ts.map +1 -1
- package/dist/util/time.js +12 -7
- package/dist/util/time.js.map +2 -2
- package/dist/util/timing.d.ts +36 -0
- package/dist/util/timing.d.ts.map +1 -0
- package/dist/util/timing.interface.d.ts +47 -0
- package/dist/util/timing.interface.d.ts.map +1 -0
- package/dist/util/timing.interface.js +1 -0
- package/dist/util/timing.interface.js.map +7 -0
- package/dist/util/timing.js +98 -0
- package/dist/util/timing.js.map +7 -0
- package/dist/util/url.js +1 -1
- package/dist/util/url.js.map +2 -2
- package/dist/webserver/controller/base.d.ts +3 -1
- package/dist/webserver/controller/base.d.ts.map +1 -1
- package/dist/webserver/controller/base.interface.d.ts +2 -0
- package/dist/webserver/controller/base.interface.d.ts.map +1 -1
- package/dist/webserver/controller/base.js +4 -1
- package/dist/webserver/controller/base.js.map +2 -2
- package/dist/webserver/controller/health.d.ts +8 -1
- package/dist/webserver/controller/health.d.ts.map +1 -1
- package/dist/webserver/controller/health.js +36 -22
- package/dist/webserver/controller/health.js.map +2 -2
- package/dist/webserver/webserver.d.ts +16 -2
- package/dist/webserver/webserver.d.ts.map +1 -1
- package/dist/webserver/webserver.interface.d.ts +37 -0
- package/dist/webserver/webserver.interface.d.ts.map +1 -1
- package/dist/webserver/webserver.interface.js.map +2 -2
- package/dist/webserver/webserver.js +117 -20
- package/dist/webserver/webserver.js.map +2 -2
- package/dist/websocket/controllers/server/system.d.ts.map +1 -1
- package/dist/websocket/controllers/server/system.js.map +2 -2
- package/dist/websocket/websocket-base.d.ts.map +1 -1
- package/dist/websocket/websocket-base.js +2 -3
- package/dist/websocket/websocket-base.js.map +2 -2
- package/dist/websocket/websocket-server.d.ts +1 -1
- package/dist/websocket/websocket-server.d.ts.map +1 -1
- package/dist/websocket/websocket-server.js +7 -31
- package/dist/websocket/websocket-server.js.map +2 -2
- package/package.json +51 -10
|
@@ -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;
|
|
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"}
|
|
@@ -27,10 +27,14 @@ class DynamicEntity extends BaseEntity {
|
|
|
27
27
|
}
|
|
28
28
|
static validate(item, isCreating) {
|
|
29
29
|
const schemaName = isCreating ? "schema" : "schemaUpdate";
|
|
30
|
-
if (!
|
|
30
|
+
if (!["schema", "schemaUpdate"].includes(schemaName)) {
|
|
31
|
+
throw new Error("Invalid schema reference");
|
|
32
|
+
}
|
|
33
|
+
const selectedSchema = schemaName === "schema" ? this.schema : this.schemaUpdate;
|
|
34
|
+
if (!selectedSchema) {
|
|
31
35
|
throw new Error("Schema not defined in entity.");
|
|
32
36
|
}
|
|
33
|
-
return
|
|
37
|
+
return selectedSchema.validate(item, { abortEarly: false });
|
|
34
38
|
}
|
|
35
39
|
static getSearchFields() {
|
|
36
40
|
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\n if (!
|
|
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,
|
|
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;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/database/instance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AACtF,OAAO,KAAK,eAAe,MAAM,cAAc,CAAC;AAEhD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC,uBAAuB;IACvB,OAAO,CAAC,eAAe,CAAkB;IAEzC,yBAAyB;IACzB,OAAO,CAAC,iBAAiB,CAAoB;IAE7C,wBAAwB;IACxB,OAAO,CAAC,GAAG,CAAW;IAEtB;;;OAGG;gBACS,EACV,eAAe,EACf,iBAAiB,EACjB,GAAG,GACJ,EAAE;QACD,eAAe,EAAE,eAAe,CAAC;QACjC,iBAAiB,EAAE,iBAAiB,CAAC;QACrC,GAAG,EAAE,QAAQ,CAAC;KACf;
|
|
1
|
+
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/database/instance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AACtF,OAAO,KAAK,eAAe,MAAM,cAAc,CAAC;AAEhD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC,uBAAuB;IACvB,OAAO,CAAC,eAAe,CAAkB;IAEzC,yBAAyB;IACzB,OAAO,CAAC,iBAAiB,CAAoB;IAE7C,wBAAwB;IACxB,OAAO,CAAC,GAAG,CAAW;IAEtB;;;OAGG;gBACS,EACV,eAAe,EACf,iBAAiB,EACjB,GAAG,GACJ,EAAE;QACD,eAAe,EAAE,eAAe,CAAC;QACjC,iBAAiB,EAAE,iBAAiB,CAAC;QACrC,GAAG,EAAE,QAAQ,CAAC;KACf;IAMD;;OAEG;IACI,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAItC;;OAEG;IACI,gBAAgB,IAAI,aAAa;IAIxC;;OAEG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAKzC"}
|
|
@@ -22,14 +22,6 @@ class DatabaseInstance {
|
|
|
22
22
|
this.databaseManager = databaseManager;
|
|
23
23
|
this.applicationConfig = applicationConfig;
|
|
24
24
|
this.orm = orm;
|
|
25
|
-
const config = orm.config.getAll();
|
|
26
|
-
if (this.applicationConfig.log?.startUp) {
|
|
27
|
-
this.databaseManager.log("Connected", {
|
|
28
|
-
Host: config.host,
|
|
29
|
-
User: config.user,
|
|
30
|
-
Database: config.dbName
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
25
|
}
|
|
34
26
|
/**
|
|
35
27
|
* Check if database is connected
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/database/instance.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager, MikroORM } from '@mikro-orm/postgresql';\nimport type { ApplicationConfig } from '../application/base-application.interface.js';\nimport type DatabaseManager from './manager.js';\n\n/**\n * Database Instance\n */\nexport default class DatabaseInstance {\n /** Database manager */\n private databaseManager: DatabaseManager;\n\n /** Application config */\n private applicationConfig: ApplicationConfig;\n\n /** MikroORM instance */\n private orm: MikroORM;\n\n /**\n * Database Instance constructor\n * @param orm MikroORM instance\n */\n constructor({\n databaseManager,\n applicationConfig,\n orm,\n }: {\n databaseManager: DatabaseManager;\n applicationConfig: ApplicationConfig;\n orm: MikroORM;\n }) {\n this.databaseManager = databaseManager;\n this.applicationConfig = applicationConfig;\n this.orm = orm;\n
|
|
5
|
-
"mappings": ";;AAOA,MAAO,iBAA+B;AAAA,EAPtC,OAOsC;AAAA;AAAA;AAAA;AAAA,EAE5B;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAIG;AACD,SAAK,kBAAkB;AACvB,SAAK,oBAAoB;AACzB,SAAK,MAAM;
|
|
4
|
+
"sourcesContent": ["import type { EntityManager, MikroORM } from '@mikro-orm/postgresql';\nimport type { ApplicationConfig } from '../application/base-application.interface.js';\nimport type DatabaseManager from './manager.js';\n\n/**\n * Database Instance\n */\nexport default class DatabaseInstance {\n /** Database manager */\n private databaseManager: DatabaseManager;\n\n /** Application config */\n private applicationConfig: ApplicationConfig;\n\n /** MikroORM instance */\n private orm: MikroORM;\n\n /**\n * Database Instance constructor\n * @param orm MikroORM instance\n */\n constructor({\n databaseManager,\n applicationConfig,\n orm,\n }: {\n databaseManager: DatabaseManager;\n applicationConfig: ApplicationConfig;\n orm: MikroORM;\n }) {\n this.databaseManager = databaseManager;\n this.applicationConfig = applicationConfig;\n this.orm = orm;\n }\n\n /**\n * Check if database is connected\n */\n public isConnected(): Promise<boolean> {\n return this.orm.isConnected();\n }\n\n /**\n * Get EntityManager\n */\n public getEntityManager(): EntityManager {\n return this.orm.em.fork();\n }\n\n /**\n * Disconnect\n */\n public async disconnect(): Promise<void> {\n await this.orm.close();\n\n this.databaseManager.log('Disconnected');\n }\n}\n"],
|
|
5
|
+
"mappings": ";;AAOA,MAAO,iBAA+B;AAAA,EAPtC,OAOsC;AAAA;AAAA;AAAA;AAAA,EAE5B;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAIG;AACD,SAAK,kBAAkB;AACvB,SAAK,oBAAoB;AACzB,SAAK,MAAM;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKO,cAAgC;AACrC,WAAO,KAAK,IAAI,YAAY;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKO,mBAAkC;AACvC,WAAO,KAAK,IAAI,GAAG,KAAK;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,aAA4B;AACvC,UAAM,KAAK,IAAI,MAAM;AAErB,SAAK,gBAAgB,IAAI,cAAc;AAAA,EACzC;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;
|
|
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"}
|
package/dist/database/manager.js
CHANGED
|
@@ -3,6 +3,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
3
3
|
import { MikroORM } from "@mikro-orm/postgresql";
|
|
4
4
|
import DatabaseInstance from "./instance.js";
|
|
5
5
|
import { Logger } from "../logger/index.js";
|
|
6
|
+
import { DatabasePerformanceWrapper } from "../performance/index.js";
|
|
6
7
|
class DatabaseManager {
|
|
7
8
|
static {
|
|
8
9
|
__name(this, "DatabaseManager");
|
|
@@ -20,21 +21,82 @@ class DatabaseManager {
|
|
|
20
21
|
* Connect to database
|
|
21
22
|
*/
|
|
22
23
|
async connect() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
return DatabasePerformanceWrapper.monitorConnection("connect", async () => {
|
|
25
|
+
const startTime = performance.now();
|
|
26
|
+
try {
|
|
27
|
+
const orm = await MikroORM.init();
|
|
28
|
+
const databaseInstance = new DatabaseInstance({
|
|
29
|
+
databaseManager: this,
|
|
30
|
+
applicationConfig: this.options.applicationConfig,
|
|
31
|
+
orm
|
|
32
|
+
});
|
|
33
|
+
this.instances.push(databaseInstance);
|
|
34
|
+
const duration = performance.now() - startTime;
|
|
35
|
+
const ormConfig = typeof orm.config?.getAll === "function" ? orm.config.getAll() : void 0;
|
|
36
|
+
const logMeta = {
|
|
37
|
+
Host: ormConfig?.host ?? this.options.host,
|
|
38
|
+
User: ormConfig?.user ?? this.options.username,
|
|
39
|
+
Database: ormConfig?.dbName ?? this.options.databaseName,
|
|
40
|
+
Duration: `${duration.toFixed(2)}ms`
|
|
41
|
+
};
|
|
42
|
+
if (this.options.applicationConfig.log?.startUp) {
|
|
43
|
+
this.log("Connected", logMeta);
|
|
44
|
+
} else {
|
|
45
|
+
this.logger.debug({ message: "Database connected", meta: logMeta });
|
|
46
|
+
}
|
|
47
|
+
return databaseInstance;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
const duration = performance.now() - startTime;
|
|
50
|
+
this.logger.error({
|
|
51
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
52
|
+
message: "Database connection failed",
|
|
53
|
+
meta: {
|
|
54
|
+
Host: this.options.host,
|
|
55
|
+
Database: this.options.databaseName,
|
|
56
|
+
Duration: `${duration.toFixed(2)}ms`
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
28
61
|
});
|
|
29
|
-
this.instances.push(databaseInstance);
|
|
30
|
-
return databaseInstance;
|
|
31
62
|
}
|
|
32
63
|
/**
|
|
33
64
|
* Disconnect from database
|
|
34
65
|
*/
|
|
35
66
|
async disconnect() {
|
|
36
|
-
await
|
|
37
|
-
|
|
67
|
+
await DatabasePerformanceWrapper.monitorConnection("disconnect", async () => {
|
|
68
|
+
const startTime = performance.now();
|
|
69
|
+
const instanceCount = this.instances.length;
|
|
70
|
+
try {
|
|
71
|
+
await Promise.all(this.instances.map((instance) => instance.disconnect()));
|
|
72
|
+
const duration = performance.now() - startTime;
|
|
73
|
+
if (instanceCount > 0) {
|
|
74
|
+
const meta = {
|
|
75
|
+
Host: this.options.host,
|
|
76
|
+
Instances: instanceCount,
|
|
77
|
+
Duration: `${duration.toFixed(2)}ms`
|
|
78
|
+
};
|
|
79
|
+
if (this.options.applicationConfig.log?.startUp) {
|
|
80
|
+
this.log("Disconnected all database instances", meta);
|
|
81
|
+
} else {
|
|
82
|
+
this.logger.debug({ message: "Database instances disconnected", meta });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
this.instances = [];
|
|
86
|
+
} catch (error) {
|
|
87
|
+
const duration = performance.now() - startTime;
|
|
88
|
+
this.logger.error({
|
|
89
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
90
|
+
message: "Database disconnection failed",
|
|
91
|
+
meta: {
|
|
92
|
+
Host: this.options.host,
|
|
93
|
+
Duration: `${duration.toFixed(2)}ms`,
|
|
94
|
+
Instances: instanceCount
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
38
100
|
}
|
|
39
101
|
/**
|
|
40
102
|
* Log database message
|
|
@@ -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';\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 const orm = await MikroORM.init();\n\n
|
|
5
|
-
"mappings": ";;AAAA,SAAS,gBAAgB;AACzB,OAAO,sBAAsB;AAE7B,SAAS,cAAc;
|
|
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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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { type ErrorEnvelope, type ErrorReportOptions } from './error.interface.js';
|
|
2
|
+
/**
|
|
3
|
+
* Centralized error reporter for the framework
|
|
4
|
+
*
|
|
5
|
+
* Provides a unified interface for error reporting, normalization, logging,
|
|
6
|
+
* and external error tracking (Sentry). Eliminates inconsistent error handling
|
|
7
|
+
* and ensures all errors are properly structured and correlated.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const errorReporter = ErrorReporter.getInstance();
|
|
12
|
+
*
|
|
13
|
+
* // Report an error
|
|
14
|
+
* errorReporter.report(error, {
|
|
15
|
+
* context: { userId: '123', operation: 'fetchUser' },
|
|
16
|
+
* severity: ErrorSeverity.CRITICAL
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Report with custom code
|
|
20
|
+
* errorReporter.report(
|
|
21
|
+
* new Error('Database connection lost'),
|
|
22
|
+
* {
|
|
23
|
+
* code: ErrorCode.DATABASE_CONNECTION_FAILED,
|
|
24
|
+
* captureInSentry: true
|
|
25
|
+
* }
|
|
26
|
+
* );
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare class ErrorReporter {
|
|
30
|
+
private static instance;
|
|
31
|
+
private constructor();
|
|
32
|
+
/**
|
|
33
|
+
* Get the singleton instance
|
|
34
|
+
*/
|
|
35
|
+
static getInstance(): ErrorReporter;
|
|
36
|
+
/**
|
|
37
|
+
* Report an error through the centralized error pipeline
|
|
38
|
+
*
|
|
39
|
+
* This method:
|
|
40
|
+
* 1. Normalizes the error into a standard envelope
|
|
41
|
+
* 2. Logs the error with appropriate severity
|
|
42
|
+
* 3. Optionally captures the error in Sentry
|
|
43
|
+
* 4. Adds request correlation if available
|
|
44
|
+
*
|
|
45
|
+
* @param error - The error to report (Error, string, or unknown)
|
|
46
|
+
* @param options - Reporting options (context, severity, etc.)
|
|
47
|
+
* @returns Normalized error envelope
|
|
48
|
+
*/
|
|
49
|
+
report(error: Error | unknown, options?: ErrorReportOptions): ErrorEnvelope;
|
|
50
|
+
/**
|
|
51
|
+
* Normalize any error into a standardized ErrorEnvelope
|
|
52
|
+
*
|
|
53
|
+
* @param error - The error to normalize
|
|
54
|
+
* @param options - Optional configuration
|
|
55
|
+
* @returns Normalized error envelope
|
|
56
|
+
*/
|
|
57
|
+
private normalizeError;
|
|
58
|
+
/**
|
|
59
|
+
* Log the error with appropriate severity
|
|
60
|
+
*
|
|
61
|
+
* @param envelope - Normalized error envelope
|
|
62
|
+
*/
|
|
63
|
+
private logError;
|
|
64
|
+
/**
|
|
65
|
+
* Determine if error should be captured in Sentry
|
|
66
|
+
*
|
|
67
|
+
* @param envelope - Normalized error envelope
|
|
68
|
+
* @param options - Reporting options
|
|
69
|
+
* @returns Whether to capture in Sentry
|
|
70
|
+
*/
|
|
71
|
+
private shouldCaptureInSentry;
|
|
72
|
+
/**
|
|
73
|
+
* Capture error in Sentry with enriched context
|
|
74
|
+
*
|
|
75
|
+
* @param error - Original error
|
|
76
|
+
* @param envelope - Normalized error envelope
|
|
77
|
+
*/
|
|
78
|
+
private captureInSentry;
|
|
79
|
+
/**
|
|
80
|
+
* Map framework error severity to Sentry severity level
|
|
81
|
+
*
|
|
82
|
+
* @param severity - Framework error severity
|
|
83
|
+
* @returns Sentry severity level
|
|
84
|
+
*/
|
|
85
|
+
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
|
+
}
|
|
94
|
+
declare const _default: ErrorReporter;
|
|
95
|
+
export default _default;
|
|
96
|
+
//# sourceMappingURL=error-reporter.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import * as Sentry from "@sentry/node";
|
|
4
|
+
import { getRequestId } from "../request-context/index.js";
|
|
5
|
+
import Logger from "../logger/logger.js";
|
|
6
|
+
import { ErrorCode, ErrorSeverity } from "./error.interface.js";
|
|
7
|
+
import { FrameworkError } from "./framework-errors.js";
|
|
8
|
+
class ErrorReporter {
|
|
9
|
+
static {
|
|
10
|
+
__name(this, "ErrorReporter");
|
|
11
|
+
}
|
|
12
|
+
static instance;
|
|
13
|
+
constructor() {
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get the singleton instance
|
|
17
|
+
*/
|
|
18
|
+
static getInstance() {
|
|
19
|
+
if (!ErrorReporter.instance) {
|
|
20
|
+
ErrorReporter.instance = new ErrorReporter();
|
|
21
|
+
}
|
|
22
|
+
return ErrorReporter.instance;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Report an error through the centralized error pipeline
|
|
26
|
+
*
|
|
27
|
+
* This method:
|
|
28
|
+
* 1. Normalizes the error into a standard envelope
|
|
29
|
+
* 2. Logs the error with appropriate severity
|
|
30
|
+
* 3. Optionally captures the error in Sentry
|
|
31
|
+
* 4. Adds request correlation if available
|
|
32
|
+
*
|
|
33
|
+
* @param error - The error to report (Error, string, or unknown)
|
|
34
|
+
* @param options - Reporting options (context, severity, etc.)
|
|
35
|
+
* @returns Normalized error envelope
|
|
36
|
+
*/
|
|
37
|
+
report(error, options) {
|
|
38
|
+
const envelope = this.normalizeError(error, options);
|
|
39
|
+
if (options?.log !== false) {
|
|
40
|
+
this.logError(envelope);
|
|
41
|
+
}
|
|
42
|
+
if (this.shouldCaptureInSentry(envelope, options)) {
|
|
43
|
+
this.captureInSentry(error, envelope);
|
|
44
|
+
}
|
|
45
|
+
return envelope;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Normalize any error into a standardized ErrorEnvelope
|
|
49
|
+
*
|
|
50
|
+
* @param error - The error to normalize
|
|
51
|
+
* @param options - Optional configuration
|
|
52
|
+
* @returns Normalized error envelope
|
|
53
|
+
*/
|
|
54
|
+
normalizeError(error, options) {
|
|
55
|
+
const requestId = getRequestId();
|
|
56
|
+
if (error instanceof FrameworkError) {
|
|
57
|
+
return {
|
|
58
|
+
message: error.message,
|
|
59
|
+
code: options?.code ?? error.code,
|
|
60
|
+
severity: options?.severity ?? error.severity,
|
|
61
|
+
stack: error.stack,
|
|
62
|
+
requestId,
|
|
63
|
+
context: { ...error.context, ...options?.context },
|
|
64
|
+
cause: error.cause,
|
|
65
|
+
timestamp: error.timestamp,
|
|
66
|
+
name: error.name
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (error instanceof Error) {
|
|
70
|
+
return {
|
|
71
|
+
message: error.message,
|
|
72
|
+
code: options?.code ?? ErrorCode.UNKNOWN,
|
|
73
|
+
severity: options?.severity ?? ErrorSeverity.ERROR,
|
|
74
|
+
stack: error.stack,
|
|
75
|
+
requestId,
|
|
76
|
+
context: options?.context,
|
|
77
|
+
cause: error.cause,
|
|
78
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
79
|
+
name: error.name
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (typeof error === "string") {
|
|
83
|
+
return {
|
|
84
|
+
message: error,
|
|
85
|
+
code: options?.code ?? ErrorCode.UNKNOWN,
|
|
86
|
+
severity: options?.severity ?? ErrorSeverity.ERROR,
|
|
87
|
+
requestId,
|
|
88
|
+
context: options?.context,
|
|
89
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
message: this.serializeUnknownError(error),
|
|
94
|
+
code: options?.code ?? ErrorCode.UNKNOWN,
|
|
95
|
+
severity: options?.severity ?? ErrorSeverity.ERROR,
|
|
96
|
+
requestId,
|
|
97
|
+
context: { ...options?.context, originalError: error },
|
|
98
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Log the error with appropriate severity
|
|
103
|
+
*
|
|
104
|
+
* @param envelope - Normalized error envelope
|
|
105
|
+
*/
|
|
106
|
+
logError(envelope) {
|
|
107
|
+
const meta = {
|
|
108
|
+
code: envelope.code,
|
|
109
|
+
severity: envelope.severity
|
|
110
|
+
};
|
|
111
|
+
if (envelope.requestId) {
|
|
112
|
+
meta.requestId = envelope.requestId;
|
|
113
|
+
}
|
|
114
|
+
if (envelope.context) {
|
|
115
|
+
Object.assign(meta, envelope.context);
|
|
116
|
+
}
|
|
117
|
+
switch (envelope.severity) {
|
|
118
|
+
case ErrorSeverity.FATAL:
|
|
119
|
+
case ErrorSeverity.CRITICAL:
|
|
120
|
+
case ErrorSeverity.ERROR:
|
|
121
|
+
Logger.error({ error: envelope.message, meta });
|
|
122
|
+
break;
|
|
123
|
+
case ErrorSeverity.WARNING:
|
|
124
|
+
Logger.warn({ message: envelope.message, meta });
|
|
125
|
+
break;
|
|
126
|
+
case ErrorSeverity.INFO:
|
|
127
|
+
Logger.info({ message: envelope.message, meta });
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Determine if error should be captured in Sentry
|
|
133
|
+
*
|
|
134
|
+
* @param envelope - Normalized error envelope
|
|
135
|
+
* @param options - Reporting options
|
|
136
|
+
* @returns Whether to capture in Sentry
|
|
137
|
+
*/
|
|
138
|
+
shouldCaptureInSentry(envelope, options) {
|
|
139
|
+
if (options?.captureInSentry === false) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
if (options?.captureInSentry === true) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
return envelope.severity === ErrorSeverity.FATAL || envelope.severity === ErrorSeverity.CRITICAL || envelope.severity === ErrorSeverity.ERROR;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Capture error in Sentry with enriched context
|
|
149
|
+
*
|
|
150
|
+
* @param error - Original error
|
|
151
|
+
* @param envelope - Normalized error envelope
|
|
152
|
+
*/
|
|
153
|
+
captureInSentry(error, envelope) {
|
|
154
|
+
if (!Logger.isSentryInitialized) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
Sentry.withScope((scope) => {
|
|
158
|
+
scope.setLevel(this.mapSeverityToSentryLevel(envelope.severity));
|
|
159
|
+
scope.setTag("error_code", envelope.code);
|
|
160
|
+
if (envelope.requestId) {
|
|
161
|
+
scope.setTag("request_id", envelope.requestId);
|
|
162
|
+
}
|
|
163
|
+
if (envelope.context) {
|
|
164
|
+
scope.setContext("error_context", envelope.context);
|
|
165
|
+
}
|
|
166
|
+
if (error instanceof Error) {
|
|
167
|
+
Sentry.captureException(error);
|
|
168
|
+
} else {
|
|
169
|
+
Sentry.captureMessage(envelope.message, "error");
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Map framework error severity to Sentry severity level
|
|
175
|
+
*
|
|
176
|
+
* @param severity - Framework error severity
|
|
177
|
+
* @returns Sentry severity level
|
|
178
|
+
*/
|
|
179
|
+
mapSeverityToSentryLevel(severity) {
|
|
180
|
+
switch (severity) {
|
|
181
|
+
case ErrorSeverity.FATAL:
|
|
182
|
+
return "fatal";
|
|
183
|
+
case ErrorSeverity.CRITICAL:
|
|
184
|
+
return "error";
|
|
185
|
+
case ErrorSeverity.ERROR:
|
|
186
|
+
return "error";
|
|
187
|
+
case ErrorSeverity.WARNING:
|
|
188
|
+
return "warning";
|
|
189
|
+
case ErrorSeverity.INFO:
|
|
190
|
+
return "info";
|
|
191
|
+
default:
|
|
192
|
+
return "error";
|
|
193
|
+
}
|
|
194
|
+
}
|
|
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
|
+
}
|
|
223
|
+
var error_reporter_default = ErrorReporter.getInstance();
|
|
224
|
+
export {
|
|
225
|
+
ErrorReporter,
|
|
226
|
+
error_reporter_default as default
|
|
227
|
+
};
|
|
228
|
+
//# sourceMappingURL=error-reporter.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|