logixia 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,1115 @@
1
+ import { v4 } from "uuid";
2
+ import { AsyncLocalStorage } from "async_hooks";
3
+ import { Injectable, Module, RequestMethod, Scope } from "@nestjs/common";
4
+
5
+ //#region rolldown:runtime
6
+ var __create = Object.create;
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __getProtoOf = Object.getPrototypeOf;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __commonJS = (cb, mod) => function() {
13
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
17
+ key = keys[i];
18
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
19
+ get: ((k) => from[k]).bind(null, key),
20
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
21
+ });
22
+ }
23
+ return to;
24
+ };
25
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
26
+ value: mod,
27
+ enumerable: true
28
+ }) : target, mod));
29
+
30
+ //#endregion
31
+ //#region src/types/index.ts
32
+ const LogLevel = {
33
+ ERROR: "error",
34
+ WARN: "warn",
35
+ INFO: "info",
36
+ DEBUG: "debug",
37
+ TRACE: "trace",
38
+ VERBOSE: "verbose"
39
+ };
40
+ const DEFAULT_LOG_LEVELS = {
41
+ error: 0,
42
+ warn: 1,
43
+ info: 2,
44
+ debug: 3,
45
+ trace: 4,
46
+ verbose: 5
47
+ };
48
+ const DEFAULT_LOG_COLORS = {
49
+ error: "red",
50
+ warn: "yellow",
51
+ info: "green",
52
+ debug: "blue",
53
+ trace: "magenta",
54
+ verbose: "cyan"
55
+ };
56
+
57
+ //#endregion
58
+ //#region src/utils/trace.utils.ts
59
+ const traceStorage = new AsyncLocalStorage();
60
+ /**
61
+ * Default trace ID generator using UUID v4
62
+ */
63
+ function generateTraceId() {
64
+ return v4().replace(/-/g, "").substring(0, 16);
65
+ }
66
+ /**
67
+ * Get current trace ID from async context
68
+ */
69
+ function getCurrentTraceId() {
70
+ const store = traceStorage.getStore();
71
+ return store === null || store === void 0 ? void 0 : store.traceId;
72
+ }
73
+ /**
74
+ * Set trace ID in async context
75
+ */
76
+ function setTraceId(traceId, data) {
77
+ const currentStore = traceStorage.getStore() || {};
78
+ traceStorage.enterWith({
79
+ ...currentStore,
80
+ traceId,
81
+ ...data
82
+ });
83
+ }
84
+ /**
85
+ * Run function with trace ID context
86
+ */
87
+ function runWithTraceId(traceId, fn, data) {
88
+ return traceStorage.run({
89
+ traceId,
90
+ ...data
91
+ }, fn);
92
+ }
93
+ /**
94
+ * Extract trace ID from request using configuration
95
+ */
96
+ function extractTraceId(request, config) {
97
+ if (config.header) {
98
+ const headers = Array.isArray(config.header) ? config.header : [config.header];
99
+ for (const header of headers) {
100
+ var _request$headers;
101
+ const value = (_request$headers = request.headers) === null || _request$headers === void 0 ? void 0 : _request$headers[header.toLowerCase()];
102
+ if (value) return Array.isArray(value) ? value[0] : value;
103
+ }
104
+ }
105
+ if (config.query) {
106
+ const queries = Array.isArray(config.query) ? config.query : [config.query];
107
+ for (const query of queries) {
108
+ var _request$query;
109
+ const value = (_request$query = request.query) === null || _request$query === void 0 ? void 0 : _request$query[query];
110
+ if (value) return Array.isArray(value) ? value[0] : value;
111
+ }
112
+ }
113
+ if (config.body) {
114
+ const bodyFields = Array.isArray(config.body) ? config.body : [config.body];
115
+ for (const field of bodyFields) {
116
+ var _request$body;
117
+ const value = (_request$body = request.body) === null || _request$body === void 0 ? void 0 : _request$body[field];
118
+ if (value) return value;
119
+ }
120
+ }
121
+ if (config.params) {
122
+ const paramFields = Array.isArray(config.params) ? config.params : [config.params];
123
+ for (const param of paramFields) {
124
+ var _request$params;
125
+ const value = (_request$params = request.params) === null || _request$params === void 0 ? void 0 : _request$params[param];
126
+ if (value) return value;
127
+ }
128
+ }
129
+ }
130
+ /**
131
+ * Create trace ID middleware for Express/NestJS
132
+ */
133
+ function createTraceMiddleware(config) {
134
+ return (req, res, next) => {
135
+ let traceId;
136
+ if (config.extractor) traceId = extractTraceId(req, config.extractor);
137
+ if (!traceId) traceId = config.generator ? config.generator() : generateTraceId();
138
+ req.traceId = traceId;
139
+ res.setHeader("X-Trace-Id", traceId);
140
+ runWithTraceId(traceId, () => {
141
+ next();
142
+ }, { requestId: req.id || generateTraceId() });
143
+ };
144
+ }
145
+
146
+ //#endregion
147
+ //#region src/utils/error.utils.ts
148
+ /**
149
+ * Serialize error object to JSON-safe format
150
+ */
151
+ function serializeError(error, options = {}) {
152
+ const { includeStack = true, maxDepth = 3, excludeFields = [] } = options;
153
+ const serialized = {
154
+ name: error.name,
155
+ message: error.message
156
+ };
157
+ if (includeStack && error.stack) serialized.stack = error.stack;
158
+ const errorKeys = Object.getOwnPropertyNames(error);
159
+ for (const key of errorKeys) if (key !== "name" && key !== "message" && key !== "stack" && !excludeFields.includes(key)) try {
160
+ const value = error[key];
161
+ serialized[key] = serializeValue(value, maxDepth);
162
+ } catch {}
163
+ return serialized;
164
+ }
165
+ /**
166
+ * Recursively serialize values with depth limit
167
+ */
168
+ function serializeValue(value, maxDepth, currentDepth = 0) {
169
+ if (currentDepth >= maxDepth) return "[Max Depth Reached]";
170
+ if (value === null || value === void 0) return value;
171
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
172
+ if (value instanceof Date) return value.toISOString();
173
+ if (value instanceof Error) return serializeError(value, { maxDepth: maxDepth - currentDepth });
174
+ if (Array.isArray(value)) return value.map((item) => serializeValue(item, maxDepth, currentDepth + 1));
175
+ if (typeof value === "object") {
176
+ const serialized = {};
177
+ for (const [key, val] of Object.entries(value)) try {
178
+ serialized[key] = serializeValue(val, maxDepth, currentDepth + 1);
179
+ } catch {
180
+ serialized[key] = "[Unserializable]";
181
+ }
182
+ return serialized;
183
+ }
184
+ return String(value);
185
+ }
186
+ /**
187
+ * Check if value is an Error instance
188
+ */
189
+ function isError(value) {
190
+ return value instanceof Error || value && typeof value === "object" && "name" in value && "message" in value;
191
+ }
192
+ /**
193
+ * Create error from various input types
194
+ */
195
+ function normalizeError(error) {
196
+ if (isError(error)) return error;
197
+ if (typeof error === "string") return new Error(error);
198
+ if (typeof error === "object" && error !== null) {
199
+ const err = new Error(error.message || "Unknown error");
200
+ Object.assign(err, error);
201
+ return err;
202
+ }
203
+ return new Error(String(error));
204
+ }
205
+
206
+ //#endregion
207
+ //#region src/core/logitron-logger.ts
208
+ var LogixiaLogger = class LogixiaLogger {
209
+ constructor(config, context) {
210
+ this.timers = /* @__PURE__ */ new Map();
211
+ this.contextData = {};
212
+ this.config = {
213
+ appName: "App",
214
+ environment: "development",
215
+ traceId: true,
216
+ format: {
217
+ timestamp: true,
218
+ colorize: true,
219
+ json: false
220
+ },
221
+ silent: false,
222
+ levelOptions: {
223
+ level: LogLevel.INFO,
224
+ levels: {
225
+ [LogLevel.ERROR]: 0,
226
+ [LogLevel.WARN]: 1,
227
+ [LogLevel.INFO]: 2,
228
+ [LogLevel.DEBUG]: 3,
229
+ [LogLevel.TRACE]: 4,
230
+ [LogLevel.VERBOSE]: 5
231
+ },
232
+ colors: {
233
+ [LogLevel.ERROR]: "red",
234
+ [LogLevel.WARN]: "yellow",
235
+ [LogLevel.INFO]: "blue",
236
+ [LogLevel.DEBUG]: "green",
237
+ [LogLevel.TRACE]: "gray",
238
+ [LogLevel.VERBOSE]: "cyan"
239
+ }
240
+ },
241
+ ...config
242
+ };
243
+ if (!this.config.fields) this.config.fields = {
244
+ timestamp: "[yyyy-mm-dd HH:MM:ss.MS]",
245
+ level: "[log_level]",
246
+ appName: "[app_name]",
247
+ traceId: "[trace_id]",
248
+ message: "[message]",
249
+ payload: "[payload]",
250
+ timeTaken: "[time_taken_MS]"
251
+ };
252
+ this.context = context ?? "";
253
+ this.createCustomLevelMethods();
254
+ }
255
+ /**
256
+ * Create dynamic methods for custom levels
257
+ */
258
+ createCustomLevelMethods() {
259
+ var _this$config$levelOpt;
260
+ if ((_this$config$levelOpt = this.config.levelOptions) === null || _this$config$levelOpt === void 0 ? void 0 : _this$config$levelOpt.levels) Object.keys(this.config.levelOptions.levels).forEach((levelName) => {
261
+ if (!this[levelName.toLowerCase()]) this[levelName.toLowerCase()] = async (message, data) => {
262
+ await this.log(levelName.toLowerCase(), message, data);
263
+ };
264
+ });
265
+ }
266
+ /**
267
+ * Error logging with overloads
268
+ */
269
+ async error(messageOrError, data) {
270
+ if (isError(messageOrError)) await this.log("error", messageOrError.message, {
271
+ ...data,
272
+ error: serializeError(messageOrError)
273
+ });
274
+ else await this.log("error", messageOrError, data);
275
+ }
276
+ async warn(message, data) {
277
+ await this.log("warn", message, data);
278
+ }
279
+ async info(message, data) {
280
+ await this.log("info", message, data);
281
+ }
282
+ async debug(message, data) {
283
+ await this.log("debug", message, data);
284
+ }
285
+ async trace(message, data) {
286
+ await this.log("trace", message, data);
287
+ }
288
+ async verbose(message, data) {
289
+ await this.log("verbose", message, data);
290
+ }
291
+ /**
292
+ * Log with custom level
293
+ */
294
+ async logLevel(level, message, data) {
295
+ await this.log(level, message, data);
296
+ }
297
+ /**
298
+ * Timing methods
299
+ */
300
+ time(label) {
301
+ this.timers.set(label, {
302
+ label,
303
+ startTime: Date.now()
304
+ });
305
+ }
306
+ async timeEnd(label) {
307
+ const timer = this.timers.get(label);
308
+ if (!timer) {
309
+ await this.warn(`Timer '${label}' does not exist`);
310
+ return;
311
+ }
312
+ const endTime = Date.now();
313
+ const duration = endTime - timer.startTime;
314
+ timer.endTime = endTime;
315
+ timer.duration = duration;
316
+ await this.info(`Timer '${label}' finished`, {
317
+ duration: `${duration}ms`,
318
+ startTime: new Date(timer.startTime).toISOString(),
319
+ endTime: new Date(endTime).toISOString()
320
+ });
321
+ this.timers.delete(label);
322
+ return duration;
323
+ }
324
+ async timeAsync(label, fn) {
325
+ this.time(label);
326
+ try {
327
+ const result = await fn();
328
+ await this.timeEnd(label);
329
+ return result;
330
+ } catch (error) {
331
+ await this.timeEnd(label);
332
+ throw error;
333
+ }
334
+ }
335
+ /**
336
+ * Level and context management
337
+ */
338
+ setLevel(level) {
339
+ this.config.levelOptions = this.config.levelOptions || {};
340
+ this.config.levelOptions.level = level;
341
+ }
342
+ getLevel() {
343
+ var _this$config$levelOpt2;
344
+ return ((_this$config$levelOpt2 = this.config.levelOptions) === null || _this$config$levelOpt2 === void 0 ? void 0 : _this$config$levelOpt2.level) || LogLevel.INFO;
345
+ }
346
+ setContext(context) {
347
+ this.context = context;
348
+ }
349
+ getContext() {
350
+ return this.context;
351
+ }
352
+ /**
353
+ * Create child logger
354
+ */
355
+ child(context, data) {
356
+ const childLogger = new LogixiaLogger(this.config, context);
357
+ if (data) childLogger.contextData = {
358
+ ...this.contextData,
359
+ ...data
360
+ };
361
+ return childLogger;
362
+ }
363
+ /**
364
+ * Close logger and cleanup resources
365
+ */
366
+ async close() {
367
+ for (const [label, timer] of this.timers) await this.warn(`Timer '${label}' was not ended properly`, {
368
+ startTime: new Date(timer.startTime).toISOString(),
369
+ duration: `${Date.now() - timer.startTime}ms (incomplete)`
370
+ });
371
+ this.timers.clear();
372
+ }
373
+ /**
374
+ * Core logging method
375
+ */
376
+ async log(level, message, data) {
377
+ if (this.config.silent) return;
378
+ if (!this.shouldLog(level)) return;
379
+ const entry = {
380
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
381
+ level,
382
+ appName: this.config.appName ?? "App",
383
+ message,
384
+ ...this.context && { context: this.context },
385
+ payload: {
386
+ ...this.contextData,
387
+ ...data
388
+ }
389
+ };
390
+ if (this.config.traceId) entry.traceId = getCurrentTraceId() || generateTraceId();
391
+ const formattedLog = this.formatLog(entry);
392
+ this.output(formattedLog, level);
393
+ }
394
+ /**
395
+ * Format log entry according to configuration
396
+ */
397
+ formatLog(entry) {
398
+ var _this$config$format, _this$config$format2, _this$config$format3, _this$config$levelOpt3;
399
+ if ((_this$config$format = this.config.format) === null || _this$config$format === void 0 ? void 0 : _this$config$format.json) return JSON.stringify(entry);
400
+ let formatted = "";
401
+ if (((_this$config$format2 = this.config.format) === null || _this$config$format2 === void 0 ? void 0 : _this$config$format2.timestamp) !== false) {
402
+ const timestamp = new Date(entry.timestamp).toLocaleString();
403
+ formatted += `[${timestamp}] `;
404
+ }
405
+ const levelName = entry.level;
406
+ const coloredLevel = ((_this$config$format3 = this.config.format) === null || _this$config$format3 === void 0 ? void 0 : _this$config$format3.colorize) ? this.colorize(levelName.toUpperCase(), ((_this$config$levelOpt3 = this.config.levelOptions) === null || _this$config$levelOpt3 === void 0 || (_this$config$levelOpt3 = _this$config$levelOpt3.colors) === null || _this$config$levelOpt3 === void 0 ? void 0 : _this$config$levelOpt3[levelName]) || "white") : levelName.toUpperCase();
407
+ formatted += `[${coloredLevel}] `;
408
+ formatted += `[${entry.appName}] `;
409
+ if (entry.traceId) formatted += `[${entry.traceId}] `;
410
+ if (entry.context) formatted += `[${entry.context}] `;
411
+ formatted += entry.message;
412
+ if (entry.payload && Object.keys(entry.payload).length > 0) formatted += ` ${JSON.stringify(entry.payload)}`;
413
+ return formatted;
414
+ }
415
+ /**
416
+ * Colorize text based on color name
417
+ */
418
+ colorize(text, color) {
419
+ var _this$config$format4;
420
+ if (!((_this$config$format4 = this.config.format) === null || _this$config$format4 === void 0 ? void 0 : _this$config$format4.colorize)) return text;
421
+ const colors = {
422
+ red: "\x1B[31m",
423
+ green: "\x1B[32m",
424
+ yellow: "\x1B[33m",
425
+ blue: "\x1B[34m",
426
+ magenta: "\x1B[35m",
427
+ cyan: "\x1B[36m",
428
+ white: "\x1B[37m",
429
+ gray: "\x1B[90m",
430
+ reset: "\x1B[0m"
431
+ };
432
+ return `${colors[color.toLowerCase()] || colors.white}${text}${colors.reset}`;
433
+ }
434
+ shouldLog(level) {
435
+ var _this$config$levelOpt4;
436
+ const currentLevel = this.getLevel();
437
+ const levelMap = {
438
+ [LogLevel.ERROR]: 0,
439
+ [LogLevel.WARN]: 1,
440
+ [LogLevel.INFO]: 2,
441
+ [LogLevel.DEBUG]: 3,
442
+ [LogLevel.TRACE]: 4,
443
+ [LogLevel.VERBOSE]: 5,
444
+ ...((_this$config$levelOpt4 = this.config.levelOptions) === null || _this$config$levelOpt4 === void 0 ? void 0 : _this$config$levelOpt4.levels) || {}
445
+ };
446
+ const currentLevelValue = levelMap[currentLevel];
447
+ const messageLevelValue = levelMap[level];
448
+ return messageLevelValue !== void 0 && currentLevelValue !== void 0 && messageLevelValue <= currentLevelValue;
449
+ }
450
+ /**
451
+ * Output log to console or other destinations
452
+ */
453
+ output(message, level) {
454
+ switch (level) {
455
+ case LogLevel.ERROR:
456
+ console.error(message);
457
+ break;
458
+ case LogLevel.WARN:
459
+ console.warn(message);
460
+ break;
461
+ case LogLevel.DEBUG:
462
+ case LogLevel.TRACE:
463
+ console.debug(message);
464
+ break;
465
+ default: console.log(message);
466
+ }
467
+ }
468
+ };
469
+ /**
470
+ * Factory function to create a typed logger with custom levels
471
+ */
472
+ function createLogger$1(config, context) {
473
+ var _config$levelOptions;
474
+ const logger$1 = new LogixiaLogger(config, context);
475
+ if ((_config$levelOptions = config.levelOptions) === null || _config$levelOptions === void 0 ? void 0 : _config$levelOptions.levels) Object.keys(config.levelOptions.levels).forEach((levelName) => {
476
+ if (!logger$1[levelName]) logger$1[levelName] = async (message, data) => {
477
+ await logger$1.log(levelName, message, data);
478
+ };
479
+ });
480
+ return logger$1;
481
+ }
482
+
483
+ //#endregion
484
+ //#region node_modules/.pnpm/@oxc-project+runtime@0.87.0/node_modules/@oxc-project/runtime/src/helpers/decorateMetadata.js
485
+ var require_decorateMetadata = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/@oxc-project+runtime@0.87.0/node_modules/@oxc-project/runtime/src/helpers/decorateMetadata.js": ((exports, module) => {
486
+ function __decorateMetadata(k, v) {
487
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
488
+ }
489
+ module.exports = __decorateMetadata, module.exports.__esModule = true, module.exports["default"] = module.exports;
490
+ }) });
491
+
492
+ //#endregion
493
+ //#region node_modules/.pnpm/@oxc-project+runtime@0.87.0/node_modules/@oxc-project/runtime/src/helpers/decorate.js
494
+ var require_decorate = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/@oxc-project+runtime@0.87.0/node_modules/@oxc-project/runtime/src/helpers/decorate.js": ((exports, module) => {
495
+ function __decorate(decorators, target, key, desc) {
496
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
497
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
498
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
499
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
500
+ }
501
+ module.exports = __decorate, module.exports.__esModule = true, module.exports["default"] = module.exports;
502
+ }) });
503
+
504
+ //#endregion
505
+ //#region src/core/logitron-nestjs.service.ts
506
+ var import_decorateMetadata$1 = /* @__PURE__ */ __toESM(require_decorateMetadata());
507
+ var import_decorate$2 = /* @__PURE__ */ __toESM(require_decorate());
508
+ var _LogixiaLoggerService;
509
+ let LogixiaLoggerService = _LogixiaLoggerService = class LogixiaLoggerService$1 {
510
+ constructor(config) {
511
+ const defaultConfig = {
512
+ appName: "NestJS-App",
513
+ environment: "development",
514
+ traceId: true,
515
+ format: {
516
+ timestamp: true,
517
+ colorize: true,
518
+ json: false
519
+ },
520
+ silent: false,
521
+ levelOptions: {
522
+ level: LogLevel.INFO,
523
+ levels: {
524
+ error: 0,
525
+ warn: 1,
526
+ log: 2,
527
+ debug: 3,
528
+ verbose: 4
529
+ },
530
+ colors: {
531
+ error: "red",
532
+ warn: "yellow",
533
+ log: "green",
534
+ debug: "blue",
535
+ verbose: "cyan"
536
+ }
537
+ },
538
+ fields: {
539
+ timestamp: "[yyyy-mm-dd HH:MM:ss.MS]",
540
+ level: "[log_level]",
541
+ appName: "[app_name]",
542
+ traceId: "[trace_id]",
543
+ message: "[message]",
544
+ payload: "[payload]",
545
+ timeTaken: "[time_taken_MS]"
546
+ }
547
+ };
548
+ this.logger = new LogixiaLogger({
549
+ ...defaultConfig,
550
+ ...config
551
+ });
552
+ }
553
+ /**
554
+ * NestJS LoggerService interface implementation
555
+ */
556
+ log(message, context) {
557
+ this.setContextIfProvided(context);
558
+ this.logger.info(this.formatMessage(message)).catch(console.error);
559
+ }
560
+ error(message, trace, context) {
561
+ this.setContextIfProvided(context);
562
+ const errorData = {};
563
+ if (trace) errorData.stack = trace;
564
+ if (typeof message === "object" && message instanceof Error) this.logger.error(message, errorData).catch(console.error);
565
+ else this.logger.error(this.formatMessage(message), errorData).catch(console.error);
566
+ }
567
+ warn(message, context) {
568
+ this.setContextIfProvided(context);
569
+ this.logger.warn(this.formatMessage(message)).catch(console.error);
570
+ }
571
+ debug(message, context) {
572
+ this.setContextIfProvided(context);
573
+ this.logger.debug(this.formatMessage(message)).catch(console.error);
574
+ }
575
+ verbose(message, context) {
576
+ this.setContextIfProvided(context);
577
+ this.logger.trace(this.formatMessage(message)).catch(console.error);
578
+ }
579
+ /**
580
+ * Extended Logitron methods
581
+ */
582
+ async info(message, data) {
583
+ return this.logger.info(message, data);
584
+ }
585
+ async trace(message, data) {
586
+ return this.logger.trace(message, data);
587
+ }
588
+ logLevel(level, message, data) {
589
+ return this.logger.logLevel(level, message, data);
590
+ }
591
+ /**
592
+ * Timing methods
593
+ */
594
+ time(label) {
595
+ this.logger.time(label);
596
+ }
597
+ async timeEnd(label) {
598
+ return this.logger.timeEnd(label);
599
+ }
600
+ async timeAsync(label, fn) {
601
+ return this.logger.timeAsync(label, fn);
602
+ }
603
+ /**
604
+ * Context and level management
605
+ */
606
+ setContext(context) {
607
+ this.context = context;
608
+ this.logger.setContext(context);
609
+ }
610
+ getContext() {
611
+ return this.context;
612
+ }
613
+ setLevel(level) {
614
+ this.logger.setLevel(level);
615
+ }
616
+ getLevel() {
617
+ return this.logger.getLevel();
618
+ }
619
+ /**
620
+ * Create child logger
621
+ */
622
+ child(context, data) {
623
+ const childService = new _LogixiaLoggerService();
624
+ childService.logger = this.logger.child(context, data);
625
+ childService.context = context;
626
+ return childService;
627
+ }
628
+ /**
629
+ * Get current trace ID
630
+ */
631
+ getCurrentTraceId() {
632
+ return getCurrentTraceId();
633
+ }
634
+ /**
635
+ * Close logger
636
+ */
637
+ async close() {
638
+ return this.logger.close();
639
+ }
640
+ /**
641
+ * Private helper methods
642
+ */
643
+ setContextIfProvided(context) {
644
+ if (context && context !== this.context) this.setContext(context);
645
+ }
646
+ formatMessage(message) {
647
+ if (typeof message === "string") return message;
648
+ if (typeof message === "object") return JSON.stringify(message);
649
+ return String(message);
650
+ }
651
+ /**
652
+ * Static factory method for easy instantiation
653
+ */
654
+ static create(config) {
655
+ return new _LogixiaLoggerService(config);
656
+ }
657
+ /**
658
+ * Get the underlying Logitron logger instance
659
+ */
660
+ getLogger() {
661
+ return this.logger;
662
+ }
663
+ };
664
+ LogixiaLoggerService = _LogixiaLoggerService = (0, import_decorate$2.default)([Injectable({ scope: Scope.TRANSIENT }), (0, import_decorateMetadata$1.default)("design:paramtypes", [Object])], LogixiaLoggerService);
665
+
666
+ //#endregion
667
+ //#region src/core/trace.middleware.ts
668
+ var import_decorateMetadata = /* @__PURE__ */ __toESM(require_decorateMetadata());
669
+ var import_decorate$1 = /* @__PURE__ */ __toESM(require_decorate());
670
+ let TraceMiddleware = class TraceMiddleware$1 {
671
+ constructor(config) {
672
+ this.config = config;
673
+ this.config = {
674
+ enabled: true,
675
+ generator: generateTraceId,
676
+ contextKey: "traceId",
677
+ extractor: {
678
+ header: [
679
+ "x-trace-id",
680
+ "x-request-id",
681
+ "trace-id"
682
+ ],
683
+ query: ["traceId", "trace_id"]
684
+ },
685
+ ...config
686
+ };
687
+ }
688
+ use(req, res, next) {
689
+ var _this$config;
690
+ if (!((_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.enabled)) return next();
691
+ let traceId;
692
+ if (this.config.extractor) traceId = extractTraceId(req, this.config.extractor);
693
+ if (!traceId) traceId = this.config.generator ? this.config.generator() : generateTraceId();
694
+ req.traceId = traceId;
695
+ req.requestId = req.requestId || generateTraceId();
696
+ res.setHeader("X-Trace-Id", traceId);
697
+ res.setHeader("X-Request-Id", req.requestId);
698
+ runWithTraceId(traceId, () => {
699
+ next();
700
+ }, {
701
+ requestId: req.requestId,
702
+ method: req.method,
703
+ url: req.url,
704
+ userAgent: req.get("User-Agent"),
705
+ ip: req.ip || req.connection.remoteAddress
706
+ });
707
+ }
708
+ };
709
+ TraceMiddleware = (0, import_decorate$1.default)([Injectable(), (0, import_decorateMetadata.default)("design:paramtypes", [Object])], TraceMiddleware);
710
+
711
+ //#endregion
712
+ //#region src/core/logitron-logger.module.ts
713
+ var import_decorate = /* @__PURE__ */ __toESM(require_decorate());
714
+ var _LogixiaLoggerModule;
715
+ const DEFAULT_ROUTES = [{
716
+ path: "*",
717
+ method: RequestMethod.ALL
718
+ }];
719
+ const LOGIXIA_LOGGER_CONFIG = "LOGIXIA_LOGGER_CONFIG";
720
+ const LOGIXIA_LOGGER_PREFIX = "LOGIXIA_LOGGER_";
721
+ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
722
+ static {
723
+ _LogixiaLoggerModule = this;
724
+ }
725
+ constructor() {
726
+ this.config = {};
727
+ }
728
+ static #_ = this.loggerConfig = {};
729
+ configure(consumer) {
730
+ const { forRoutes = DEFAULT_ROUTES, exclude } = this.config;
731
+ const middlewareConfig = (req, res, next) => {
732
+ let traceConfig;
733
+ if (typeof _LogixiaLoggerModule.loggerConfig.traceId === "object") traceConfig = _LogixiaLoggerModule.loggerConfig.traceId;
734
+ else if (_LogixiaLoggerModule.loggerConfig.traceId === true) traceConfig = {
735
+ enabled: true,
736
+ contextKey: "traceId",
737
+ generator: () => {
738
+ const timestamp = Date.now().toString(36);
739
+ const random = Math.random().toString(36).substring(2, 8);
740
+ return `${timestamp}-${random}`;
741
+ }
742
+ };
743
+ else traceConfig = void 0;
744
+ return new TraceMiddleware(traceConfig).use(req, res, next);
745
+ };
746
+ if (exclude) consumer.apply(middlewareConfig).exclude(...exclude).forRoutes(...forRoutes);
747
+ else consumer.apply(middlewareConfig).forRoutes(...forRoutes);
748
+ }
749
+ /**
750
+ * Configure the module with synchronous options
751
+ */
752
+ static forRoot(config) {
753
+ _LogixiaLoggerModule.loggerConfig = config || {};
754
+ return {
755
+ module: _LogixiaLoggerModule,
756
+ providers: [{
757
+ provide: LOGIXIA_LOGGER_CONFIG,
758
+ useValue: config || {}
759
+ }, {
760
+ provide: LogixiaLoggerService,
761
+ useFactory: (loggerConfig) => {
762
+ const defaultConfig = {
763
+ level: "info",
764
+ service: "NestJSApp",
765
+ environment: "development",
766
+ fields: {},
767
+ formatters: ["text"],
768
+ outputs: ["console"],
769
+ levelOptions: {
770
+ level: "info",
771
+ levels: {
772
+ error: 0,
773
+ warn: 1,
774
+ info: 2,
775
+ debug: 3,
776
+ verbose: 4
777
+ },
778
+ colors: {
779
+ error: "red",
780
+ warn: "yellow",
781
+ info: "green",
782
+ debug: "blue",
783
+ verbose: "cyan"
784
+ }
785
+ },
786
+ ...loggerConfig
787
+ };
788
+ return new LogixiaLoggerService(defaultConfig);
789
+ },
790
+ inject: [LOGIXIA_LOGGER_CONFIG]
791
+ }],
792
+ exports: [LogixiaLoggerService, LOGIXIA_LOGGER_CONFIG],
793
+ global: true
794
+ };
795
+ }
796
+ /**
797
+ * Configure the module with asynchronous options
798
+ */
799
+ static forRootAsync(options) {
800
+ return {
801
+ module: _LogixiaLoggerModule,
802
+ imports: options.imports || [],
803
+ providers: [...this.createAsyncProviders(options), {
804
+ provide: LogixiaLoggerService,
805
+ useFactory: (loggerConfig) => {
806
+ const defaultConfig = {
807
+ level: "info",
808
+ service: "NestJSApp",
809
+ environment: "development",
810
+ fields: {},
811
+ formatters: ["text"],
812
+ outputs: ["console"],
813
+ levelOptions: {
814
+ level: "info",
815
+ levels: {
816
+ error: 0,
817
+ warn: 1,
818
+ info: 2,
819
+ debug: 3,
820
+ verbose: 4
821
+ },
822
+ colors: {
823
+ error: "red",
824
+ warn: "yellow",
825
+ info: "green",
826
+ debug: "blue",
827
+ verbose: "cyan"
828
+ }
829
+ },
830
+ ...loggerConfig
831
+ };
832
+ _LogixiaLoggerModule.loggerConfig = defaultConfig;
833
+ return new LogixiaLoggerService(defaultConfig);
834
+ },
835
+ inject: [LOGIXIA_LOGGER_CONFIG]
836
+ }],
837
+ exports: [LogixiaLoggerService, LOGIXIA_LOGGER_CONFIG],
838
+ global: true
839
+ };
840
+ }
841
+ /**
842
+ * Create feature-specific logger instances
843
+ */
844
+ static forFeature(context) {
845
+ const providerToken = `${LOGIXIA_LOGGER_PREFIX}${context.toUpperCase()}`;
846
+ return {
847
+ module: _LogixiaLoggerModule,
848
+ providers: [{
849
+ provide: providerToken,
850
+ useFactory: (baseLogger) => {
851
+ return baseLogger.child(context);
852
+ },
853
+ inject: [LogixiaLoggerService]
854
+ }],
855
+ exports: [providerToken]
856
+ };
857
+ }
858
+ static createAsyncProviders(options) {
859
+ if (options.useExisting || options.useFactory) return [this.createAsyncOptionsProvider(options)];
860
+ return [this.createAsyncOptionsProvider(options), {
861
+ provide: options.useClass,
862
+ useClass: options.useClass
863
+ }];
864
+ }
865
+ static createAsyncOptionsProvider(options) {
866
+ if (options.useFactory) return {
867
+ provide: LOGIXIA_LOGGER_CONFIG,
868
+ useFactory: options.useFactory,
869
+ inject: options.inject || []
870
+ };
871
+ return {
872
+ provide: LOGIXIA_LOGGER_CONFIG,
873
+ useFactory: async (optionsFactory) => await optionsFactory.createLogixiaOptions(),
874
+ inject: [options.useExisting || options.useClass]
875
+ };
876
+ }
877
+ };
878
+ LogixiaLoggerModule = _LogixiaLoggerModule = (0, import_decorate.default)([Module({})], LogixiaLoggerModule);
879
+
880
+ //#endregion
881
+ //#region src/formatters/json.formatter.ts
882
+ var JsonFormatter = class {
883
+ constructor(options = {}) {
884
+ this.includeTimestamp = options.includeTimestamp ?? true;
885
+ this.includeLevel = options.includeLevel ?? true;
886
+ this.includeAppName = options.includeAppName ?? true;
887
+ this.includeTraceId = options.includeTraceId ?? true;
888
+ this.includeContext = options.includeContext ?? true;
889
+ this.prettyPrint = options.prettyPrint ?? false;
890
+ }
891
+ format(entry) {
892
+ const formatted = {};
893
+ if (this.includeTimestamp) formatted.timestamp = entry.timestamp;
894
+ if (this.includeLevel) {
895
+ formatted.level = entry.level.toLowerCase();
896
+ formatted.levelValue = entry.level;
897
+ }
898
+ if (this.includeAppName) formatted.appName = entry.appName;
899
+ if (this.includeTraceId && entry.traceId) formatted.traceId = entry.traceId;
900
+ if (this.includeContext && entry.context) formatted.context = entry.context;
901
+ formatted.message = entry.message;
902
+ if (entry.payload && Object.keys(entry.payload).length > 0) formatted.payload = this.serializePayload(entry.payload);
903
+ if (entry.error) formatted.error = serializeError(entry.error);
904
+ formatted.meta = {
905
+ pid: process.pid,
906
+ hostname: process.env.HOSTNAME || "unknown",
907
+ version: process.version
908
+ };
909
+ return this.prettyPrint ? JSON.stringify(formatted, null, 2) : JSON.stringify(formatted);
910
+ }
911
+ serializePayload(payload) {
912
+ const serialized = {};
913
+ for (const [key, value] of Object.entries(payload)) try {
914
+ if (value instanceof Error) serialized[key] = serializeError(value);
915
+ else if (value instanceof Date) serialized[key] = value.toISOString();
916
+ else if (typeof value === "function") serialized[key] = "[Function]";
917
+ else if (typeof value === "symbol") serialized[key] = value.toString();
918
+ else if (value === void 0) serialized[key] = null;
919
+ else serialized[key] = value;
920
+ } catch {
921
+ serialized[key] = "[Unserializable]";
922
+ }
923
+ return serialized;
924
+ }
925
+ };
926
+
927
+ //#endregion
928
+ //#region src/formatters/text.formatter.ts
929
+ var TextFormatter = class TextFormatter {
930
+ constructor(options = {}) {
931
+ this.colorize = options.colorize ?? true;
932
+ this.includeTimestamp = options.includeTimestamp ?? true;
933
+ this.includeAppName = options.includeAppName ?? true;
934
+ this.includeTraceId = options.includeTraceId ?? true;
935
+ this.includeContext = options.includeContext ?? true;
936
+ this.timestampFormat = options.timestampFormat ?? "locale";
937
+ this.colors = {
938
+ error: "\x1B[31m",
939
+ warn: "\x1B[33m",
940
+ info: "\x1B[32m",
941
+ debug: "\x1B[34m",
942
+ trace: "\x1B[35m",
943
+ verbose: "\x1B[36m",
944
+ reset: "\x1B[0m",
945
+ bold: "\x1B[1m",
946
+ dim: "\x1B[2m",
947
+ ...options.colors
948
+ };
949
+ }
950
+ format(entry) {
951
+ const parts = [];
952
+ if (this.includeTimestamp) {
953
+ const timestamp = this.formatTimestamp(entry.timestamp);
954
+ parts.push(this.colorize ? `${this.colors.dim}${timestamp}${this.colors.reset}` : timestamp);
955
+ }
956
+ const levelName = entry.level.toLowerCase();
957
+ const levelColor = this.colors[levelName] || this.colors.reset;
958
+ const formattedLevel = this.colorize ? `${levelColor}${this.colors.bold}${levelName.toUpperCase().padEnd(5)}${this.colors.reset}` : levelName.toUpperCase().padEnd(5);
959
+ parts.push(`[${formattedLevel}]`);
960
+ if (this.includeAppName) {
961
+ const appName = this.colorize ? `${this.colors.bold}${entry.appName}${this.colors.reset}` : entry.appName;
962
+ parts.push(`[${appName}]`);
963
+ }
964
+ if (this.includeTraceId && entry.traceId) {
965
+ const traceId = this.colorize ? `${this.colors.dim}${entry.traceId}${this.colors.reset}` : entry.traceId;
966
+ parts.push(`[${traceId}]`);
967
+ }
968
+ if (this.includeContext && entry.context) {
969
+ const context = this.colorize ? `${this.colors.cyan}${entry.context}${this.colors.reset}` : entry.context;
970
+ parts.push(`[${context}]`);
971
+ }
972
+ const message = this.colorize && entry.level === LogLevel.ERROR ? `${this.colors.error}${entry.message}${this.colors.reset}` : entry.message;
973
+ parts.push(message);
974
+ if (entry.payload && Object.keys(entry.payload).length > 0) {
975
+ const payload = this.formatPayload(entry.payload);
976
+ if (payload) parts.push(this.colorize ? `${this.colors.dim}${payload}${this.colors.reset}` : payload);
977
+ }
978
+ return parts.join(" ");
979
+ }
980
+ formatTimestamp(timestamp) {
981
+ const date = new Date(timestamp);
982
+ switch (this.timestampFormat) {
983
+ case "iso": return date.toISOString();
984
+ case "short": return date.toLocaleTimeString();
985
+ case "locale":
986
+ default: return date.toLocaleString();
987
+ }
988
+ }
989
+ formatPayload(payload) {
990
+ try {
991
+ if (Object.keys(payload).length === 1) {
992
+ const entry = Object.entries(payload)[0];
993
+ if (entry) {
994
+ const [key, value] = entry;
995
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return `${key}=${value}`;
996
+ }
997
+ }
998
+ return Object.entries(payload).map(([key, value]) => {
999
+ if (value === null || value === void 0) return `${key}=${value}`;
1000
+ if (typeof value === "string") return `${key}="${value}"`;
1001
+ if (typeof value === "number" || typeof value === "boolean") return `${key}=${value}`;
1002
+ if (value instanceof Date) return `${key}=${value.toISOString()}`;
1003
+ if (typeof value === "object") return `${key}=${JSON.stringify(value)}`;
1004
+ return `${key}=${String(value)}`;
1005
+ }).join(" ");
1006
+ } catch {
1007
+ return JSON.stringify(payload);
1008
+ }
1009
+ }
1010
+ /**
1011
+ * Create a formatter with preset configurations
1012
+ */
1013
+ static createSimple() {
1014
+ return new TextFormatter({
1015
+ colorize: true,
1016
+ includeTimestamp: true,
1017
+ includeAppName: false,
1018
+ includeTraceId: false,
1019
+ includeContext: true,
1020
+ timestampFormat: "short"
1021
+ });
1022
+ }
1023
+ static createDetailed() {
1024
+ return new TextFormatter({
1025
+ colorize: true,
1026
+ includeTimestamp: true,
1027
+ includeAppName: true,
1028
+ includeTraceId: true,
1029
+ includeContext: true,
1030
+ timestampFormat: "locale"
1031
+ });
1032
+ }
1033
+ static createMinimal() {
1034
+ return new TextFormatter({
1035
+ colorize: false,
1036
+ includeTimestamp: false,
1037
+ includeAppName: false,
1038
+ includeTraceId: false,
1039
+ includeContext: false
1040
+ });
1041
+ }
1042
+ };
1043
+
1044
+ //#endregion
1045
+ //#region src/index.ts
1046
+ /**
1047
+ * Default configuration for Logitron logger
1048
+ */
1049
+ const DEFAULT_CONFIG = {
1050
+ appName: "App",
1051
+ environment: "development",
1052
+ traceId: true,
1053
+ format: {
1054
+ timestamp: true,
1055
+ colorize: true,
1056
+ json: false
1057
+ },
1058
+ silent: false,
1059
+ levelOptions: {
1060
+ level: LogLevel.INFO,
1061
+ levels: {
1062
+ [LogLevel.ERROR]: 0,
1063
+ [LogLevel.WARN]: 1,
1064
+ [LogLevel.INFO]: 2,
1065
+ [LogLevel.DEBUG]: 3,
1066
+ [LogLevel.TRACE]: 4,
1067
+ [LogLevel.VERBOSE]: 5
1068
+ },
1069
+ colors: {
1070
+ [LogLevel.ERROR]: "red",
1071
+ [LogLevel.WARN]: "yellow",
1072
+ [LogLevel.INFO]: "blue",
1073
+ [LogLevel.DEBUG]: "green",
1074
+ [LogLevel.TRACE]: "gray",
1075
+ [LogLevel.VERBOSE]: "cyan"
1076
+ }
1077
+ },
1078
+ fields: {
1079
+ timestamp: true,
1080
+ level: true,
1081
+ appName: true,
1082
+ traceId: true,
1083
+ message: true,
1084
+ payload: true,
1085
+ timeTaken: true
1086
+ },
1087
+ outputs: ["console"]
1088
+ };
1089
+ /**
1090
+ * Create a new Logitron logger instance with TypeScript support for custom levels
1091
+ * @param config - Logger configuration
1092
+ * @returns Typed logger instance
1093
+ */
1094
+ const createLogger = createLogger$1;
1095
+ /**
1096
+ * Create a new Logitron logger service for NestJS
1097
+ * @param config - Logger configuration
1098
+ * @returns LogixiaLoggerService instance
1099
+ */
1100
+ function createLoggerService(config) {
1101
+ return new LogixiaLoggerService({
1102
+ ...DEFAULT_CONFIG,
1103
+ ...config
1104
+ });
1105
+ }
1106
+ /**
1107
+ * Default logger instance
1108
+ */
1109
+ const logger = new LogixiaLogger(DEFAULT_CONFIG);
1110
+ /**
1111
+ * Export default configuration for reference
1112
+ */
1113
+ //#endregion
1114
+ export { DEFAULT_CONFIG, DEFAULT_LOG_COLORS, DEFAULT_LOG_LEVELS, JsonFormatter, LOGIXIA_LOGGER_CONFIG, LOGIXIA_LOGGER_PREFIX, LogLevel, LogixiaLogger, LogixiaLoggerModule, LogixiaLoggerService, TextFormatter, createLogger, createLoggerService, createTraceMiddleware, extractTraceId, generateTraceId, getCurrentTraceId, isError, logger, normalizeError, runWithTraceId, serializeError, setTraceId, traceStorage };
1115
+ //# sourceMappingURL=index.mjs.map