logiscout 1.0.0 → 1.0.3

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 (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -0
  3. package/dist/cjs/core/context/RequestContext.cjs +34 -4
  4. package/dist/cjs/core/context/RequestContext.d.ts.map +1 -1
  5. package/dist/cjs/core/types/LogEntry.d.ts +1 -0
  6. package/dist/cjs/core/types/LogEntry.d.ts.map +1 -1
  7. package/dist/cjs/index.cjs +13 -2
  8. package/dist/cjs/index.d.ts +1 -0
  9. package/dist/cjs/index.d.ts.map +1 -1
  10. package/dist/cjs/init.cjs +13 -0
  11. package/dist/cjs/init.d.ts +3 -0
  12. package/dist/cjs/init.d.ts.map +1 -0
  13. package/dist/cjs/initiator/state.cjs +17 -0
  14. package/dist/cjs/initiator/state.d.ts +8 -0
  15. package/dist/cjs/initiator/state.d.ts.map +1 -0
  16. package/dist/cjs/middlewares/correlationMiddleware.cjs +56 -6
  17. package/dist/cjs/middlewares/correlationMiddleware.d.ts +16 -1
  18. package/dist/cjs/middlewares/correlationMiddleware.d.ts.map +1 -1
  19. package/dist/cjs/services/Levels/Levels.cjs +4 -0
  20. package/dist/cjs/services/Levels/Levels.d.ts +1 -0
  21. package/dist/cjs/services/Levels/Levels.d.ts.map +1 -1
  22. package/dist/cjs/services/Logger/Logger.cjs +121 -38
  23. package/dist/cjs/services/Logger/Logger.d.ts +4 -1
  24. package/dist/cjs/services/Logger/Logger.d.ts.map +1 -1
  25. package/dist/cjs/services/formatters/ConsoleFormatter.cjs +37 -0
  26. package/dist/cjs/services/formatters/ConsoleFormatter.d.ts +12 -0
  27. package/dist/cjs/services/formatters/ConsoleFormatter.d.ts.map +1 -0
  28. package/dist/esm/core/context/RequestContext.d.ts.map +1 -1
  29. package/dist/esm/core/context/RequestContext.js +34 -4
  30. package/dist/esm/core/types/LogEntry.d.ts +1 -0
  31. package/dist/esm/core/types/LogEntry.d.ts.map +1 -1
  32. package/dist/esm/index.d.ts +1 -0
  33. package/dist/esm/index.d.ts.map +1 -1
  34. package/dist/esm/index.js +11 -1
  35. package/dist/esm/init.d.ts +3 -0
  36. package/dist/esm/init.d.ts.map +1 -0
  37. package/dist/esm/init.js +10 -0
  38. package/dist/esm/initiator/state.d.ts +8 -0
  39. package/dist/esm/initiator/state.d.ts.map +1 -0
  40. package/dist/esm/initiator/state.js +13 -0
  41. package/dist/esm/middlewares/correlationMiddleware.d.ts +16 -1
  42. package/dist/esm/middlewares/correlationMiddleware.d.ts.map +1 -1
  43. package/dist/esm/middlewares/correlationMiddleware.js +56 -6
  44. package/dist/esm/services/Levels/Levels.d.ts +1 -0
  45. package/dist/esm/services/Levels/Levels.d.ts.map +1 -1
  46. package/dist/esm/services/Levels/Levels.js +4 -0
  47. package/dist/esm/services/Logger/Logger.d.ts +4 -1
  48. package/dist/esm/services/Logger/Logger.d.ts.map +1 -1
  49. package/dist/esm/services/Logger/Logger.js +121 -38
  50. package/dist/esm/services/formatters/ConsoleFormatter.d.ts +12 -0
  51. package/dist/esm/services/formatters/ConsoleFormatter.d.ts.map +1 -0
  52. package/dist/esm/services/formatters/ConsoleFormatter.js +33 -0
  53. package/package.json +10 -12
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Muhammad Saad Akmal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # Logiscout
@@ -6,12 +6,42 @@ const crypto_1 = require("crypto");
6
6
  const storage = new async_hooks_1.AsyncLocalStorage();
7
7
  class RequestContext {
8
8
  static run(fn, correlationId) {
9
- storage.run({
10
- correlationId: correlationId ?? (0, crypto_1.randomUUID)(),
11
- }, fn);
9
+ // Validate function parameter
10
+ if (typeof fn !== "function") {
11
+ throw new Error("RequestContext.run() requires a function as the first parameter. " +
12
+ "Usage: RequestContext.run(() => { ... }, correlationId?)");
13
+ }
14
+ // Validate correlationId if provided
15
+ if (correlationId !== undefined && typeof correlationId !== "string") {
16
+ throw new Error("RequestContext.run(): correlationId must be a string if provided. " +
17
+ `Received: ${typeof correlationId}`);
18
+ }
19
+ if (correlationId && correlationId.length > 100) {
20
+ throw new Error("RequestContext.run(): correlationId cannot exceed 100 characters.");
21
+ }
22
+ // Generate UUID if not provided
23
+ const id = correlationId ?? (0, crypto_1.randomUUID)();
24
+ try {
25
+ storage.run({
26
+ correlationId: id,
27
+ }, fn);
28
+ }
29
+ catch (error) {
30
+ throw new Error(`RequestContext.run(): Failed to run function in context. ${error instanceof Error ? error.message : "Unknown error"}`);
31
+ }
12
32
  }
13
33
  static getCorrelationId() {
14
- return storage.getStore()?.correlationId;
34
+ try {
35
+ const store = storage.getStore();
36
+ return store?.correlationId;
37
+ }
38
+ catch (error) {
39
+ // AsyncLocalStorage access failed - likely outside async context
40
+ console.warn("[RequestContext] Warning: Could not retrieve correlationId. " +
41
+ "This may occur outside of a RequestContext.run() block. " +
42
+ "Consider using createCorrelationMiddleware() for HTTP requests.");
43
+ return undefined;
44
+ }
15
45
  }
16
46
  }
17
47
  exports.RequestContext = RequestContext;
@@ -1 +1 @@
1
- {"version":3,"file":"RequestContext.d.ts","sourceRoot":"","sources":["../../../../src/core/context/RequestContext.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;CACvB;AAID,qBAAa,cAAc;IACzB,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IASxD,MAAM,CAAC,gBAAgB,IAAI,MAAM,GAAG,SAAS;CAG9C"}
1
+ {"version":3,"file":"RequestContext.d.ts","sourceRoot":"","sources":["../../../../src/core/context/RequestContext.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;CACvB;AAID,qBAAa,cAAc;IACzB,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IA0CxD,MAAM,CAAC,gBAAgB,IAAI,MAAM,GAAG,SAAS;CAc9C"}
@@ -5,5 +5,6 @@ export interface LogEntry {
5
5
  timestamp: string;
6
6
  level: LogLevels;
7
7
  correlationId?: string;
8
+ send?: boolean;
8
9
  }
9
10
  //# sourceMappingURL=LogEntry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LogEntry.d.ts","sourceRoot":"","sources":["../../../../src/core/types/LogEntry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
1
+ {"version":3,"file":"LogEntry.d.ts","sourceRoot":"","sources":["../../../../src/core/types/LogEntry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAC,OAAO,CAAA;CACd"}
@@ -1,15 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createCorrelationMiddleware = exports.createLogger = exports.BaseLogger = exports.Levels = exports.LogLevels = void 0;
3
+ exports.createCorrelationMiddleware = exports.createLogger = exports.initLogiscout = exports.BaseLogger = exports.Levels = exports.LogLevels = void 0;
4
4
  var LogLevels_js_1 = require("./core/enum/LogLevels.cjs");
5
5
  Object.defineProperty(exports, "LogLevels", { enumerable: true, get: function () { return LogLevels_js_1.LogLevels; } });
6
6
  var Levels_js_1 = require("./services/Levels/Levels.cjs");
7
7
  Object.defineProperty(exports, "Levels", { enumerable: true, get: function () { return Levels_js_1.Levels; } });
8
8
  var Logger_js_1 = require("./services/Logger/Logger.cjs");
9
9
  Object.defineProperty(exports, "BaseLogger", { enumerable: true, get: function () { return Logger_js_1.Logger; } });
10
+ const state_js_1 = require("./initiator/state.cjs");
10
11
  const Levels_js_2 = require("./services/Levels/Levels.cjs");
11
12
  // const Logger = new Levels();
12
- const createLogger = (component) => new Levels_js_2.Levels(component);
13
+ // export const createLogger = (component: string) =>
14
+ // new Levels(component);
15
+ var init_js_1 = require("./init.cjs");
16
+ Object.defineProperty(exports, "initLogiscout", { enumerable: true, get: function () { return init_js_1.initLogiscout; } });
17
+ const createLogger = (component) => {
18
+ const config = (0, state_js_1.getLogiScouConfig)();
19
+ return new Levels_js_2.Levels(component, {
20
+ projectName: config.projectName,
21
+ environment: config.environment,
22
+ });
23
+ };
13
24
  exports.createLogger = createLogger;
14
25
  var correlationMiddleware_js_1 = require("./middlewares/correlationMiddleware.cjs");
15
26
  Object.defineProperty(exports, "createCorrelationMiddleware", { enumerable: true, get: function () { return correlationMiddleware_js_1.createCorrelationMiddleware; } });
@@ -4,6 +4,7 @@ export { LogEntry } from "./core/types/LogEntry.js";
4
4
  export { Levels } from "./services/Levels/Levels.js";
5
5
  export { Logger as BaseLogger } from "./services/Logger/Logger.js";
6
6
  import { Levels } from "./services/Levels/Levels.js";
7
+ export { initLogiscout } from "./init.js";
7
8
  export declare const createLogger: (component: string) => Levels;
8
9
  export { createCorrelationMiddleware } from "./middlewares/correlationMiddleware.js";
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AACrD,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAGrD,eAAO,MAAM,YAAY,GAAI,WAAW,MAAM,WACvB,CAAC;AAGxB,OAAO,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AACrD,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAOrD,OAAO,EAAC,aAAa,EAAC,MAAM,WAAW,CAAA;AACvC,eAAO,MAAM,YAAY,GAAI,WAAW,MAAM,WAO7C,CAAC;AAEF,OAAO,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initLogiscout = initLogiscout;
4
+ const state_js_1 = require("./initiator/state.cjs");
5
+ function initLogiscout(config) {
6
+ if (!config.projectName) {
7
+ throw new Error("projectName is required");
8
+ }
9
+ if (!config.environment) {
10
+ throw new Error("environment is required");
11
+ }
12
+ (0, state_js_1.setConfig)(config);
13
+ }
@@ -0,0 +1,3 @@
1
+ import { LogiscoutConfig } from "./initiator/state.js";
2
+ export declare function initLogiscout(config: LogiscoutConfig): void;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAa,MAAM,sBAAsB,CAAC;AAIlE,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,QAUpD"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setConfig = setConfig;
4
+ exports.getLogiScouConfig = getLogiScouConfig;
5
+ let config = null;
6
+ function setConfig(c) {
7
+ if (config) {
8
+ throw new Error("Logiscout has already been initialized");
9
+ }
10
+ config = c;
11
+ }
12
+ function getLogiScouConfig() {
13
+ if (!config) {
14
+ throw new Error("Logiscout is not initialized. Call initLogiscout() before using the SDK.");
15
+ }
16
+ return config;
17
+ }
@@ -0,0 +1,8 @@
1
+ export type LogiscoutConfig = {
2
+ projectName: string;
3
+ environment: "dev" | "staging" | "prod" | string;
4
+ apiKey?: string;
5
+ };
6
+ export declare function setConfig(c: LogiscoutConfig): void;
7
+ export declare function getLogiScouConfig(): LogiscoutConfig;
8
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/initiator/state.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,wBAAgB,SAAS,CAAC,CAAC,EAAE,eAAe,QAK3C;AAED,wBAAgB,iBAAiB,IAAI,eAAe,CAOnD"}
@@ -6,15 +6,65 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.createCorrelationMiddleware = void 0;
7
7
  const RequestContext_js_1 = require("../core/context/RequestContext.cjs");
8
8
  const crypto_1 = __importDefault(require("crypto"));
9
+ const state_js_1 = require("../initiator/state.cjs");
9
10
  const createCorrelationMiddleware = () => {
10
11
  return (req, res, next) => {
11
- const correlationId = crypto_1.default.randomUUID();
12
- RequestContext_js_1.RequestContext.run(() => {
13
- if (res?.setHeader) {
14
- res.setHeader("x-correlation-id", correlationId);
12
+ // Validate request object
13
+ const { projectName, environment } = (0, state_js_1.getLogiScouConfig)(); // 🔒 guard
14
+ if (!req || typeof req !== "object") {
15
+ console.error("[CorrelationMiddleware] Error: Invalid request object. " +
16
+ "Usage: createCorrelationMiddleware()(req, res, next)");
17
+ next?.(new Error("Invalid request object in correlation middleware"));
18
+ return;
19
+ }
20
+ // Validate response object
21
+ if (!res || typeof res !== "object") {
22
+ console.error("[CorrelationMiddleware] Error: Invalid response object. " +
23
+ "Usage: createCorrelationMiddleware()(req, res, next)");
24
+ next?.(new Error("Invalid response object in correlation middleware"));
25
+ return;
26
+ }
27
+ try {
28
+ // Check for existing correlation ID in headers (case-insensitive)
29
+ const headers = req.headers || {};
30
+ const existingId = headers["x-correlation-id"] ||
31
+ headers["X-Correlation-ID"] ||
32
+ req.get?.("x-correlation-id") ||
33
+ req.get?.("X-Correlation-ID");
34
+ const correlationId = (typeof existingId === "string" && existingId.trim()) || crypto_1.default.randomUUID();
35
+ // Validate correlation ID
36
+ if (!correlationId || typeof correlationId !== "string") {
37
+ console.error("[CorrelationMiddleware] Error: Failed to generate or retrieve correlation ID");
38
+ next?.(new Error("Correlation ID generation failed"));
39
+ return;
15
40
  }
16
- next();
17
- }, correlationId);
41
+ if (correlationId.length > 100) {
42
+ console.warn("[CorrelationMiddleware] Warning: Correlation ID exceeds 100 characters and will be truncated");
43
+ }
44
+ // Run the remaining middleware in the request context
45
+ RequestContext_js_1.RequestContext.run(() => {
46
+ // Safely set the correlation ID header
47
+ try {
48
+ if (res.setHeader) {
49
+ res.setHeader("x-correlation-id", correlationId);
50
+ }
51
+ }
52
+ catch (headerError) {
53
+ // setHeader might fail in some edge cases, don't block the request
54
+ console.warn("[CorrelationMiddleware] Warning: Could not set x-correlation-id header", headerError instanceof Error ? headerError.message : "Unknown error");
55
+ }
56
+ // Store correlation ID in response locals for downstream access
57
+ if (res.locals) {
58
+ res.locals.correlationId = correlationId;
59
+ }
60
+ next?.();
61
+ }, correlationId);
62
+ }
63
+ catch (error) {
64
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
65
+ console.error(`[CorrelationMiddleware] Error: Failed to initialize request context. ${errorMessage}`);
66
+ next?.(error instanceof Error ? error : new Error("Request context initialization failed"));
67
+ }
18
68
  };
19
69
  };
20
70
  exports.createCorrelationMiddleware = createCorrelationMiddleware;
@@ -1,2 +1,17 @@
1
- export declare const createCorrelationMiddleware: () => (req: any, res: any, next: () => void) => void;
1
+ interface RequestLike {
2
+ headers?: Record<string, string | string[] | undefined>;
3
+ get?: (header: string) => string | undefined;
4
+ }
5
+ interface ResponseLike {
6
+ setHeader?: (name: string, value: string) => void;
7
+ locals?: Record<string, unknown>;
8
+ }
9
+ interface NextFunction {
10
+ (err?: Error): void;
11
+ }
12
+ interface MiddlewareHandler {
13
+ (req: RequestLike, res: ResponseLike, next: NextFunction): void;
14
+ }
15
+ export declare const createCorrelationMiddleware: () => MiddlewareHandler;
16
+ export {};
2
17
  //# sourceMappingURL=correlationMiddleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"correlationMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middlewares/correlationMiddleware.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,2BAA2B,SAC9B,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,IAAI,SAU7C,CAAC"}
1
+ {"version":3,"file":"correlationMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middlewares/correlationMiddleware.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACxD,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC9C;AAED,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,UAAU,YAAY;IACpB,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,UAAU,iBAAiB;IACzB,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CACjE;AAED,eAAO,MAAM,2BAA2B,QAAO,iBAmF9C,CAAC"}
@@ -20,5 +20,9 @@ class Levels extends Logger_js_1.Logger {
20
20
  const entry = this.getLogEntry(message, LogLevels_js_1.LogLevels.DEBUG, meta);
21
21
  this.log(entry);
22
22
  }
23
+ critical(message, meta) {
24
+ const entry = this.getLogEntry(message, LogLevels_js_1.LogLevels.CRITICAL, meta);
25
+ this.log(entry);
26
+ }
23
27
  }
24
28
  exports.Levels = Levels;
@@ -5,5 +5,6 @@ export declare class Levels extends Logger implements LoggerInterface {
5
5
  warn(message: string, meta?: Record<string, unknown>): void;
6
6
  error(message: string, meta?: Record<string, unknown>): void;
7
7
  debug(message: string, meta?: Record<string, unknown>): void;
8
+ critical(message: string, meta?: Record<string, unknown>): void;
8
9
  }
9
10
  //# sourceMappingURL=Levels.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Levels.d.ts","sourceRoot":"","sources":["../../../../src/services/Levels/Levels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAG7C,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE1E,qBAAa,MAAO,SAAQ,MAAO,YAAW,eAAe;IAC3D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK3D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAM3D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK5D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAI7D"}
1
+ {"version":3,"file":"Levels.d.ts","sourceRoot":"","sources":["../../../../src/services/Levels/Levels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAG7C,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE1E,qBAAa,MAAO,SAAQ,MAAO,YAAW,eAAe;IAC3D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK3D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK3D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK5D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK5D,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAKhE"}
@@ -35,65 +35,148 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.Logger = void 0;
37
37
  const winston_1 = __importStar(require("winston"));
38
+ const LogLevels_js_1 = require("../../core/enum/LogLevels.cjs");
38
39
  const RequestContext_js_1 = require("../../core/context/RequestContext.cjs");
40
+ const ConsoleFormatter_js_1 = require("../formatters/ConsoleFormatter.cjs");
39
41
  class Logger {
40
42
  winstonLogger;
41
43
  componentName;
42
- constructor(componentName) {
44
+ projectName;
45
+ environment;
46
+ constructor(componentName, config) {
47
+ // Validate component name
48
+ if (!componentName || typeof componentName !== "string") {
49
+ throw new Error("Logger: Component name must be a non-empty string. " +
50
+ "Usage: createLogger('ComponentName')");
51
+ }
52
+ if (componentName.length > 100) {
53
+ throw new Error("Logger: Component name cannot exceed 100 characters. " +
54
+ `Received: '${componentName.substring(0, 20)}...'`);
55
+ }
43
56
  this.componentName = componentName;
44
- this.winstonLogger = winston_1.default.createLogger({
45
- level: "debug",
46
- levels: {
47
- error: 0,
48
- warn: 1,
49
- info: 2,
50
- debug: 3,
51
- },
52
- format: winston_1.format.combine(winston_1.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), winston_1.format.printf(({ timestamp, level, message, component, correlationId, ...meta }) => {
53
- const metaString = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
54
- return `[${component}] [${timestamp}] [${level.toUpperCase()}] [${correlationId}] ${message}${metaString}`;
55
- })),
56
- transports: [
57
- new winston_1.transports.Console({
58
- format: winston_1.format.combine(winston_1.format.colorize({ all: true }), winston_1.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), winston_1.format.printf(({ timestamp, level, message, ...meta }) => {
59
- const metaString = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
60
- return `[${componentName}] [${timestamp}] [${level}] ${message}${metaString}`;
61
- })),
62
- }),
63
- ],
64
- });
57
+ this.projectName = config.projectName;
58
+ this.environment = config.environment;
59
+ try {
60
+ // Create structlog-style formatter instance
61
+ const consoleFormatter = new ConsoleFormatter_js_1.ConsoleFormatter();
62
+ this.winstonLogger = winston_1.default.createLogger({
63
+ level: "debug",
64
+ levels: {
65
+ error: 0,
66
+ warn: 1,
67
+ info: 2,
68
+ debug: 3,
69
+ },
70
+ // File transport format (non-colorized)
71
+ format: winston_1.format.combine(winston_1.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), winston_1.format.printf(({ timestamp, level, message, component, ...meta }) => {
72
+ const formatted = consoleFormatter.format({
73
+ level: level,
74
+ message: String(message),
75
+ timestamp: String(timestamp),
76
+ component: component,
77
+ ...meta,
78
+ });
79
+ return `[${config.projectName}] ${formatted}`;
80
+ })),
81
+ transports: [
82
+ new winston_1.transports.Console({
83
+ // Console transport with structlog-style formatting and colors
84
+ format: winston_1.format.combine(winston_1.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), winston_1.format.printf(({ timestamp, level, message, component, ...meta }) => {
85
+ const formatted = consoleFormatter.format({
86
+ level: level,
87
+ message: String(message),
88
+ timestamp: String(timestamp),
89
+ component: component,
90
+ ...meta,
91
+ });
92
+ return formatted;
93
+ })),
94
+ }),
95
+ ],
96
+ });
97
+ }
98
+ catch (error) {
99
+ throw new Error(`Logger: Failed to initialize Winston logger. ${error instanceof Error ? error.message : "Unknown error"}`);
100
+ }
65
101
  }
66
102
  log(entry) {
67
103
  try {
68
- const correlationId = RequestContext_js_1.RequestContext.getCorrelationId();
69
- const logMeta = {
70
- component: this.componentName,
71
- correlationId,
72
- ...entry.meta,
73
- };
104
+ // Validate log entry
105
+ if (!entry) {
106
+ console.error("[Logiscout] Error: Log entry is undefined or null");
107
+ return;
108
+ }
109
+ if (!entry.message || typeof entry.message !== "string") {
110
+ console.error("[Logiscout] Error: Log message must be a non-empty string. " +
111
+ `Usage: logiscout.${entry.level}('Your message', { meta })`);
112
+ return;
113
+ }
114
+ if (entry.message.length > 10000) {
115
+ console.error("[Logiscout] Error: Log message exceeds 10000 characters. " +
116
+ "Message truncated for logging.");
117
+ entry.message = entry.message.substring(0, 10000) + "... [truncated]";
118
+ }
119
+ const correlationId = RequestContext_js_1.RequestContext.getCorrelationId() ?? "no-correlation-id";
120
+ // Safely handle metadata - prevent circular reference issues
121
+ let logMeta;
122
+ try {
123
+ logMeta = {
124
+ component: this.componentName,
125
+ correlationId,
126
+ ...entry.meta,
127
+ };
128
+ }
129
+ catch (metaError) {
130
+ console.error("[Logiscout] Error: Failed to process metadata. Logging without metadata.", metaError instanceof Error ? metaError.message : "Unknown error");
131
+ logMeta = {
132
+ component: this.componentName,
133
+ correlationId,
134
+ _metaError: "Failed to process metadata",
135
+ };
136
+ }
74
137
  this.winstonLogger.log(entry.level, entry.message, logMeta);
75
- // Send structured log to API (no formatting)
76
- // LogApi({
77
- // logs: {
78
- // ...entry,
79
- // component: this.componentName,
80
- // correlationId,
81
- // },
82
- // });
138
+ if (entry.send && this.environment == "prod") {
139
+ // console.log("sending to he server")
140
+ // Send structured log to API (no formatting)
141
+ // LogApi({
142
+ // logs: {
143
+ // ...entry,
144
+ // component: this.componentName,
145
+ // correlationId,
146
+ // },
147
+ // });
148
+ }
149
+ else {
150
+ // console.log("Showed to the user")
151
+ }
83
152
  }
84
- catch {
85
- // never throw from logger
153
+ catch (error) {
154
+ // Silent failure - logger should never crash the application
155
+ // Log to console as last resort
156
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
157
+ console.error(`[Logiscout] Critical: Logger failed to write log: ${errorMessage}`);
86
158
  }
87
159
  }
88
160
  getWinstonLogger() {
89
161
  return this.winstonLogger;
90
162
  }
91
163
  getLogEntry(message, logLevel, meta) {
164
+ // Validate message
165
+ if (!message || typeof message !== "string") {
166
+ throw new Error(`Logger: Message must be a non-empty string. ` +
167
+ `Received: ${typeof message === "undefined" ? "undefined" : typeof message}`);
168
+ }
169
+ // Validate log level
170
+ if (!Object.values(LogLevels_js_1.LogLevels).includes(logLevel)) {
171
+ throw new Error(`Logger: Invalid log level '${logLevel}'. ` +
172
+ `Valid levels: ${Object.values(LogLevels_js_1.LogLevels).join(", ")}`);
173
+ }
92
174
  const entry = {
93
175
  message,
94
176
  meta,
95
177
  timestamp: new Date().toISOString(),
96
178
  level: logLevel,
179
+ send: true
97
180
  };
98
181
  return entry;
99
182
  }
@@ -1,10 +1,13 @@
1
1
  import { Logger as WinstonLogger } from "winston";
2
2
  import { LogEntry } from "../../core/types/LogEntry.js";
3
3
  import { LogLevels } from "../../core/enum/LogLevels.js";
4
+ import { LogiscoutConfig } from "../../initiator/state.js";
4
5
  export declare abstract class Logger {
5
6
  protected winstonLogger: WinstonLogger;
6
7
  private componentName;
7
- constructor(componentName: string);
8
+ private projectName;
9
+ private environment;
10
+ constructor(componentName: string, config: LogiscoutConfig);
8
11
  protected log(entry: LogEntry): void;
9
12
  getWinstonLogger(): WinstonLogger;
10
13
  protected getLogEntry(message: string, logLevel: LogLevels, meta?: Record<string, unknown>): LogEntry;
@@ -1 +1 @@
1
- {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../../../src/services/Logger/Logger.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,MAAM,IAAI,aAAa,EAAsB,MAAM,SAAS,CAAC;AAE/E,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAGxD,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAGzD,8BAAsB,MAAM;IAC1B,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IACvC,OAAO,CAAC,aAAa,CAAS;gBAGlB,aAAa,EAAE,MAAM;IA4CjC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAyBpC,gBAAgB,IAAI,aAAa;IAIjC,SAAS,CAAC,WAAW,CACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,SAAS,EACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,QAAQ;CASZ"}
1
+ {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../../../src/services/Logger/Logger.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,MAAM,IAAI,aAAa,EAAsB,MAAM,SAAS,CAAC;AAE/E,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAGxD,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAI3D,8BAAsB,MAAM;IAC1B,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IACvC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,WAAW,CAAQ;gBAEf,aAAa,EAAE,MAAM,EAAG,MAAM,EAAC,eAAe;IAwE1D,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAsEpC,gBAAgB,IAAI,aAAa;IAIjC,SAAS,CAAC,WAAW,CACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,SAAS,EACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,QAAQ;CA0BZ"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConsoleFormatter = void 0;
4
+ const LogLevels_js_1 = require("../../core/enum/LogLevels.cjs");
5
+ const LEVEL_COLORS = {
6
+ [LogLevels_js_1.LogLevels.DEBUG]: "\x1b[90m", // gray
7
+ [LogLevels_js_1.LogLevels.INFO]: "\x1b[32m", // green
8
+ [LogLevels_js_1.LogLevels.WARN]: "\x1b[33m", // yellow
9
+ [LogLevels_js_1.LogLevels.ERROR]: "\x1b[31m", // red
10
+ [LogLevels_js_1.LogLevels.CRITICAL]: "\x1b[35m" // magenta
11
+ };
12
+ const RESET = "\x1b[0m";
13
+ class ConsoleFormatter {
14
+ format(data) {
15
+ const { level, message, timestamp, component, meta } = data;
16
+ const color = LEVEL_COLORS[level] ?? "";
17
+ const levelLabel = `${color}${level.toUpperCase()}${RESET}`;
18
+ const componentLabel = component ?? "App";
19
+ let output = `${timestamp} ` +
20
+ `[${levelLabel}] ` +
21
+ `[${componentLabel}] ` +
22
+ `${message}`;
23
+ if (meta && Object.keys(meta).length > 0) {
24
+ output += `\n${this.prettyJson(meta)}`;
25
+ }
26
+ return output;
27
+ }
28
+ prettyJson(obj) {
29
+ try {
30
+ return JSON.stringify(obj, null, 2);
31
+ }
32
+ catch {
33
+ return "{ \"error\": \"Failed to serialize metadata\" }";
34
+ }
35
+ }
36
+ }
37
+ exports.ConsoleFormatter = ConsoleFormatter;
@@ -0,0 +1,12 @@
1
+ import { LogLevels } from "../../core/enum/LogLevels.js";
2
+ export declare class ConsoleFormatter {
3
+ format(data: {
4
+ level: LogLevels;
5
+ message: string;
6
+ timestamp: string;
7
+ component?: string;
8
+ meta?: Record<string, unknown>;
9
+ }): string;
10
+ private prettyJson;
11
+ }
12
+ //# sourceMappingURL=ConsoleFormatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsoleFormatter.d.ts","sourceRoot":"","sources":["../../../../src/services/formatters/ConsoleFormatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAazD,qBAAa,gBAAgB;IAC3B,MAAM,CAAC,IAAI,EAAE;QACX,KAAK,EAAE,SAAS,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAChC,GAAG,MAAM;IAoBV,OAAO,CAAC,UAAU;CAOnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"RequestContext.d.ts","sourceRoot":"","sources":["../../../../src/core/context/RequestContext.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;CACvB;AAID,qBAAa,cAAc;IACzB,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IASxD,MAAM,CAAC,gBAAgB,IAAI,MAAM,GAAG,SAAS;CAG9C"}
1
+ {"version":3,"file":"RequestContext.d.ts","sourceRoot":"","sources":["../../../../src/core/context/RequestContext.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;CACvB;AAID,qBAAa,cAAc;IACzB,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IA0CxD,MAAM,CAAC,gBAAgB,IAAI,MAAM,GAAG,SAAS;CAc9C"}
@@ -3,11 +3,41 @@ import { randomUUID } from "crypto";
3
3
  const storage = new AsyncLocalStorage();
4
4
  export class RequestContext {
5
5
  static run(fn, correlationId) {
6
- storage.run({
7
- correlationId: correlationId ?? randomUUID(),
8
- }, fn);
6
+ // Validate function parameter
7
+ if (typeof fn !== "function") {
8
+ throw new Error("RequestContext.run() requires a function as the first parameter. " +
9
+ "Usage: RequestContext.run(() => { ... }, correlationId?)");
10
+ }
11
+ // Validate correlationId if provided
12
+ if (correlationId !== undefined && typeof correlationId !== "string") {
13
+ throw new Error("RequestContext.run(): correlationId must be a string if provided. " +
14
+ `Received: ${typeof correlationId}`);
15
+ }
16
+ if (correlationId && correlationId.length > 100) {
17
+ throw new Error("RequestContext.run(): correlationId cannot exceed 100 characters.");
18
+ }
19
+ // Generate UUID if not provided
20
+ const id = correlationId ?? randomUUID();
21
+ try {
22
+ storage.run({
23
+ correlationId: id,
24
+ }, fn);
25
+ }
26
+ catch (error) {
27
+ throw new Error(`RequestContext.run(): Failed to run function in context. ${error instanceof Error ? error.message : "Unknown error"}`);
28
+ }
9
29
  }
10
30
  static getCorrelationId() {
11
- return storage.getStore()?.correlationId;
31
+ try {
32
+ const store = storage.getStore();
33
+ return store?.correlationId;
34
+ }
35
+ catch (error) {
36
+ // AsyncLocalStorage access failed - likely outside async context
37
+ console.warn("[RequestContext] Warning: Could not retrieve correlationId. " +
38
+ "This may occur outside of a RequestContext.run() block. " +
39
+ "Consider using createCorrelationMiddleware() for HTTP requests.");
40
+ return undefined;
41
+ }
12
42
  }
13
43
  }
@@ -5,5 +5,6 @@ export interface LogEntry {
5
5
  timestamp: string;
6
6
  level: LogLevels;
7
7
  correlationId?: string;
8
+ send?: boolean;
8
9
  }
9
10
  //# sourceMappingURL=LogEntry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LogEntry.d.ts","sourceRoot":"","sources":["../../../../src/core/types/LogEntry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
1
+ {"version":3,"file":"LogEntry.d.ts","sourceRoot":"","sources":["../../../../src/core/types/LogEntry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAC,OAAO,CAAA;CACd"}
@@ -4,6 +4,7 @@ export { LogEntry } from "./core/types/LogEntry.js";
4
4
  export { Levels } from "./services/Levels/Levels.js";
5
5
  export { Logger as BaseLogger } from "./services/Logger/Logger.js";
6
6
  import { Levels } from "./services/Levels/Levels.js";
7
+ export { initLogiscout } from "./init.js";
7
8
  export declare const createLogger: (component: string) => Levels;
8
9
  export { createCorrelationMiddleware } from "./middlewares/correlationMiddleware.js";
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AACrD,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAGrD,eAAO,MAAM,YAAY,GAAI,WAAW,MAAM,WACvB,CAAC;AAGxB,OAAO,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AACrD,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAOrD,OAAO,EAAC,aAAa,EAAC,MAAM,WAAW,CAAA;AACvC,eAAO,MAAM,YAAY,GAAI,WAAW,MAAM,WAO7C,CAAC;AAEF,OAAO,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAC"}
package/dist/esm/index.js CHANGED
@@ -1,8 +1,18 @@
1
1
  export { LogLevels } from "./core/enum/LogLevels.js";
2
2
  export { Levels } from "./services/Levels/Levels.js";
3
3
  export { Logger as BaseLogger } from "./services/Logger/Logger.js";
4
+ import { getLogiScouConfig } from "./initiator/state.js";
4
5
  import { Levels } from "./services/Levels/Levels.js";
5
6
  // const Logger = new Levels();
6
- export const createLogger = (component) => new Levels(component);
7
+ // export const createLogger = (component: string) =>
8
+ // new Levels(component);
9
+ export { initLogiscout } from "./init.js";
10
+ export const createLogger = (component) => {
11
+ const config = getLogiScouConfig();
12
+ return new Levels(component, {
13
+ projectName: config.projectName,
14
+ environment: config.environment,
15
+ });
16
+ };
7
17
  export { createCorrelationMiddleware } from "./middlewares/correlationMiddleware.js";
8
18
  // export { Logger };
@@ -0,0 +1,3 @@
1
+ import { LogiscoutConfig } from "./initiator/state.js";
2
+ export declare function initLogiscout(config: LogiscoutConfig): void;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAa,MAAM,sBAAsB,CAAC;AAIlE,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,QAUpD"}
@@ -0,0 +1,10 @@
1
+ import { setConfig } from "./initiator/state.js";
2
+ export function initLogiscout(config) {
3
+ if (!config.projectName) {
4
+ throw new Error("projectName is required");
5
+ }
6
+ if (!config.environment) {
7
+ throw new Error("environment is required");
8
+ }
9
+ setConfig(config);
10
+ }
@@ -0,0 +1,8 @@
1
+ export type LogiscoutConfig = {
2
+ projectName: string;
3
+ environment: "dev" | "staging" | "prod" | string;
4
+ apiKey?: string;
5
+ };
6
+ export declare function setConfig(c: LogiscoutConfig): void;
7
+ export declare function getLogiScouConfig(): LogiscoutConfig;
8
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/initiator/state.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,wBAAgB,SAAS,CAAC,CAAC,EAAE,eAAe,QAK3C;AAED,wBAAgB,iBAAiB,IAAI,eAAe,CAOnD"}
@@ -0,0 +1,13 @@
1
+ let config = null;
2
+ export function setConfig(c) {
3
+ if (config) {
4
+ throw new Error("Logiscout has already been initialized");
5
+ }
6
+ config = c;
7
+ }
8
+ export function getLogiScouConfig() {
9
+ if (!config) {
10
+ throw new Error("Logiscout is not initialized. Call initLogiscout() before using the SDK.");
11
+ }
12
+ return config;
13
+ }
@@ -1,2 +1,17 @@
1
- export declare const createCorrelationMiddleware: () => (req: any, res: any, next: () => void) => void;
1
+ interface RequestLike {
2
+ headers?: Record<string, string | string[] | undefined>;
3
+ get?: (header: string) => string | undefined;
4
+ }
5
+ interface ResponseLike {
6
+ setHeader?: (name: string, value: string) => void;
7
+ locals?: Record<string, unknown>;
8
+ }
9
+ interface NextFunction {
10
+ (err?: Error): void;
11
+ }
12
+ interface MiddlewareHandler {
13
+ (req: RequestLike, res: ResponseLike, next: NextFunction): void;
14
+ }
15
+ export declare const createCorrelationMiddleware: () => MiddlewareHandler;
16
+ export {};
2
17
  //# sourceMappingURL=correlationMiddleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"correlationMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middlewares/correlationMiddleware.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,2BAA2B,SAC9B,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,IAAI,SAU7C,CAAC"}
1
+ {"version":3,"file":"correlationMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middlewares/correlationMiddleware.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACxD,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC9C;AAED,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,UAAU,YAAY;IACpB,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,UAAU,iBAAiB;IACzB,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CACjE;AAED,eAAO,MAAM,2BAA2B,QAAO,iBAmF9C,CAAC"}
@@ -1,13 +1,63 @@
1
1
  import { RequestContext } from "../core/context/RequestContext.js";
2
2
  import crypto from "crypto";
3
+ import { getLogiScouConfig } from "../initiator/state.js";
3
4
  export const createCorrelationMiddleware = () => {
4
5
  return (req, res, next) => {
5
- const correlationId = crypto.randomUUID();
6
- RequestContext.run(() => {
7
- if (res?.setHeader) {
8
- res.setHeader("x-correlation-id", correlationId);
6
+ // Validate request object
7
+ const { projectName, environment } = getLogiScouConfig(); // 🔒 guard
8
+ if (!req || typeof req !== "object") {
9
+ console.error("[CorrelationMiddleware] Error: Invalid request object. " +
10
+ "Usage: createCorrelationMiddleware()(req, res, next)");
11
+ next?.(new Error("Invalid request object in correlation middleware"));
12
+ return;
13
+ }
14
+ // Validate response object
15
+ if (!res || typeof res !== "object") {
16
+ console.error("[CorrelationMiddleware] Error: Invalid response object. " +
17
+ "Usage: createCorrelationMiddleware()(req, res, next)");
18
+ next?.(new Error("Invalid response object in correlation middleware"));
19
+ return;
20
+ }
21
+ try {
22
+ // Check for existing correlation ID in headers (case-insensitive)
23
+ const headers = req.headers || {};
24
+ const existingId = headers["x-correlation-id"] ||
25
+ headers["X-Correlation-ID"] ||
26
+ req.get?.("x-correlation-id") ||
27
+ req.get?.("X-Correlation-ID");
28
+ const correlationId = (typeof existingId === "string" && existingId.trim()) || crypto.randomUUID();
29
+ // Validate correlation ID
30
+ if (!correlationId || typeof correlationId !== "string") {
31
+ console.error("[CorrelationMiddleware] Error: Failed to generate or retrieve correlation ID");
32
+ next?.(new Error("Correlation ID generation failed"));
33
+ return;
9
34
  }
10
- next();
11
- }, correlationId);
35
+ if (correlationId.length > 100) {
36
+ console.warn("[CorrelationMiddleware] Warning: Correlation ID exceeds 100 characters and will be truncated");
37
+ }
38
+ // Run the remaining middleware in the request context
39
+ RequestContext.run(() => {
40
+ // Safely set the correlation ID header
41
+ try {
42
+ if (res.setHeader) {
43
+ res.setHeader("x-correlation-id", correlationId);
44
+ }
45
+ }
46
+ catch (headerError) {
47
+ // setHeader might fail in some edge cases, don't block the request
48
+ console.warn("[CorrelationMiddleware] Warning: Could not set x-correlation-id header", headerError instanceof Error ? headerError.message : "Unknown error");
49
+ }
50
+ // Store correlation ID in response locals for downstream access
51
+ if (res.locals) {
52
+ res.locals.correlationId = correlationId;
53
+ }
54
+ next?.();
55
+ }, correlationId);
56
+ }
57
+ catch (error) {
58
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
59
+ console.error(`[CorrelationMiddleware] Error: Failed to initialize request context. ${errorMessage}`);
60
+ next?.(error instanceof Error ? error : new Error("Request context initialization failed"));
61
+ }
12
62
  };
13
63
  };
@@ -5,5 +5,6 @@ export declare class Levels extends Logger implements LoggerInterface {
5
5
  warn(message: string, meta?: Record<string, unknown>): void;
6
6
  error(message: string, meta?: Record<string, unknown>): void;
7
7
  debug(message: string, meta?: Record<string, unknown>): void;
8
+ critical(message: string, meta?: Record<string, unknown>): void;
8
9
  }
9
10
  //# sourceMappingURL=Levels.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Levels.d.ts","sourceRoot":"","sources":["../../../../src/services/Levels/Levels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAG7C,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE1E,qBAAa,MAAO,SAAQ,MAAO,YAAW,eAAe;IAC3D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK3D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAM3D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK5D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAI7D"}
1
+ {"version":3,"file":"Levels.d.ts","sourceRoot":"","sources":["../../../../src/services/Levels/Levels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAG7C,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE1E,qBAAa,MAAO,SAAQ,MAAO,YAAW,eAAe;IAC3D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK3D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK3D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK5D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK5D,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAKhE"}
@@ -17,4 +17,8 @@ export class Levels extends Logger {
17
17
  const entry = this.getLogEntry(message, LogLevels.DEBUG, meta);
18
18
  this.log(entry);
19
19
  }
20
+ critical(message, meta) {
21
+ const entry = this.getLogEntry(message, LogLevels.CRITICAL, meta);
22
+ this.log(entry);
23
+ }
20
24
  }
@@ -1,10 +1,13 @@
1
1
  import { Logger as WinstonLogger } from "winston";
2
2
  import { LogEntry } from "../../core/types/LogEntry.js";
3
3
  import { LogLevels } from "../../core/enum/LogLevels.js";
4
+ import { LogiscoutConfig } from "../../initiator/state.js";
4
5
  export declare abstract class Logger {
5
6
  protected winstonLogger: WinstonLogger;
6
7
  private componentName;
7
- constructor(componentName: string);
8
+ private projectName;
9
+ private environment;
10
+ constructor(componentName: string, config: LogiscoutConfig);
8
11
  protected log(entry: LogEntry): void;
9
12
  getWinstonLogger(): WinstonLogger;
10
13
  protected getLogEntry(message: string, logLevel: LogLevels, meta?: Record<string, unknown>): LogEntry;
@@ -1 +1 @@
1
- {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../../../src/services/Logger/Logger.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,MAAM,IAAI,aAAa,EAAsB,MAAM,SAAS,CAAC;AAE/E,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAGxD,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAGzD,8BAAsB,MAAM;IAC1B,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IACvC,OAAO,CAAC,aAAa,CAAS;gBAGlB,aAAa,EAAE,MAAM;IA4CjC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAyBpC,gBAAgB,IAAI,aAAa;IAIjC,SAAS,CAAC,WAAW,CACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,SAAS,EACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,QAAQ;CASZ"}
1
+ {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../../../src/services/Logger/Logger.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,MAAM,IAAI,aAAa,EAAsB,MAAM,SAAS,CAAC;AAE/E,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAGxD,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAI3D,8BAAsB,MAAM;IAC1B,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IACvC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,WAAW,CAAQ;gBAEf,aAAa,EAAE,MAAM,EAAG,MAAM,EAAC,eAAe;IAwE1D,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAsEpC,gBAAgB,IAAI,aAAa;IAIjC,SAAS,CAAC,WAAW,CACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,SAAS,EACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,QAAQ;CA0BZ"}
@@ -1,63 +1,146 @@
1
1
  import winston, { format, transports } from "winston";
2
+ import { LogLevels } from "../../core/enum/LogLevels.js";
2
3
  import { RequestContext } from "../../core/context/RequestContext.js";
4
+ import { ConsoleFormatter } from "../formatters/ConsoleFormatter.js";
3
5
  export class Logger {
4
6
  winstonLogger;
5
7
  componentName;
6
- constructor(componentName) {
8
+ projectName;
9
+ environment;
10
+ constructor(componentName, config) {
11
+ // Validate component name
12
+ if (!componentName || typeof componentName !== "string") {
13
+ throw new Error("Logger: Component name must be a non-empty string. " +
14
+ "Usage: createLogger('ComponentName')");
15
+ }
16
+ if (componentName.length > 100) {
17
+ throw new Error("Logger: Component name cannot exceed 100 characters. " +
18
+ `Received: '${componentName.substring(0, 20)}...'`);
19
+ }
7
20
  this.componentName = componentName;
8
- this.winstonLogger = winston.createLogger({
9
- level: "debug",
10
- levels: {
11
- error: 0,
12
- warn: 1,
13
- info: 2,
14
- debug: 3,
15
- },
16
- format: format.combine(format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), format.printf(({ timestamp, level, message, component, correlationId, ...meta }) => {
17
- const metaString = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
18
- return `[${component}] [${timestamp}] [${level.toUpperCase()}] [${correlationId}] ${message}${metaString}`;
19
- })),
20
- transports: [
21
- new transports.Console({
22
- format: format.combine(format.colorize({ all: true }), format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), format.printf(({ timestamp, level, message, ...meta }) => {
23
- const metaString = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
24
- return `[${componentName}] [${timestamp}] [${level}] ${message}${metaString}`;
25
- })),
26
- }),
27
- ],
28
- });
21
+ this.projectName = config.projectName;
22
+ this.environment = config.environment;
23
+ try {
24
+ // Create structlog-style formatter instance
25
+ const consoleFormatter = new ConsoleFormatter();
26
+ this.winstonLogger = winston.createLogger({
27
+ level: "debug",
28
+ levels: {
29
+ error: 0,
30
+ warn: 1,
31
+ info: 2,
32
+ debug: 3,
33
+ },
34
+ // File transport format (non-colorized)
35
+ format: format.combine(format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), format.printf(({ timestamp, level, message, component, ...meta }) => {
36
+ const formatted = consoleFormatter.format({
37
+ level: level,
38
+ message: String(message),
39
+ timestamp: String(timestamp),
40
+ component: component,
41
+ ...meta,
42
+ });
43
+ return `[${config.projectName}] ${formatted}`;
44
+ })),
45
+ transports: [
46
+ new transports.Console({
47
+ // Console transport with structlog-style formatting and colors
48
+ format: format.combine(format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), format.printf(({ timestamp, level, message, component, ...meta }) => {
49
+ const formatted = consoleFormatter.format({
50
+ level: level,
51
+ message: String(message),
52
+ timestamp: String(timestamp),
53
+ component: component,
54
+ ...meta,
55
+ });
56
+ return formatted;
57
+ })),
58
+ }),
59
+ ],
60
+ });
61
+ }
62
+ catch (error) {
63
+ throw new Error(`Logger: Failed to initialize Winston logger. ${error instanceof Error ? error.message : "Unknown error"}`);
64
+ }
29
65
  }
30
66
  log(entry) {
31
67
  try {
32
- const correlationId = RequestContext.getCorrelationId();
33
- const logMeta = {
34
- component: this.componentName,
35
- correlationId,
36
- ...entry.meta,
37
- };
68
+ // Validate log entry
69
+ if (!entry) {
70
+ console.error("[Logiscout] Error: Log entry is undefined or null");
71
+ return;
72
+ }
73
+ if (!entry.message || typeof entry.message !== "string") {
74
+ console.error("[Logiscout] Error: Log message must be a non-empty string. " +
75
+ `Usage: logiscout.${entry.level}('Your message', { meta })`);
76
+ return;
77
+ }
78
+ if (entry.message.length > 10000) {
79
+ console.error("[Logiscout] Error: Log message exceeds 10000 characters. " +
80
+ "Message truncated for logging.");
81
+ entry.message = entry.message.substring(0, 10000) + "... [truncated]";
82
+ }
83
+ const correlationId = RequestContext.getCorrelationId() ?? "no-correlation-id";
84
+ // Safely handle metadata - prevent circular reference issues
85
+ let logMeta;
86
+ try {
87
+ logMeta = {
88
+ component: this.componentName,
89
+ correlationId,
90
+ ...entry.meta,
91
+ };
92
+ }
93
+ catch (metaError) {
94
+ console.error("[Logiscout] Error: Failed to process metadata. Logging without metadata.", metaError instanceof Error ? metaError.message : "Unknown error");
95
+ logMeta = {
96
+ component: this.componentName,
97
+ correlationId,
98
+ _metaError: "Failed to process metadata",
99
+ };
100
+ }
38
101
  this.winstonLogger.log(entry.level, entry.message, logMeta);
39
- // Send structured log to API (no formatting)
40
- // LogApi({
41
- // logs: {
42
- // ...entry,
43
- // component: this.componentName,
44
- // correlationId,
45
- // },
46
- // });
102
+ if (entry.send && this.environment == "prod") {
103
+ // console.log("sending to he server")
104
+ // Send structured log to API (no formatting)
105
+ // LogApi({
106
+ // logs: {
107
+ // ...entry,
108
+ // component: this.componentName,
109
+ // correlationId,
110
+ // },
111
+ // });
112
+ }
113
+ else {
114
+ // console.log("Showed to the user")
115
+ }
47
116
  }
48
- catch {
49
- // never throw from logger
117
+ catch (error) {
118
+ // Silent failure - logger should never crash the application
119
+ // Log to console as last resort
120
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
121
+ console.error(`[Logiscout] Critical: Logger failed to write log: ${errorMessage}`);
50
122
  }
51
123
  }
52
124
  getWinstonLogger() {
53
125
  return this.winstonLogger;
54
126
  }
55
127
  getLogEntry(message, logLevel, meta) {
128
+ // Validate message
129
+ if (!message || typeof message !== "string") {
130
+ throw new Error(`Logger: Message must be a non-empty string. ` +
131
+ `Received: ${typeof message === "undefined" ? "undefined" : typeof message}`);
132
+ }
133
+ // Validate log level
134
+ if (!Object.values(LogLevels).includes(logLevel)) {
135
+ throw new Error(`Logger: Invalid log level '${logLevel}'. ` +
136
+ `Valid levels: ${Object.values(LogLevels).join(", ")}`);
137
+ }
56
138
  const entry = {
57
139
  message,
58
140
  meta,
59
141
  timestamp: new Date().toISOString(),
60
142
  level: logLevel,
143
+ send: true
61
144
  };
62
145
  return entry;
63
146
  }
@@ -0,0 +1,12 @@
1
+ import { LogLevels } from "../../core/enum/LogLevels.js";
2
+ export declare class ConsoleFormatter {
3
+ format(data: {
4
+ level: LogLevels;
5
+ message: string;
6
+ timestamp: string;
7
+ component?: string;
8
+ meta?: Record<string, unknown>;
9
+ }): string;
10
+ private prettyJson;
11
+ }
12
+ //# sourceMappingURL=ConsoleFormatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsoleFormatter.d.ts","sourceRoot":"","sources":["../../../../src/services/formatters/ConsoleFormatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAazD,qBAAa,gBAAgB;IAC3B,MAAM,CAAC,IAAI,EAAE;QACX,KAAK,EAAE,SAAS,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAChC,GAAG,MAAM;IAoBV,OAAO,CAAC,UAAU;CAOnB"}
@@ -0,0 +1,33 @@
1
+ import { LogLevels } from "../../core/enum/LogLevels.js";
2
+ const LEVEL_COLORS = {
3
+ [LogLevels.DEBUG]: "\x1b[90m", // gray
4
+ [LogLevels.INFO]: "\x1b[32m", // green
5
+ [LogLevels.WARN]: "\x1b[33m", // yellow
6
+ [LogLevels.ERROR]: "\x1b[31m", // red
7
+ [LogLevels.CRITICAL]: "\x1b[35m" // magenta
8
+ };
9
+ const RESET = "\x1b[0m";
10
+ export class ConsoleFormatter {
11
+ format(data) {
12
+ const { level, message, timestamp, component, meta } = data;
13
+ const color = LEVEL_COLORS[level] ?? "";
14
+ const levelLabel = `${color}${level.toUpperCase()}${RESET}`;
15
+ const componentLabel = component ?? "App";
16
+ let output = `${timestamp} ` +
17
+ `[${levelLabel}] ` +
18
+ `[${componentLabel}] ` +
19
+ `${message}`;
20
+ if (meta && Object.keys(meta).length > 0) {
21
+ output += `\n${this.prettyJson(meta)}`;
22
+ }
23
+ return output;
24
+ }
25
+ prettyJson(obj) {
26
+ try {
27
+ return JSON.stringify(obj, null, 2);
28
+ }
29
+ catch {
30
+ return "{ \"error\": \"Failed to serialize metadata\" }";
31
+ }
32
+ }
33
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "logiscout",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "Logiscout — a structured logger library",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.cjs",
@@ -26,31 +26,29 @@
26
26
  "keywords": [
27
27
  "logger",
28
28
  "logging",
29
- "correlation-id",
30
- "async-context",
31
29
  "structured-logging",
32
- "nodejs",
33
- "express",
34
- "winston"
30
+ "nodejs"
35
31
  ],
36
- "author": "YOUR_NAME",
32
+ "author": "Logiscout",
37
33
  "license": "MIT",
38
34
  "repository": {
39
35
  "type": "git",
40
- "url": "https://github.com/YOUR_GITHUB_USERNAME/logicout"
36
+ "url": "https://github.com/saadakmal460/Logiscout.git"
41
37
  },
42
- "homepage": "https://github.com/YOUR_GITHUB_USERNAME/logicout#readme",
38
+ "homepage": "https://github.com/saadakmal460/Logiscout#readme",
43
39
  "bugs": {
44
- "url": "https://github.com/YOUR_GITHUB_USERNAME/logicout/issues"
40
+ "url": "https://github.com/saadakmal460/Logiscout/issues"
45
41
  },
46
42
  "engines": {
47
43
  "node": ">=18"
48
44
  },
49
45
  "dependencies": {
46
+ "axios": "^1.13.2",
50
47
  "winston": "^3.11.0"
51
48
  },
52
49
  "devDependencies": {
53
- "typescript": "^5.3.3",
54
- "@types/node": "^20.10.0"
50
+ "@types/node": "^20.10.0",
51
+ "ts-node": "^10.9.2",
52
+ "typescript": "^5.9.3"
55
53
  }
56
54
  }