@rawnodes/logger 1.7.0 → 1.9.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.js CHANGED
@@ -4,11 +4,15 @@ var winston = require('winston');
4
4
  var async_hooks = require('async_hooks');
5
5
  var DailyRotateFile = require('winston-daily-rotate-file');
6
6
  var util = require('util');
7
+ var TransportStream = require('winston-transport');
8
+ var clientCloudwatchLogs = require('@aws-sdk/client-cloudwatch-logs');
9
+ var zod = require('zod');
7
10
  var crypto = require('crypto');
8
11
 
9
12
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
13
 
11
14
  var DailyRotateFile__default = /*#__PURE__*/_interopDefault(DailyRotateFile);
15
+ var TransportStream__default = /*#__PURE__*/_interopDefault(TransportStream);
12
16
 
13
17
  // src/state.ts
14
18
  var LoggerStore = class {
@@ -21,6 +25,26 @@ var LoggerStore = class {
21
25
  }
22
26
  };
23
27
 
28
+ // src/types.ts
29
+ var LOG_LEVELS = {
30
+ off: -1,
31
+ error: 0,
32
+ warn: 1,
33
+ info: 2,
34
+ http: 3,
35
+ verbose: 4,
36
+ debug: 5,
37
+ silly: 6
38
+ };
39
+ function isValidLogLevel(level) {
40
+ return level in LOG_LEVELS;
41
+ }
42
+ function assertLogLevel(level) {
43
+ if (!isValidLogLevel(level)) {
44
+ throw new Error(`Invalid log level: "${level}". Valid levels: ${Object.keys(LOG_LEVELS).join(", ")}`);
45
+ }
46
+ }
47
+
24
48
  // src/utils/mask-secrets.ts
25
49
  var DEFAULT_SECRET_PATTERNS = [
26
50
  "password",
@@ -175,6 +199,20 @@ function maskSecretsFormat(options) {
175
199
  return maskSecrets(info, options);
176
200
  })();
177
201
  }
202
+ function createFilterFormat(defaultLevel, rules, store) {
203
+ if (!rules?.length && defaultLevel === void 0) {
204
+ return winston.format((info) => info)();
205
+ }
206
+ return winston.format((info) => {
207
+ const logLevel = info.level;
208
+ const context = info.context;
209
+ const storeContext = store.getStore();
210
+ const matchingRule = rules?.find((rule) => matchesContext(storeContext, context, rule.match));
211
+ const effectiveLevel = matchingRule?.level ?? defaultLevel ?? "silly";
212
+ if (effectiveLevel === "off") return false;
213
+ return LOG_LEVELS[logLevel] <= LOG_LEVELS[effectiveLevel] ? info : false;
214
+ })();
215
+ }
178
216
  function createPlainFormat(store) {
179
217
  return winston.format.combine(
180
218
  winston.format.errors({ stack: true }),
@@ -239,17 +277,461 @@ function createFormat(logFormat, store) {
239
277
  }
240
278
  }
241
279
 
280
+ // src/transports/buffer.ts
281
+ var MessageBuffer = class {
282
+ constructor(options) {
283
+ this.options = options;
284
+ }
285
+ queue = [];
286
+ timer = null;
287
+ flushing = false;
288
+ closed = false;
289
+ add(message) {
290
+ if (this.closed) return;
291
+ this.queue.push(message);
292
+ if (this.queue.length >= this.options.batchSize) {
293
+ void this.flush();
294
+ } else {
295
+ this.scheduleFlush();
296
+ }
297
+ }
298
+ async flush() {
299
+ if (this.flushing || this.queue.length === 0) return;
300
+ this.flushing = true;
301
+ this.clearTimer();
302
+ const messages = this.queue.splice(0, this.options.batchSize);
303
+ try {
304
+ await this.sendWithRetry(messages);
305
+ } catch (error) {
306
+ this.options.onError?.(error, messages);
307
+ } finally {
308
+ this.flushing = false;
309
+ if (this.queue.length > 0 && !this.closed) {
310
+ void this.flush();
311
+ }
312
+ }
313
+ }
314
+ async close() {
315
+ this.closed = true;
316
+ this.clearTimer();
317
+ while (this.queue.length > 0) {
318
+ await this.flush();
319
+ }
320
+ }
321
+ scheduleFlush() {
322
+ if (this.timer || this.closed) return;
323
+ this.timer = setTimeout(() => {
324
+ this.timer = null;
325
+ void this.flush();
326
+ }, this.options.flushInterval);
327
+ }
328
+ clearTimer() {
329
+ if (this.timer) {
330
+ clearTimeout(this.timer);
331
+ this.timer = null;
332
+ }
333
+ }
334
+ async sendWithRetry(messages) {
335
+ let lastError = null;
336
+ for (let attempt = 0; attempt < this.options.maxRetries; attempt++) {
337
+ try {
338
+ await this.options.onFlush(messages);
339
+ return;
340
+ } catch (error) {
341
+ lastError = error;
342
+ if (attempt < this.options.maxRetries - 1) {
343
+ await this.delay(this.options.retryDelay * Math.pow(2, attempt));
344
+ }
345
+ }
346
+ }
347
+ throw lastError;
348
+ }
349
+ delay(ms) {
350
+ return new Promise((resolve) => setTimeout(resolve, ms));
351
+ }
352
+ };
353
+
354
+ // src/transports/base-http.ts
355
+ var DEFAULT_OPTIONS = {
356
+ batchSize: 10,
357
+ flushInterval: 5e3,
358
+ maxRetries: 3,
359
+ retryDelay: 1e3
360
+ };
361
+ var BaseHttpTransport = class extends TransportStream__default.default {
362
+ buffer;
363
+ constructor(opts = {}) {
364
+ super();
365
+ this.buffer = new MessageBuffer({
366
+ batchSize: opts.batchSize ?? DEFAULT_OPTIONS.batchSize,
367
+ flushInterval: opts.flushInterval ?? DEFAULT_OPTIONS.flushInterval,
368
+ maxRetries: opts.maxRetries ?? DEFAULT_OPTIONS.maxRetries,
369
+ retryDelay: opts.retryDelay ?? DEFAULT_OPTIONS.retryDelay,
370
+ onFlush: this.sendBatch.bind(this),
371
+ onError: this.handleError.bind(this)
372
+ });
373
+ }
374
+ log(info, callback) {
375
+ const message = this.transformMessage(info);
376
+ this.buffer.add(message);
377
+ callback();
378
+ }
379
+ close() {
380
+ return this.buffer.close();
381
+ }
382
+ transformMessage(info) {
383
+ const { level, message, timestamp, context, ...meta } = info;
384
+ return {
385
+ level,
386
+ message: String(message),
387
+ timestamp: timestamp ? new Date(String(timestamp)) : /* @__PURE__ */ new Date(),
388
+ context,
389
+ meta: Object.keys(meta).length > 0 ? meta : void 0
390
+ };
391
+ }
392
+ handleError(error, messages) {
393
+ console.error(
394
+ `[${this.constructor.name}] Failed to send ${messages.length} messages:`,
395
+ error.message
396
+ );
397
+ this.emit("error", error);
398
+ }
399
+ };
400
+
401
+ // src/transports/discord.ts
402
+ var DEFAULT_EMBED_COLORS = {
403
+ off: 0,
404
+ error: 15548997,
405
+ warn: 16705372,
406
+ info: 5763719,
407
+ http: 5793266,
408
+ verbose: 10181046,
409
+ debug: 3447003,
410
+ silly: 9807270
411
+ };
412
+ var DiscordTransport = class extends BaseHttpTransport {
413
+ config;
414
+ constructor(config) {
415
+ super({
416
+ batchSize: config.batchSize ?? 10,
417
+ flushInterval: config.flushInterval ?? 2e3,
418
+ maxRetries: config.maxRetries,
419
+ retryDelay: config.retryDelay
420
+ });
421
+ this.config = config;
422
+ }
423
+ async sendBatch(messages) {
424
+ const chunks = this.chunkArray(messages, 10);
425
+ for (const chunk of chunks) {
426
+ const payload = {
427
+ username: this.config.username,
428
+ avatar_url: this.config.avatarUrl,
429
+ embeds: chunk.map((msg) => this.createEmbed(msg))
430
+ };
431
+ await this.sendWebhook(payload);
432
+ }
433
+ }
434
+ createEmbed(msg) {
435
+ const color = this.config.embedColors?.[msg.level] ?? DEFAULT_EMBED_COLORS[msg.level];
436
+ const embed = {
437
+ title: `[${msg.level.toUpperCase()}] ${msg.context || "APP"}`,
438
+ description: msg.message.slice(0, 4096),
439
+ // Discord limit
440
+ color
441
+ };
442
+ if (this.config.includeTimestamp !== false) {
443
+ embed.timestamp = msg.timestamp.toISOString();
444
+ }
445
+ if (this.config.includeMeta !== false && msg.meta) {
446
+ embed.fields = this.metaToFields(msg.meta);
447
+ }
448
+ return embed;
449
+ }
450
+ metaToFields(meta) {
451
+ const maxFields = this.config.maxEmbedFields ?? 25;
452
+ const fields = [];
453
+ for (const [key, value] of Object.entries(meta)) {
454
+ if (fields.length >= maxFields) break;
455
+ let strValue;
456
+ if (typeof value === "object") {
457
+ strValue = "```json\n" + JSON.stringify(value, null, 2).slice(0, 1e3) + "\n```";
458
+ } else {
459
+ strValue = String(value).slice(0, 1024);
460
+ }
461
+ fields.push({
462
+ name: key.slice(0, 256),
463
+ value: strValue,
464
+ inline: typeof value !== "object" && String(value).length < 50
465
+ });
466
+ }
467
+ return fields;
468
+ }
469
+ async sendWebhook(payload) {
470
+ const response = await fetch(this.config.webhookUrl, {
471
+ method: "POST",
472
+ headers: { "Content-Type": "application/json" },
473
+ body: JSON.stringify(payload)
474
+ });
475
+ if (!response.ok) {
476
+ const text = await response.text();
477
+ throw new Error(`Discord webhook failed: ${response.status} ${text}`);
478
+ }
479
+ }
480
+ chunkArray(array, size) {
481
+ const chunks = [];
482
+ for (let i = 0; i < array.length; i += size) {
483
+ chunks.push(array.slice(i, i + size));
484
+ }
485
+ return chunks;
486
+ }
487
+ };
488
+
489
+ // src/transports/telegram.ts
490
+ var LEVEL_EMOJI = {
491
+ off: "",
492
+ error: "\u{1F534}",
493
+ warn: "\u{1F7E1}",
494
+ info: "\u{1F7E2}",
495
+ http: "\u{1F535}",
496
+ verbose: "\u{1F7E3}",
497
+ debug: "\u26AA",
498
+ silly: "\u26AB"
499
+ };
500
+ var TelegramTransport = class extends BaseHttpTransport {
501
+ config;
502
+ apiUrl;
503
+ constructor(config) {
504
+ super({
505
+ batchSize: config.batchSize ?? 20,
506
+ flushInterval: config.flushInterval ?? 1e3,
507
+ maxRetries: config.maxRetries,
508
+ retryDelay: config.retryDelay
509
+ });
510
+ this.config = config;
511
+ this.apiUrl = `https://api.telegram.org/bot${config.botToken}`;
512
+ }
513
+ async sendBatch(messages) {
514
+ const text = this.formatBatchMessage(messages);
515
+ await this.sendMessage(text, messages);
516
+ }
517
+ formatBatchMessage(messages) {
518
+ const parseMode = this.config.parseMode ?? "Markdown";
519
+ return messages.map((msg) => {
520
+ if (parseMode === "HTML") {
521
+ return this.formatHtml(msg);
522
+ }
523
+ return this.formatMarkdown(msg, parseMode === "MarkdownV2");
524
+ }).join("\n\n---\n\n");
525
+ }
526
+ formatMarkdown(msg, v2) {
527
+ const emoji = LEVEL_EMOJI[msg.level];
528
+ const escape = v2 ? this.escapeMarkdownV2.bind(this) : (s) => s;
529
+ let text = `${emoji} *${msg.level.toUpperCase()}* \\[${escape(msg.context || "APP")}\\]
530
+ `;
531
+ text += escape(msg.message);
532
+ if (msg.meta && Object.keys(msg.meta).length > 0) {
533
+ const metaStr = JSON.stringify(msg.meta, null, 2);
534
+ text += "\n```json\n" + metaStr + "\n```";
535
+ }
536
+ return text;
537
+ }
538
+ formatHtml(msg) {
539
+ const emoji = LEVEL_EMOJI[msg.level];
540
+ let text = `${emoji} <b>${msg.level.toUpperCase()}</b> [${this.escapeHtml(msg.context || "APP")}]
541
+ `;
542
+ text += this.escapeHtml(msg.message);
543
+ if (msg.meta && Object.keys(msg.meta).length > 0) {
544
+ const metaStr = JSON.stringify(msg.meta, null, 2);
545
+ text += "\n<pre>" + this.escapeHtml(metaStr) + "</pre>";
546
+ }
547
+ return text;
548
+ }
549
+ shouldMute(messages) {
550
+ if (this.config.disableNotification !== void 0) {
551
+ return this.config.disableNotification;
552
+ }
553
+ return !messages.some((m) => m.level === "error");
554
+ }
555
+ async sendMessage(text, messages) {
556
+ const body = {
557
+ chat_id: this.config.chatId,
558
+ text,
559
+ parse_mode: this.config.parseMode ?? "Markdown",
560
+ disable_notification: this.shouldMute(messages)
561
+ };
562
+ if (this.config.threadId) {
563
+ body.message_thread_id = this.config.threadId;
564
+ }
565
+ if (this.config.replyToMessageId) {
566
+ body.reply_to_message_id = this.config.replyToMessageId;
567
+ }
568
+ const response = await fetch(`${this.apiUrl}/sendMessage`, {
569
+ method: "POST",
570
+ headers: { "Content-Type": "application/json" },
571
+ body: JSON.stringify(body)
572
+ });
573
+ if (!response.ok) {
574
+ const result = await response.json();
575
+ throw new Error(`Telegram API failed: ${response.status} ${JSON.stringify(result)}`);
576
+ }
577
+ }
578
+ escapeMarkdownV2(text) {
579
+ return text.replace(/[_*[\]()~`>#+\-=|{}.!]/g, "\\$&");
580
+ }
581
+ escapeHtml(text) {
582
+ const entities = {
583
+ "&": "&amp;",
584
+ "<": "&lt;",
585
+ ">": "&gt;",
586
+ '"': "&quot;",
587
+ "'": "&#39;"
588
+ };
589
+ return text.replace(/[&<>"']/g, (c) => entities[c] || c);
590
+ }
591
+ };
592
+ var CloudWatchTransport = class extends BaseHttpTransport {
593
+ config;
594
+ client;
595
+ sequenceToken;
596
+ initialized = false;
597
+ initPromise = null;
598
+ constructor(config) {
599
+ super({
600
+ batchSize: config.batchSize ?? 100,
601
+ flushInterval: config.flushInterval ?? 1e3,
602
+ maxRetries: config.maxRetries,
603
+ retryDelay: config.retryDelay
604
+ });
605
+ this.config = config;
606
+ this.client = new clientCloudwatchLogs.CloudWatchLogsClient({
607
+ region: config.region,
608
+ credentials: {
609
+ accessKeyId: config.accessKeyId,
610
+ secretAccessKey: config.secretAccessKey
611
+ }
612
+ });
613
+ }
614
+ async sendBatch(messages) {
615
+ await this.ensureInitialized();
616
+ const logEvents = messages.map((msg) => ({
617
+ timestamp: msg.timestamp.getTime(),
618
+ message: JSON.stringify({
619
+ level: msg.level,
620
+ message: msg.message,
621
+ context: msg.context,
622
+ ...msg.meta
623
+ })
624
+ }));
625
+ logEvents.sort((a, b) => (a.timestamp ?? 0) - (b.timestamp ?? 0));
626
+ const command = new clientCloudwatchLogs.PutLogEventsCommand({
627
+ logGroupName: this.config.logGroupName,
628
+ logStreamName: this.config.logStreamName,
629
+ logEvents,
630
+ sequenceToken: this.sequenceToken
631
+ });
632
+ try {
633
+ const response = await this.client.send(command);
634
+ this.sequenceToken = response.nextSequenceToken;
635
+ } catch (error) {
636
+ if (this.isInvalidSequenceTokenError(error)) {
637
+ await this.fetchSequenceToken();
638
+ const retryCommand = new clientCloudwatchLogs.PutLogEventsCommand({
639
+ logGroupName: this.config.logGroupName,
640
+ logStreamName: this.config.logStreamName,
641
+ logEvents,
642
+ sequenceToken: this.sequenceToken
643
+ });
644
+ const response = await this.client.send(retryCommand);
645
+ this.sequenceToken = response.nextSequenceToken;
646
+ } else {
647
+ throw error;
648
+ }
649
+ }
650
+ }
651
+ async ensureInitialized() {
652
+ if (this.initialized) return;
653
+ if (!this.initPromise) {
654
+ this.initPromise = this.initialize();
655
+ }
656
+ await this.initPromise;
657
+ }
658
+ async initialize() {
659
+ if (this.config.createLogGroup) {
660
+ await this.createLogGroupIfNotExists();
661
+ }
662
+ if (this.config.createLogStream !== false) {
663
+ await this.createLogStreamIfNotExists();
664
+ }
665
+ await this.fetchSequenceToken();
666
+ this.initialized = true;
667
+ }
668
+ async createLogGroupIfNotExists() {
669
+ try {
670
+ await this.client.send(
671
+ new clientCloudwatchLogs.CreateLogGroupCommand({
672
+ logGroupName: this.config.logGroupName
673
+ })
674
+ );
675
+ } catch (error) {
676
+ if (!this.isResourceAlreadyExistsError(error)) {
677
+ throw error;
678
+ }
679
+ }
680
+ }
681
+ async createLogStreamIfNotExists() {
682
+ try {
683
+ await this.client.send(
684
+ new clientCloudwatchLogs.CreateLogStreamCommand({
685
+ logGroupName: this.config.logGroupName,
686
+ logStreamName: this.config.logStreamName
687
+ })
688
+ );
689
+ } catch (error) {
690
+ if (!this.isResourceAlreadyExistsError(error)) {
691
+ throw error;
692
+ }
693
+ }
694
+ }
695
+ async fetchSequenceToken() {
696
+ const response = await this.client.send(
697
+ new clientCloudwatchLogs.DescribeLogStreamsCommand({
698
+ logGroupName: this.config.logGroupName,
699
+ logStreamNamePrefix: this.config.logStreamName,
700
+ limit: 1
701
+ })
702
+ );
703
+ const stream = response.logStreams?.find((s) => s.logStreamName === this.config.logStreamName);
704
+ this.sequenceToken = stream?.uploadSequenceToken;
705
+ }
706
+ isResourceAlreadyExistsError(error) {
707
+ return typeof error === "object" && error !== null && "name" in error && error.name === "ResourceAlreadyExistsException";
708
+ }
709
+ isInvalidSequenceTokenError(error) {
710
+ return typeof error === "object" && error !== null && "name" in error && error.name === "InvalidSequenceTokenException";
711
+ }
712
+ };
713
+
242
714
  // src/transports.ts
715
+ function toArray(value) {
716
+ if (!value) return [];
717
+ return Array.isArray(value) ? value : [value];
718
+ }
243
719
  function createTransports(config, store) {
244
720
  const result = [
245
721
  new winston.transports.Console({
246
- format: createFormat(config.console.format, store)
722
+ format: winston.format.combine(
723
+ createFilterFormat(config.console.level, config.console.rules, store),
724
+ createFormat(config.console.format, store)
725
+ )
247
726
  })
248
727
  ];
249
728
  if (config.file) {
250
729
  result.push(
251
730
  new DailyRotateFile__default.default({
252
- format: createFormat(config.file.format, store),
731
+ format: winston.format.combine(
732
+ createFilterFormat(config.file.level, config.file.rules, store),
733
+ createFormat(config.file.format, store)
734
+ ),
253
735
  dirname: config.file.dirname,
254
736
  filename: config.file.filename,
255
737
  datePattern: config.file.datePattern ?? "YYYY-MM-DD",
@@ -259,6 +741,30 @@ function createTransports(config, store) {
259
741
  })
260
742
  );
261
743
  }
744
+ for (const discordConfig of toArray(config.discord)) {
745
+ const discord = new DiscordTransport(discordConfig);
746
+ discord.format = winston.format.combine(
747
+ createFilterFormat(discordConfig.level, discordConfig.rules, store),
748
+ winston.format.timestamp()
749
+ );
750
+ result.push(discord);
751
+ }
752
+ for (const telegramConfig of toArray(config.telegram)) {
753
+ const telegram = new TelegramTransport(telegramConfig);
754
+ telegram.format = winston.format.combine(
755
+ createFilterFormat(telegramConfig.level, telegramConfig.rules, store),
756
+ winston.format.timestamp()
757
+ );
758
+ result.push(telegram);
759
+ }
760
+ for (const cloudwatchConfig of toArray(config.cloudwatch)) {
761
+ const cloudwatch = new CloudWatchTransport(cloudwatchConfig);
762
+ cloudwatch.format = winston.format.combine(
763
+ createFilterFormat(cloudwatchConfig.level, cloudwatchConfig.rules, store),
764
+ winston.format.timestamp()
765
+ );
766
+ result.push(cloudwatch);
767
+ }
262
768
  return result;
263
769
  }
264
770
  function createExceptionHandlers(config, store) {
@@ -283,25 +789,6 @@ function createExceptionHandlers(config, store) {
283
789
  return result;
284
790
  }
285
791
 
286
- // src/types.ts
287
- var LOG_LEVELS = {
288
- error: 0,
289
- warn: 1,
290
- info: 2,
291
- http: 3,
292
- verbose: 4,
293
- debug: 5,
294
- silly: 6
295
- };
296
- function isValidLogLevel(level) {
297
- return level in LOG_LEVELS;
298
- }
299
- function assertLogLevel(level) {
300
- if (!isValidLogLevel(level)) {
301
- throw new Error(`Invalid log level: "${level}". Valid levels: ${Object.keys(LOG_LEVELS).join(", ")}`);
302
- }
303
- }
304
-
305
792
  // src/state.ts
306
793
  function parseLevelConfig(level) {
307
794
  if (typeof level === "string") {
@@ -356,6 +843,81 @@ function matchesContext(storeContext, loggerContext, match) {
356
843
  const combined = { ...storeContext, context: loggerContext };
357
844
  return Object.entries(match).every(([key, value]) => combined[key] === value);
358
845
  }
846
+ var LogLevelSchema = zod.z.enum(["off", "error", "warn", "info", "http", "verbose", "debug", "silly"]);
847
+ var LogFormatSchema = zod.z.enum(["json", "plain", "logfmt", "simple"]);
848
+ var LevelRuleSchema = zod.z.object({
849
+ match: zod.z.record(zod.z.string(), zod.z.unknown()),
850
+ level: LogLevelSchema
851
+ });
852
+ var ConsoleConfigSchema = zod.z.object({
853
+ format: LogFormatSchema,
854
+ level: LogLevelSchema.optional(),
855
+ rules: zod.z.array(LevelRuleSchema).optional()
856
+ });
857
+ var FileConfigSchema = zod.z.object({
858
+ format: LogFormatSchema,
859
+ level: LogLevelSchema.optional(),
860
+ rules: zod.z.array(LevelRuleSchema).optional(),
861
+ dirname: zod.z.string().min(1, "dirname is required"),
862
+ filename: zod.z.string().min(1, "filename is required"),
863
+ datePattern: zod.z.string().optional(),
864
+ zippedArchive: zod.z.boolean().optional(),
865
+ maxSize: zod.z.string().optional(),
866
+ maxFiles: zod.z.string().optional()
867
+ });
868
+ var HttpTransportBaseConfigSchema = zod.z.object({
869
+ level: LogLevelSchema.optional(),
870
+ rules: zod.z.array(LevelRuleSchema).optional(),
871
+ batchSize: zod.z.number().int().positive().optional(),
872
+ flushInterval: zod.z.number().int().positive().optional(),
873
+ maxRetries: zod.z.number().int().nonnegative().optional(),
874
+ retryDelay: zod.z.number().int().positive().optional()
875
+ });
876
+ var DiscordConfigSchema = HttpTransportBaseConfigSchema.extend({
877
+ webhookUrl: zod.z.url("webhookUrl must be a valid URL"),
878
+ username: zod.z.string().optional(),
879
+ avatarUrl: zod.z.url().optional(),
880
+ embedColors: zod.z.record(zod.z.string(), zod.z.number().int()).optional(),
881
+ includeTimestamp: zod.z.boolean().optional(),
882
+ includeMeta: zod.z.boolean().optional(),
883
+ maxEmbedFields: zod.z.number().int().min(1).max(25).optional()
884
+ });
885
+ var TelegramConfigSchema = HttpTransportBaseConfigSchema.extend({
886
+ botToken: zod.z.string().min(1, "botToken is required"),
887
+ chatId: zod.z.union([zod.z.string(), zod.z.number()]),
888
+ parseMode: zod.z.enum(["Markdown", "MarkdownV2", "HTML"]).optional(),
889
+ disableNotification: zod.z.boolean().optional(),
890
+ threadId: zod.z.number().int().optional(),
891
+ replyToMessageId: zod.z.number().int().optional()
892
+ });
893
+ var CloudWatchConfigSchema = HttpTransportBaseConfigSchema.extend({
894
+ logGroupName: zod.z.string().min(1, "logGroupName is required"),
895
+ logStreamName: zod.z.string().min(1, "logStreamName is required"),
896
+ region: zod.z.string().min(1, "region is required"),
897
+ accessKeyId: zod.z.string().min(1, "accessKeyId is required"),
898
+ secretAccessKey: zod.z.string().min(1, "secretAccessKey is required"),
899
+ createLogGroup: zod.z.boolean().optional(),
900
+ createLogStream: zod.z.boolean().optional()
901
+ });
902
+ var LevelConfigObjectSchema = zod.z.object({
903
+ default: LogLevelSchema,
904
+ rules: zod.z.array(LevelRuleSchema).optional()
905
+ });
906
+ var LevelConfigSchema = zod.z.union([LogLevelSchema, LevelConfigObjectSchema]);
907
+ var LoggerConfigSchema = zod.z.object({
908
+ level: LevelConfigSchema,
909
+ console: ConsoleConfigSchema,
910
+ file: FileConfigSchema.optional(),
911
+ discord: zod.z.union([DiscordConfigSchema, zod.z.array(DiscordConfigSchema)]).optional(),
912
+ telegram: zod.z.union([TelegramConfigSchema, zod.z.array(TelegramConfigSchema)]).optional(),
913
+ cloudwatch: zod.z.union([CloudWatchConfigSchema, zod.z.array(CloudWatchConfigSchema)]).optional()
914
+ });
915
+ function validateConfig(config) {
916
+ return LoggerConfigSchema.parse(config);
917
+ }
918
+ function safeValidateConfig(config) {
919
+ return LoggerConfigSchema.safeParse(config);
920
+ }
359
921
 
360
922
  // src/logger.ts
361
923
  var Logger = class _Logger {
@@ -364,7 +926,8 @@ var Logger = class _Logger {
364
926
  this.context = context;
365
927
  }
366
928
  static create(config, store) {
367
- const state = createState(config, store);
929
+ const validatedConfig = validateConfig(config);
930
+ const state = createState(validatedConfig, store);
368
931
  return new _Logger(state, "APP");
369
932
  }
370
933
  for(context) {
@@ -544,9 +1107,26 @@ function getOrGenerateRequestId(headers, options = {}) {
544
1107
  return extractRequestId(headers) ?? generateRequestId(options);
545
1108
  }
546
1109
 
1110
+ exports.BaseHttpTransport = BaseHttpTransport;
1111
+ exports.CloudWatchConfigSchema = CloudWatchConfigSchema;
1112
+ exports.CloudWatchTransport = CloudWatchTransport;
1113
+ exports.ConsoleConfigSchema = ConsoleConfigSchema;
1114
+ exports.DiscordConfigSchema = DiscordConfigSchema;
1115
+ exports.DiscordTransport = DiscordTransport;
1116
+ exports.FileConfigSchema = FileConfigSchema;
1117
+ exports.HttpTransportBaseConfigSchema = HttpTransportBaseConfigSchema;
547
1118
  exports.LOG_LEVELS = LOG_LEVELS;
1119
+ exports.LevelConfigObjectSchema = LevelConfigObjectSchema;
1120
+ exports.LevelConfigSchema = LevelConfigSchema;
1121
+ exports.LevelRuleSchema = LevelRuleSchema;
1122
+ exports.LogFormatSchema = LogFormatSchema;
1123
+ exports.LogLevelSchema = LogLevelSchema;
548
1124
  exports.Logger = Logger;
1125
+ exports.LoggerConfigSchema = LoggerConfigSchema;
549
1126
  exports.LoggerStore = LoggerStore;
1127
+ exports.MessageBuffer = MessageBuffer;
1128
+ exports.TelegramConfigSchema = TelegramConfigSchema;
1129
+ exports.TelegramTransport = TelegramTransport;
550
1130
  exports.assertLogLevel = assertLogLevel;
551
1131
  exports.createMasker = createMasker;
552
1132
  exports.createSingletonLogger = createSingletonLogger;
@@ -558,7 +1138,10 @@ exports.generateRequestId = generateRequestId;
558
1138
  exports.getOrGenerateRequestId = getOrGenerateRequestId;
559
1139
  exports.isValidLogLevel = isValidLogLevel;
560
1140
  exports.maskSecrets = maskSecrets;
1141
+ exports.matchesContext = matchesContext;
561
1142
  exports.measureAsync = measureAsync;
562
1143
  exports.measureSync = measureSync;
1144
+ exports.safeValidateConfig = safeValidateConfig;
1145
+ exports.validateConfig = validateConfig;
563
1146
  //# sourceMappingURL=index.js.map
564
1147
  //# sourceMappingURL=index.js.map