legend-transactional 2.2.3 → 2.3.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.d.mts CHANGED
@@ -72,6 +72,12 @@ declare const availableMicroservices: {
72
72
  * Represents the "legend-storage" microservice.
73
73
  */
74
74
  readonly Storage: "legend-storage";
75
+ /**
76
+ * Represents the "audit-eda" microservice for event-driven architecture auditing.
77
+ * This microservice consumes audit events (audit.received, audit.processed, audit.dead_letter)
78
+ * to track event lifecycle and debugging purposes.
79
+ */
80
+ readonly AuditEda: "audit-eda";
75
81
  };
76
82
  /**
77
83
  * Type of available microservices in the system.
@@ -460,6 +466,89 @@ interface EventPayload {
460
466
  bucketName: string;
461
467
  filePaths: string[];
462
468
  };
469
+ /**
470
+ * Emitted when an event is received by a microservice before processing starts (audit tracking)
471
+ */
472
+ 'audit.received': {
473
+ /**
474
+ * The microservice that received the event
475
+ */
476
+ microservice: string;
477
+ /**
478
+ * The event that was received
479
+ */
480
+ receivedEvent: string;
481
+ /**
482
+ * Timestamp when the event was received (UNIX timestamp in seconds)
483
+ */
484
+ receivedAt: number;
485
+ /**
486
+ * The queue name from which the event was consumed
487
+ */
488
+ queueName: string;
489
+ /**
490
+ * Optional event identifier for tracking
491
+ */
492
+ eventId?: string;
493
+ };
494
+ /**
495
+ * Emitted when an event is successfully processed by a microservice for audit tracking
496
+ */
497
+ 'audit.processed': {
498
+ /**
499
+ * The microservice that processed the event
500
+ */
501
+ microservice: string;
502
+ /**
503
+ * The original event that was processed
504
+ */
505
+ processedEvent: string;
506
+ /**
507
+ * Timestamp when the event was processed (UNIX timestamp in seconds)
508
+ */
509
+ processedAt: number;
510
+ /**
511
+ * The queue name where the event was consumed
512
+ */
513
+ queueName: string;
514
+ /**
515
+ * Optional event identifier for tracking
516
+ */
517
+ eventId?: string;
518
+ };
519
+ /**
520
+ * Emitted when a message is rejected/nacked and sent to dead letter queue
521
+ */
522
+ 'audit.dead_letter': {
523
+ /**
524
+ * The microservice that rejected the event
525
+ */
526
+ microservice: string;
527
+ /**
528
+ * The original event that was rejected
529
+ */
530
+ rejectedEvent: string;
531
+ /**
532
+ * Timestamp when the event was rejected (UNIX timestamp in seconds)
533
+ */
534
+ rejectedAt: number;
535
+ /**
536
+ * The queue name where the event was rejected from
537
+ */
538
+ queueName: string;
539
+ /**
540
+ * Reason for rejection (delay, fibonacci_strategy, etc.)
541
+ */
542
+ rejectionReason: 'delay' | 'fibonacci_strategy';
543
+ /**
544
+ * Optional retry count
545
+ */
546
+ retryCount?: number;
547
+ /**
548
+ * Optional event identifier for tracking
549
+ */
550
+ eventId?: string;
551
+ };
463
552
  }
464
553
  /**
465
554
  * Represents the available events in the system.
@@ -467,6 +556,9 @@ interface EventPayload {
467
556
  declare const microserviceEvent: {
468
557
  readonly 'TEST.IMAGE': "test.image";
469
558
  readonly 'TEST.MINT': "test.mint";
559
+ readonly 'AUDIT.RECEIVED': "audit.received";
560
+ readonly 'AUDIT.PROCESSED': "audit.processed";
561
+ readonly 'AUDIT.DEAD_LETTER': "audit.dead_letter";
470
562
  readonly 'AUTH.DELETED_USER': "auth.deleted_user";
471
563
  readonly 'AUTH.LOGOUT_USER': "auth.logout_user";
472
564
  readonly 'AUTH.NEW_USER': "auth.new_user";
@@ -559,7 +651,7 @@ declare abstract class ConsumeChannel {
559
651
  *
560
652
  * @see NACKING_DELAY_MS
561
653
  */
562
- nackWithDelay: (delay?: number, maxRetries?: number) => {
654
+ nackWithDelay(delay?: number, maxRetries?: number): {
563
655
  count: number;
564
656
  delay: number;
565
657
  };
@@ -576,7 +668,7 @@ declare abstract class ConsumeChannel {
576
668
  * - `occurrence`: The current occurrence count for the Fibonacci sequence.
577
669
  * @see MAX_OCCURRENCE
578
670
  */
579
- nackWithFibonacciStrategy: (maxOccurrence?: number, maxRetries?: number) => {
671
+ nackWithFibonacciStrategy(maxOccurrence?: number, maxRetries?: number): {
580
672
  count: number;
581
673
  delay: number;
582
674
  occurrence: number;
@@ -595,14 +687,48 @@ declare abstract class ConsumeChannel {
595
687
 
596
688
  /**
597
689
  * Represents a **_consume_** channel for handling saga events/commands.
598
- * Extends the abstract ConsumeChannel class.
690
+ * Extends the abstract ConsumeChannel class with automatic audit event emission.
599
691
  *
600
692
  */
601
693
  declare class EventsConsumeChannel extends ConsumeChannel {
694
+ /**
695
+ * The microservice name that is processing the event
696
+ */
697
+ private readonly microservice;
698
+ /**
699
+ * The original event that was received
700
+ */
701
+ private readonly processedEvent;
702
+ /**
703
+ * Creates a new EventsConsumeChannel instance
704
+ *
705
+ * @param channel - The AMQP Channel
706
+ * @param msg - The consumed message
707
+ * @param queueName - The queue name
708
+ * @param microservice - The microservice name processing the event
709
+ * @param processedEvent - The event type being processed
710
+ */
711
+ constructor(channel: Channel, msg: ConsumeMessage, queueName: string, microservice: string, processedEvent: string);
602
712
  /**
603
713
  * Acknowledges the consumed saga event/command.
714
+ * Automatically emits audit.processed event after successful ACK.
604
715
  */
605
716
  ackMessage(): void;
717
+ /**
718
+ * Override nackWithDelay to emit audit.dead_letter event
719
+ */
720
+ nackWithDelay(delay?: number, maxRetries?: number): {
721
+ count: number;
722
+ delay: number;
723
+ };
724
+ /**
725
+ * Override nackWithFibonacciStrategy to emit audit.dead_letter event
726
+ */
727
+ nackWithFibonacciStrategy(maxOccurrence?: number, maxRetries?: number): {
728
+ count: number;
729
+ delay: number;
730
+ occurrence: number;
731
+ };
606
732
  }
607
733
 
608
734
  /**
@@ -623,6 +749,13 @@ type MicroserviceConsumeEvents<T extends MicroserviceEvent> = {
623
749
  * Represents the names of specific message queues in the RabbitMQ context.
624
750
  */
625
751
  declare const queue: {
752
+ /**
753
+ * Audit queue names for separate audit event types
754
+ * @constant
755
+ */
756
+ readonly AuditReceived: "audit_received_commands";
757
+ readonly AuditProcessed: "audit_processed_commands";
758
+ readonly AuditDeadLetter: "audit_dead_letter_commands";
626
759
  /**
627
760
  * Queue used for sending replies in response to saga events.
628
761
  */
@@ -636,6 +769,10 @@ declare const queue: {
636
769
  * Represents the names of exchanges, which act as message routing hubs in the RabbitMQ context.
637
770
  */
638
771
  declare const exchange: {
772
+ /**
773
+ * Audit exchange name for direct routing of audit events
774
+ */
775
+ readonly Audit: "audit_exchange";
639
776
  /**
640
777
  * Exchange dedicated to requeueing messages that require further processing in a saga process
641
778
  */
@@ -693,6 +830,15 @@ declare const authCommands: {
693
830
  */
694
831
  type AuthCommands = (typeof authCommands)[keyof typeof authCommands];
695
832
 
833
+ /**
834
+ * Different commands related to the "audit-eda" microservice.
835
+ */
836
+ declare const auditEdaCommands: {};
837
+ /**
838
+ * Available commands for the "audit-eda" microservice.
839
+ */
840
+ type AuditEdaCommands = (typeof auditEdaCommands)[keyof typeof auditEdaCommands];
841
+
696
842
  /**
697
843
  * Different commands related to the "blockchain" microservice.
698
844
  */
@@ -907,6 +1053,10 @@ interface CommandMap {
907
1053
  * Represents the mapping of "auth" microservice commands.
908
1054
  */
909
1055
  [availableMicroservices.Auth]: AuthCommands;
1056
+ /**
1057
+ * Represents the mapping of "audit-eda" microservice commands.
1058
+ */
1059
+ [availableMicroservices.AuditEda]: AuditEdaCommands;
910
1060
  /**
911
1061
  * Represents the mapping of "blockchain" microservice commands.
912
1062
  */
@@ -1172,6 +1322,24 @@ declare const createConsumers: (consumers: QueueConsumerProps[]) => Promise<void
1172
1322
  */
1173
1323
  declare const createHeaderConsumers: (queueName: string, events: MicroserviceEvent[]) => Promise<void>;
1174
1324
 
1325
+ /**
1326
+ * Creates audit logging infrastructure with direct exchange and separate queues
1327
+ * Uses direct exchange for efficient single-consumer delivery to audit microservice
1328
+ *
1329
+ * This function sets up the RabbitMQ infrastructure needed for audit event tracking:
1330
+ * - Creates a direct exchange for audit events
1331
+ * - Creates 3 separate queues (audit.received, audit.processed, audit.dead_letter)
1332
+ * - Binds each queue to the audit exchange with appropriate routing keys
1333
+ *
1334
+ * The direct exchange strategy ensures that:
1335
+ * - Only the audit microservice consumes audit events
1336
+ * - Routing is efficient (no pattern matching needed)
1337
+ * - Each audit event type has its own queue for isolation
1338
+ *
1339
+ * @internal This is called automatically when connecting to events
1340
+ */
1341
+ declare const createAuditLoggingResources: () => Promise<void>;
1342
+
1175
1343
  declare const sagaTitle: {
1176
1344
  /**
1177
1345
  * Saga used in the flow to purchase resources and deduct coins from the user.
@@ -1757,4 +1925,22 @@ declare const getEventObject: (event: MicroserviceEvent) => {
1757
1925
  [x: string]: MicroserviceEvent;
1758
1926
  };
1759
1927
 
1760
- export { type AuthCommands, type AvailableMicroservices, type BlockchainCommands, type CoinsCommands, type CommandMap, type CommenceSaga, type CommenceSagaEvents, type CommenceSagaHandler, type CompletedRanking, type EventPayload, EventsConsumeChannel, type EventsHandler, type Exchange, type Gender, MAX_NACK_RETRIES, MAX_OCCURRENCE, type MicroserviceCommand, MicroserviceConsumeChannel, type MicroserviceConsumeEvents, type MicroserviceConsumeSagaEvents, type MicroserviceEvent, type MicroserviceHandler, NACKING_DELAY_MS, type Nack, type PaymentEmailType, PaymentEmailTypes, type QueueConsumerProps, type RankingWinners, type RankingsCommands, type RapidMessagingCommands, type Room, type RoomCreatorCommands, type RoomInventoryCommands, type RoomSnapshotCommands, type RoomType, RoomTypes, Saga, SagaCommenceConsumeChannel, type SagaCommencePayload, SagaConsumeChannel, type SagaConsumeSagaEvents, type SagaHandler, type SagaStep, type SagaStepDefaults, type SagaTitle, type SendEmailCommands, type ShowcaseCommands, type SocialCommands, type SocialMediaRoomsCommands, type SocialUser, type Status, type StorageCommands, type TestImageCommands, type TestMintCommands, Transactional, type TransactionalConfig, type UserLocation, authCommands, availableMicroservices, blockchainCommands, closeConsumeChannel, closeRabbitMQConn, closeSendChannel, coinsCommands, commenceSaga, commenceSagaConsumeCallback, commenceSagaListener, connectToEvents, connectToSagaCommandEmitter, consume, createConsumers, createHeaderConsumers, eventCallback, exchange, fibonacci, gender, getConsumeChannel, getEventKey, getEventObject, getQueueConsumer, getQueueName, getRabbitMQConn, getSendChannel, isConnectionHealthy, microserviceEvent, nodeDataDefaults, publishEvent, queue, rankingsCommands, rapidMessagingCommands, roomCreatorCommands, roomInventoryCommands, roomSnapshotCommands, sagaConsumeCallback, sagaStepCallback, sagaTitle, saveQueueForHealthCheck, saveUri, sendEmailCommands, sendToQueue, showcaseCommands, socialCommands, socialMediaRoomsCommands, startGlobalSagaStepListener, status, stopRabbitMQ, storageCommands, testImageCommands, testMintCommands };
1928
+ /**
1929
+ * Extracts the microservice name from a queue name
1930
+ *
1931
+ * Queue names follow the pattern: `{microservice}_match_commands` or `{microservice}_saga_commands`
1932
+ * This utility extracts the microservice part from the queue name.
1933
+ *
1934
+ * @param queueName - The queue name (e.g., 'auth_match_commands', 'coins_saga_commands')
1935
+ * @returns The microservice name (e.g., 'auth', 'coins')
1936
+ *
1937
+ * @example
1938
+ * ```typescript
1939
+ * extractMicroserviceFromQueue('auth_match_commands'); // Returns: 'auth'
1940
+ * extractMicroserviceFromQueue('coins_saga_commands'); // Returns: 'coins'
1941
+ * extractMicroserviceFromQueue('audit-eda_match_commands'); // Returns: 'audit-eda'
1942
+ * ```
1943
+ */
1944
+ declare function extractMicroserviceFromQueue(queueName: string): string;
1945
+
1946
+ export { type AuditEdaCommands, type AuthCommands, type AvailableMicroservices, type BlockchainCommands, type CoinsCommands, type CommandMap, type CommenceSaga, type CommenceSagaEvents, type CommenceSagaHandler, type CompletedRanking, type EventPayload, EventsConsumeChannel, type EventsHandler, type Exchange, type Gender, MAX_NACK_RETRIES, MAX_OCCURRENCE, type MicroserviceCommand, MicroserviceConsumeChannel, type MicroserviceConsumeEvents, type MicroserviceConsumeSagaEvents, type MicroserviceEvent, type MicroserviceHandler, NACKING_DELAY_MS, type Nack, type PaymentEmailType, PaymentEmailTypes, type QueueConsumerProps, type RankingWinners, type RankingsCommands, type RapidMessagingCommands, type Room, type RoomCreatorCommands, type RoomInventoryCommands, type RoomSnapshotCommands, type RoomType, RoomTypes, Saga, SagaCommenceConsumeChannel, type SagaCommencePayload, SagaConsumeChannel, type SagaConsumeSagaEvents, type SagaHandler, type SagaStep, type SagaStepDefaults, type SagaTitle, type SendEmailCommands, type ShowcaseCommands, type SocialCommands, type SocialMediaRoomsCommands, type SocialUser, type Status, type StorageCommands, type TestImageCommands, type TestMintCommands, Transactional, type TransactionalConfig, type UserLocation, auditEdaCommands, authCommands, availableMicroservices, blockchainCommands, closeConsumeChannel, closeRabbitMQConn, closeSendChannel, coinsCommands, commenceSaga, commenceSagaConsumeCallback, commenceSagaListener, connectToEvents, connectToSagaCommandEmitter, consume, createAuditLoggingResources, createConsumers, createHeaderConsumers, eventCallback, exchange, extractMicroserviceFromQueue, fibonacci, gender, getConsumeChannel, getEventKey, getEventObject, getQueueConsumer, getQueueName, getRabbitMQConn, getSendChannel, isConnectionHealthy, microserviceEvent, nodeDataDefaults, publishEvent, queue, rankingsCommands, rapidMessagingCommands, roomCreatorCommands, roomInventoryCommands, roomSnapshotCommands, sagaConsumeCallback, sagaStepCallback, sagaTitle, saveQueueForHealthCheck, saveUri, sendEmailCommands, sendToQueue, showcaseCommands, socialCommands, socialMediaRoomsCommands, startGlobalSagaStepListener, status, stopRabbitMQ, storageCommands, testImageCommands, testMintCommands };
package/dist/index.d.ts CHANGED
@@ -72,6 +72,12 @@ declare const availableMicroservices: {
72
72
  * Represents the "legend-storage" microservice.
73
73
  */
74
74
  readonly Storage: "legend-storage";
75
+ /**
76
+ * Represents the "audit-eda" microservice for event-driven architecture auditing.
77
+ * This microservice consumes audit events (audit.received, audit.processed, audit.dead_letter)
78
+ * to track event lifecycle and debugging purposes.
79
+ */
80
+ readonly AuditEda: "audit-eda";
75
81
  };
76
82
  /**
77
83
  * Type of available microservices in the system.
@@ -460,6 +466,89 @@ interface EventPayload {
460
466
  bucketName: string;
461
467
  filePaths: string[];
462
468
  };
469
+ /**
470
+ * Emitted when an event is received by a microservice before processing starts (audit tracking)
471
+ */
472
+ 'audit.received': {
473
+ /**
474
+ * The microservice that received the event
475
+ */
476
+ microservice: string;
477
+ /**
478
+ * The event that was received
479
+ */
480
+ receivedEvent: string;
481
+ /**
482
+ * Timestamp when the event was received (UNIX timestamp in seconds)
483
+ */
484
+ receivedAt: number;
485
+ /**
486
+ * The queue name from which the event was consumed
487
+ */
488
+ queueName: string;
489
+ /**
490
+ * Optional event identifier for tracking
491
+ */
492
+ eventId?: string;
493
+ };
494
+ /**
495
+ * Emitted when an event is successfully processed by a microservice for audit tracking
496
+ */
497
+ 'audit.processed': {
498
+ /**
499
+ * The microservice that processed the event
500
+ */
501
+ microservice: string;
502
+ /**
503
+ * The original event that was processed
504
+ */
505
+ processedEvent: string;
506
+ /**
507
+ * Timestamp when the event was processed (UNIX timestamp in seconds)
508
+ */
509
+ processedAt: number;
510
+ /**
511
+ * The queue name where the event was consumed
512
+ */
513
+ queueName: string;
514
+ /**
515
+ * Optional event identifier for tracking
516
+ */
517
+ eventId?: string;
518
+ };
519
+ /**
520
+ * Emitted when a message is rejected/nacked and sent to dead letter queue
521
+ */
522
+ 'audit.dead_letter': {
523
+ /**
524
+ * The microservice that rejected the event
525
+ */
526
+ microservice: string;
527
+ /**
528
+ * The original event that was rejected
529
+ */
530
+ rejectedEvent: string;
531
+ /**
532
+ * Timestamp when the event was rejected (UNIX timestamp in seconds)
533
+ */
534
+ rejectedAt: number;
535
+ /**
536
+ * The queue name where the event was rejected from
537
+ */
538
+ queueName: string;
539
+ /**
540
+ * Reason for rejection (delay, fibonacci_strategy, etc.)
541
+ */
542
+ rejectionReason: 'delay' | 'fibonacci_strategy';
543
+ /**
544
+ * Optional retry count
545
+ */
546
+ retryCount?: number;
547
+ /**
548
+ * Optional event identifier for tracking
549
+ */
550
+ eventId?: string;
551
+ };
463
552
  }
464
553
  /**
465
554
  * Represents the available events in the system.
@@ -467,6 +556,9 @@ interface EventPayload {
467
556
  declare const microserviceEvent: {
468
557
  readonly 'TEST.IMAGE': "test.image";
469
558
  readonly 'TEST.MINT': "test.mint";
559
+ readonly 'AUDIT.RECEIVED': "audit.received";
560
+ readonly 'AUDIT.PROCESSED': "audit.processed";
561
+ readonly 'AUDIT.DEAD_LETTER': "audit.dead_letter";
470
562
  readonly 'AUTH.DELETED_USER': "auth.deleted_user";
471
563
  readonly 'AUTH.LOGOUT_USER': "auth.logout_user";
472
564
  readonly 'AUTH.NEW_USER': "auth.new_user";
@@ -559,7 +651,7 @@ declare abstract class ConsumeChannel {
559
651
  *
560
652
  * @see NACKING_DELAY_MS
561
653
  */
562
- nackWithDelay: (delay?: number, maxRetries?: number) => {
654
+ nackWithDelay(delay?: number, maxRetries?: number): {
563
655
  count: number;
564
656
  delay: number;
565
657
  };
@@ -576,7 +668,7 @@ declare abstract class ConsumeChannel {
576
668
  * - `occurrence`: The current occurrence count for the Fibonacci sequence.
577
669
  * @see MAX_OCCURRENCE
578
670
  */
579
- nackWithFibonacciStrategy: (maxOccurrence?: number, maxRetries?: number) => {
671
+ nackWithFibonacciStrategy(maxOccurrence?: number, maxRetries?: number): {
580
672
  count: number;
581
673
  delay: number;
582
674
  occurrence: number;
@@ -595,14 +687,48 @@ declare abstract class ConsumeChannel {
595
687
 
596
688
  /**
597
689
  * Represents a **_consume_** channel for handling saga events/commands.
598
- * Extends the abstract ConsumeChannel class.
690
+ * Extends the abstract ConsumeChannel class with automatic audit event emission.
599
691
  *
600
692
  */
601
693
  declare class EventsConsumeChannel extends ConsumeChannel {
694
+ /**
695
+ * The microservice name that is processing the event
696
+ */
697
+ private readonly microservice;
698
+ /**
699
+ * The original event that was received
700
+ */
701
+ private readonly processedEvent;
702
+ /**
703
+ * Creates a new EventsConsumeChannel instance
704
+ *
705
+ * @param channel - The AMQP Channel
706
+ * @param msg - The consumed message
707
+ * @param queueName - The queue name
708
+ * @param microservice - The microservice name processing the event
709
+ * @param processedEvent - The event type being processed
710
+ */
711
+ constructor(channel: Channel, msg: ConsumeMessage, queueName: string, microservice: string, processedEvent: string);
602
712
  /**
603
713
  * Acknowledges the consumed saga event/command.
714
+ * Automatically emits audit.processed event after successful ACK.
604
715
  */
605
716
  ackMessage(): void;
717
+ /**
718
+ * Override nackWithDelay to emit audit.dead_letter event
719
+ */
720
+ nackWithDelay(delay?: number, maxRetries?: number): {
721
+ count: number;
722
+ delay: number;
723
+ };
724
+ /**
725
+ * Override nackWithFibonacciStrategy to emit audit.dead_letter event
726
+ */
727
+ nackWithFibonacciStrategy(maxOccurrence?: number, maxRetries?: number): {
728
+ count: number;
729
+ delay: number;
730
+ occurrence: number;
731
+ };
606
732
  }
607
733
 
608
734
  /**
@@ -623,6 +749,13 @@ type MicroserviceConsumeEvents<T extends MicroserviceEvent> = {
623
749
  * Represents the names of specific message queues in the RabbitMQ context.
624
750
  */
625
751
  declare const queue: {
752
+ /**
753
+ * Audit queue names for separate audit event types
754
+ * @constant
755
+ */
756
+ readonly AuditReceived: "audit_received_commands";
757
+ readonly AuditProcessed: "audit_processed_commands";
758
+ readonly AuditDeadLetter: "audit_dead_letter_commands";
626
759
  /**
627
760
  * Queue used for sending replies in response to saga events.
628
761
  */
@@ -636,6 +769,10 @@ declare const queue: {
636
769
  * Represents the names of exchanges, which act as message routing hubs in the RabbitMQ context.
637
770
  */
638
771
  declare const exchange: {
772
+ /**
773
+ * Audit exchange name for direct routing of audit events
774
+ */
775
+ readonly Audit: "audit_exchange";
639
776
  /**
640
777
  * Exchange dedicated to requeueing messages that require further processing in a saga process
641
778
  */
@@ -693,6 +830,15 @@ declare const authCommands: {
693
830
  */
694
831
  type AuthCommands = (typeof authCommands)[keyof typeof authCommands];
695
832
 
833
+ /**
834
+ * Different commands related to the "audit-eda" microservice.
835
+ */
836
+ declare const auditEdaCommands: {};
837
+ /**
838
+ * Available commands for the "audit-eda" microservice.
839
+ */
840
+ type AuditEdaCommands = (typeof auditEdaCommands)[keyof typeof auditEdaCommands];
841
+
696
842
  /**
697
843
  * Different commands related to the "blockchain" microservice.
698
844
  */
@@ -907,6 +1053,10 @@ interface CommandMap {
907
1053
  * Represents the mapping of "auth" microservice commands.
908
1054
  */
909
1055
  [availableMicroservices.Auth]: AuthCommands;
1056
+ /**
1057
+ * Represents the mapping of "audit-eda" microservice commands.
1058
+ */
1059
+ [availableMicroservices.AuditEda]: AuditEdaCommands;
910
1060
  /**
911
1061
  * Represents the mapping of "blockchain" microservice commands.
912
1062
  */
@@ -1172,6 +1322,24 @@ declare const createConsumers: (consumers: QueueConsumerProps[]) => Promise<void
1172
1322
  */
1173
1323
  declare const createHeaderConsumers: (queueName: string, events: MicroserviceEvent[]) => Promise<void>;
1174
1324
 
1325
+ /**
1326
+ * Creates audit logging infrastructure with direct exchange and separate queues
1327
+ * Uses direct exchange for efficient single-consumer delivery to audit microservice
1328
+ *
1329
+ * This function sets up the RabbitMQ infrastructure needed for audit event tracking:
1330
+ * - Creates a direct exchange for audit events
1331
+ * - Creates 3 separate queues (audit.received, audit.processed, audit.dead_letter)
1332
+ * - Binds each queue to the audit exchange with appropriate routing keys
1333
+ *
1334
+ * The direct exchange strategy ensures that:
1335
+ * - Only the audit microservice consumes audit events
1336
+ * - Routing is efficient (no pattern matching needed)
1337
+ * - Each audit event type has its own queue for isolation
1338
+ *
1339
+ * @internal This is called automatically when connecting to events
1340
+ */
1341
+ declare const createAuditLoggingResources: () => Promise<void>;
1342
+
1175
1343
  declare const sagaTitle: {
1176
1344
  /**
1177
1345
  * Saga used in the flow to purchase resources and deduct coins from the user.
@@ -1757,4 +1925,22 @@ declare const getEventObject: (event: MicroserviceEvent) => {
1757
1925
  [x: string]: MicroserviceEvent;
1758
1926
  };
1759
1927
 
1760
- export { type AuthCommands, type AvailableMicroservices, type BlockchainCommands, type CoinsCommands, type CommandMap, type CommenceSaga, type CommenceSagaEvents, type CommenceSagaHandler, type CompletedRanking, type EventPayload, EventsConsumeChannel, type EventsHandler, type Exchange, type Gender, MAX_NACK_RETRIES, MAX_OCCURRENCE, type MicroserviceCommand, MicroserviceConsumeChannel, type MicroserviceConsumeEvents, type MicroserviceConsumeSagaEvents, type MicroserviceEvent, type MicroserviceHandler, NACKING_DELAY_MS, type Nack, type PaymentEmailType, PaymentEmailTypes, type QueueConsumerProps, type RankingWinners, type RankingsCommands, type RapidMessagingCommands, type Room, type RoomCreatorCommands, type RoomInventoryCommands, type RoomSnapshotCommands, type RoomType, RoomTypes, Saga, SagaCommenceConsumeChannel, type SagaCommencePayload, SagaConsumeChannel, type SagaConsumeSagaEvents, type SagaHandler, type SagaStep, type SagaStepDefaults, type SagaTitle, type SendEmailCommands, type ShowcaseCommands, type SocialCommands, type SocialMediaRoomsCommands, type SocialUser, type Status, type StorageCommands, type TestImageCommands, type TestMintCommands, Transactional, type TransactionalConfig, type UserLocation, authCommands, availableMicroservices, blockchainCommands, closeConsumeChannel, closeRabbitMQConn, closeSendChannel, coinsCommands, commenceSaga, commenceSagaConsumeCallback, commenceSagaListener, connectToEvents, connectToSagaCommandEmitter, consume, createConsumers, createHeaderConsumers, eventCallback, exchange, fibonacci, gender, getConsumeChannel, getEventKey, getEventObject, getQueueConsumer, getQueueName, getRabbitMQConn, getSendChannel, isConnectionHealthy, microserviceEvent, nodeDataDefaults, publishEvent, queue, rankingsCommands, rapidMessagingCommands, roomCreatorCommands, roomInventoryCommands, roomSnapshotCommands, sagaConsumeCallback, sagaStepCallback, sagaTitle, saveQueueForHealthCheck, saveUri, sendEmailCommands, sendToQueue, showcaseCommands, socialCommands, socialMediaRoomsCommands, startGlobalSagaStepListener, status, stopRabbitMQ, storageCommands, testImageCommands, testMintCommands };
1928
+ /**
1929
+ * Extracts the microservice name from a queue name
1930
+ *
1931
+ * Queue names follow the pattern: `{microservice}_match_commands` or `{microservice}_saga_commands`
1932
+ * This utility extracts the microservice part from the queue name.
1933
+ *
1934
+ * @param queueName - The queue name (e.g., 'auth_match_commands', 'coins_saga_commands')
1935
+ * @returns The microservice name (e.g., 'auth', 'coins')
1936
+ *
1937
+ * @example
1938
+ * ```typescript
1939
+ * extractMicroserviceFromQueue('auth_match_commands'); // Returns: 'auth'
1940
+ * extractMicroserviceFromQueue('coins_saga_commands'); // Returns: 'coins'
1941
+ * extractMicroserviceFromQueue('audit-eda_match_commands'); // Returns: 'audit-eda'
1942
+ * ```
1943
+ */
1944
+ declare function extractMicroserviceFromQueue(queueName: string): string;
1945
+
1946
+ export { type AuditEdaCommands, type AuthCommands, type AvailableMicroservices, type BlockchainCommands, type CoinsCommands, type CommandMap, type CommenceSaga, type CommenceSagaEvents, type CommenceSagaHandler, type CompletedRanking, type EventPayload, EventsConsumeChannel, type EventsHandler, type Exchange, type Gender, MAX_NACK_RETRIES, MAX_OCCURRENCE, type MicroserviceCommand, MicroserviceConsumeChannel, type MicroserviceConsumeEvents, type MicroserviceConsumeSagaEvents, type MicroserviceEvent, type MicroserviceHandler, NACKING_DELAY_MS, type Nack, type PaymentEmailType, PaymentEmailTypes, type QueueConsumerProps, type RankingWinners, type RankingsCommands, type RapidMessagingCommands, type Room, type RoomCreatorCommands, type RoomInventoryCommands, type RoomSnapshotCommands, type RoomType, RoomTypes, Saga, SagaCommenceConsumeChannel, type SagaCommencePayload, SagaConsumeChannel, type SagaConsumeSagaEvents, type SagaHandler, type SagaStep, type SagaStepDefaults, type SagaTitle, type SendEmailCommands, type ShowcaseCommands, type SocialCommands, type SocialMediaRoomsCommands, type SocialUser, type Status, type StorageCommands, type TestImageCommands, type TestMintCommands, Transactional, type TransactionalConfig, type UserLocation, auditEdaCommands, authCommands, availableMicroservices, blockchainCommands, closeConsumeChannel, closeRabbitMQConn, closeSendChannel, coinsCommands, commenceSaga, commenceSagaConsumeCallback, commenceSagaListener, connectToEvents, connectToSagaCommandEmitter, consume, createAuditLoggingResources, createConsumers, createHeaderConsumers, eventCallback, exchange, extractMicroserviceFromQueue, fibonacci, gender, getConsumeChannel, getEventKey, getEventObject, getQueueConsumer, getQueueName, getRabbitMQConn, getSendChannel, isConnectionHealthy, microserviceEvent, nodeDataDefaults, publishEvent, queue, rankingsCommands, rapidMessagingCommands, roomCreatorCommands, roomInventoryCommands, roomSnapshotCommands, sagaConsumeCallback, sagaStepCallback, sagaTitle, saveQueueForHealthCheck, saveUri, sendEmailCommands, sendToQueue, showcaseCommands, socialCommands, socialMediaRoomsCommands, startGlobalSagaStepListener, status, stopRabbitMQ, storageCommands, testImageCommands, testMintCommands };
package/dist/index.js CHANGED
@@ -75,7 +75,13 @@ var availableMicroservices = {
75
75
  /**
76
76
  * Represents the "legend-storage" microservice.
77
77
  */
78
- Storage: "legend-storage"
78
+ Storage: "legend-storage",
79
+ /**
80
+ * Represents the "audit-eda" microservice for event-driven architecture auditing.
81
+ * This microservice consumes audit events (audit.received, audit.processed, audit.dead_letter)
82
+ * to track event lifecycle and debugging purposes.
83
+ */
84
+ AuditEda: "audit-eda"
79
85
  };
80
86
 
81
87
  // src/@types/event/events.ts
@@ -98,6 +104,11 @@ var microserviceEvent = {
98
104
  "TEST.IMAGE": "test.image",
99
105
  "TEST.MINT": "test.mint",
100
106
  ///////////////////////////
107
+ // AUDIT EVENTS - For tracking event lifecycle
108
+ "AUDIT.RECEIVED": "audit.received",
109
+ "AUDIT.PROCESSED": "audit.processed",
110
+ "AUDIT.DEAD_LETTER": "audit.dead_letter",
111
+ ///////////////////////////
101
112
  "AUTH.DELETED_USER": "auth.deleted_user",
102
113
  "AUTH.LOGOUT_USER": "auth.logout_user",
103
114
  "AUTH.NEW_USER": "auth.new_user",
@@ -132,6 +143,13 @@ var microserviceEvent = {
132
143
 
133
144
  // src/@types/rabbit-mq.ts
134
145
  var queue = {
146
+ /**
147
+ * Audit queue names for separate audit event types
148
+ * @constant
149
+ */
150
+ AuditReceived: "audit_received_commands",
151
+ AuditProcessed: "audit_processed_commands",
152
+ AuditDeadLetter: "audit_dead_letter_commands",
135
153
  /**
136
154
  * Queue used for sending replies in response to saga events.
137
155
  */
@@ -142,6 +160,10 @@ var queue = {
142
160
  CommenceSaga: "commence_saga"
143
161
  };
144
162
  var exchange = {
163
+ /**
164
+ * Audit exchange name for direct routing of audit events
165
+ */
166
+ Audit: "audit_exchange",
145
167
  /**
146
168
  * Exchange dedicated to requeueing messages that require further processing in a saga process
147
169
  */
@@ -176,6 +198,9 @@ var authCommands = {
176
198
  CreateUser: "create_user"
177
199
  };
178
200
 
201
+ // src/@types/saga/commands/audit-eda.ts
202
+ var auditEdaCommands = {};
203
+
179
204
  // src/@types/saga/commands/blockchain.ts
180
205
  var blockchainCommands = {
181
206
  /**
@@ -458,6 +483,11 @@ var getEventObject = (event) => {
458
483
  };
459
484
  };
460
485
 
486
+ // src/utils/extractMicroservice.ts
487
+ function extractMicroserviceFromQueue(queueName) {
488
+ return queueName.replace(/_match_commands$/, "").replace(/_saga_commands$/, "");
489
+ }
490
+
461
491
  // src/Consumer/channels/Consume.ts
462
492
  var ConsumeChannel = class {
463
493
  /**
@@ -497,10 +527,10 @@ var ConsumeChannel = class {
497
527
  *
498
528
  * @see NACKING_DELAY_MS
499
529
  */
500
- nackWithDelay = (delay = NACKING_DELAY_MS, maxRetries) => {
530
+ nackWithDelay(delay = NACKING_DELAY_MS, maxRetries) {
501
531
  const { delay: delayNackRetry, count } = this.nack({ delay, maxRetries });
502
532
  return { count, delay: delayNackRetry };
503
- };
533
+ }
504
534
  /**
505
535
  * Negatively acknowledges (NACKs) the message using a Fibonacci backoff strategy.
506
536
  *
@@ -514,9 +544,9 @@ var ConsumeChannel = class {
514
544
  * - `occurrence`: The current occurrence count for the Fibonacci sequence.
515
545
  * @see MAX_OCCURRENCE
516
546
  */
517
- nackWithFibonacciStrategy = (maxOccurrence = MAX_OCCURRENCE, maxRetries) => {
547
+ nackWithFibonacciStrategy(maxOccurrence = MAX_OCCURRENCE, maxRetries) {
518
548
  return this.nack({ maxOccurrence, maxRetries });
519
- };
549
+ }
520
550
  /**
521
551
  * Private helper function to handle the actual NACK logic.
522
552
  *
@@ -526,11 +556,7 @@ var ConsumeChannel = class {
526
556
  * - `delay` and `maxRetries`: For linear backoff with a fixed delay and retry limit.
527
557
  * - `maxOccurrence`: For Fibonacci backoff with a maximum occurrence count.
528
558
  */
529
- nack = ({
530
- maxRetries,
531
- maxOccurrence,
532
- delay
533
- }) => {
559
+ nack({ maxRetries, maxOccurrence, delay }) {
534
560
  const { msg, queueName, channel } = this;
535
561
  channel.nack(msg, false, false);
536
562
  let count = 0;
@@ -587,7 +613,7 @@ var ConsumeChannel = class {
587
613
  });
588
614
  }
589
615
  return { count, delay: nackDelay, occurrence };
590
- };
616
+ }
591
617
  };
592
618
  var Consume_default = ConsumeChannel;
593
619
 
@@ -619,13 +645,109 @@ var commenceSagaConsumeCallback = (msg, channel, e, queueName) => {
619
645
  e.emit(saga.title, { saga, channel: responseChannel });
620
646
  };
621
647
 
648
+ // src/Broker/PublishAuditEvent.ts
649
+ async function publishAuditEvent(channel, eventType, payload) {
650
+ try {
651
+ const routingKey = eventType;
652
+ const messageBuffer = Buffer.from(JSON.stringify(payload));
653
+ channel.publish(exchange.Audit, routingKey, messageBuffer, {
654
+ contentType: "application/json",
655
+ deliveryMode: 2
656
+ // persistent
657
+ });
658
+ } catch (error) {
659
+ console.error(`Failed to publish audit event ${eventType}:`, error);
660
+ }
661
+ }
662
+ async function publishAuditReceived(channel, payload) {
663
+ await publishAuditEvent(channel, "audit.received", payload);
664
+ }
665
+ async function publishAuditProcessed(channel, payload) {
666
+ await publishAuditEvent(channel, "audit.processed", payload);
667
+ }
668
+ async function publishAuditDeadLetter(channel, payload) {
669
+ await publishAuditEvent(channel, "audit.dead_letter", payload);
670
+ }
671
+
622
672
  // src/Consumer/channels/Events.ts
623
673
  var EventsConsumeChannel = class extends Consume_default {
674
+ /**
675
+ * The microservice name that is processing the event
676
+ */
677
+ microservice;
678
+ /**
679
+ * The original event that was received
680
+ */
681
+ processedEvent;
682
+ /**
683
+ * Creates a new EventsConsumeChannel instance
684
+ *
685
+ * @param channel - The AMQP Channel
686
+ * @param msg - The consumed message
687
+ * @param queueName - The queue name
688
+ * @param microservice - The microservice name processing the event
689
+ * @param processedEvent - The event type being processed
690
+ */
691
+ constructor(channel, msg, queueName, microservice, processedEvent) {
692
+ super(channel, msg, queueName);
693
+ this.microservice = microservice;
694
+ this.processedEvent = processedEvent;
695
+ }
624
696
  /**
625
697
  * Acknowledges the consumed saga event/command.
698
+ * Automatically emits audit.processed event after successful ACK.
626
699
  */
627
700
  ackMessage() {
628
701
  this.channel.ack(this.msg, false);
702
+ const timestamp = Math.floor(Date.now() / 1e3);
703
+ publishAuditProcessed(this.channel, {
704
+ microservice: this.microservice,
705
+ processedEvent: this.processedEvent,
706
+ processedAt: timestamp,
707
+ queueName: this.queueName,
708
+ eventId: void 0
709
+ // Optional: can be enhanced later
710
+ }).catch((error) => {
711
+ console.error("Failed to emit audit.processed event:", error);
712
+ });
713
+ }
714
+ /**
715
+ * Override nackWithDelay to emit audit.dead_letter event
716
+ */
717
+ nackWithDelay(delay = NACKING_DELAY_MS, maxRetries) {
718
+ const parentNack = super.nackWithDelay(delay, maxRetries);
719
+ const timestamp = Math.floor(Date.now() / 1e3);
720
+ publishAuditDeadLetter(this.channel, {
721
+ microservice: this.microservice,
722
+ rejectedEvent: this.processedEvent,
723
+ rejectedAt: timestamp,
724
+ queueName: this.queueName,
725
+ rejectionReason: "delay",
726
+ retryCount: parentNack.count,
727
+ eventId: void 0
728
+ }).catch((error) => {
729
+ console.error("Failed to emit audit.dead_letter event:", error);
730
+ });
731
+ return parentNack;
732
+ }
733
+ /**
734
+ * Override nackWithFibonacciStrategy to emit audit.dead_letter event
735
+ */
736
+ nackWithFibonacciStrategy(maxOccurrence = MAX_OCCURRENCE, maxRetries) {
737
+ const parentNack = super.nackWithFibonacciStrategy(maxOccurrence, maxRetries);
738
+ const timestamp = Math.floor(Date.now() / 1e3);
739
+ publishAuditDeadLetter(this.channel, {
740
+ microservice: this.microservice,
741
+ rejectedEvent: this.processedEvent,
742
+ rejectedAt: timestamp,
743
+ queueName: this.queueName,
744
+ rejectionReason: "fibonacci_strategy",
745
+ retryCount: parentNack.count,
746
+ eventId: void 0
747
+ }).catch((error) => {
748
+ console.error("Failed to emit audit.dead_letter event:", error);
749
+ });
750
+ return parentNack;
629
751
  }
630
752
  };
631
753
 
@@ -668,7 +790,20 @@ var eventCallback = (msg, channel, e, queueName) => {
668
790
  { headersReceived: headers, eventsDetected: event }
669
791
  );
670
792
  }
671
- const responseChannel = new EventsConsumeChannel(channel, msg, queueName);
793
+ const microservice = extractMicroserviceFromQueue(queueName);
794
+ const receivedEvent = event[0];
795
+ const timestamp = Math.floor(Date.now() / 1e3);
796
+ publishAuditReceived(channel, {
797
+ microservice,
798
+ receivedEvent,
799
+ receivedAt: timestamp,
800
+ queueName,
801
+ eventId: void 0
802
+ // Optional: can be enhanced later with message ID tracking
803
+ }).catch((error) => {
804
+ console.error("Failed to emit audit.received event:", error);
805
+ });
806
+ const responseChannel = new EventsConsumeChannel(channel, msg, queueName, microservice, receivedEvent);
672
807
  e.emit(event[0], { payload, channel: responseChannel });
673
808
  };
674
809
 
@@ -835,6 +970,25 @@ var createHeaderConsumers = async (queueName, events) => {
835
970
  }
836
971
  }
837
972
  };
973
+
974
+ // src/Consumer/auditInfrastructure.ts
975
+ var createAuditLoggingResources = async () => {
976
+ const channel = await getConsumeChannel();
977
+ await Promise.all([
978
+ // Create direct exchange for audit events
979
+ channel.assertExchange(exchange.Audit, "direct", { durable: true }),
980
+ // Create queues for audit events
981
+ channel.assertQueue(queue.AuditReceived, { durable: true }),
982
+ channel.assertQueue(queue.AuditProcessed, { durable: true }),
983
+ channel.assertQueue(queue.AuditDeadLetter, { durable: true })
984
+ ]);
985
+ await Promise.all([
986
+ // Bind each queue to its specific routing key
987
+ channel.bindQueue(queue.AuditReceived, exchange.Audit, "audit.received"),
988
+ channel.bindQueue(queue.AuditProcessed, exchange.Audit, "audit.processed"),
989
+ channel.bindQueue(queue.AuditDeadLetter, exchange.Audit, "audit.dead_letter")
990
+ ]);
991
+ };
838
992
  var isReady = false;
839
993
  var prepare = async (url2) => {
840
994
  if (isReady) return;
@@ -894,6 +1048,7 @@ var connectToEvents = async (config) => {
894
1048
  const queueName = `${config.microservice}_match_commands`;
895
1049
  const e = mitt__default.default();
896
1050
  await createHeaderConsumers(queueName, config.events);
1051
+ await createAuditLoggingResources();
897
1052
  void consume(e, queueName, eventCallback);
898
1053
  return e;
899
1054
  };
@@ -979,6 +1134,7 @@ exports.Saga = Saga;
979
1134
  exports.SagaCommenceConsumeChannel = SagaCommenceConsumeChannel;
980
1135
  exports.SagaConsumeChannel = SagaConsumeChannel;
981
1136
  exports.Transactional = Transactional;
1137
+ exports.auditEdaCommands = auditEdaCommands;
982
1138
  exports.authCommands = authCommands;
983
1139
  exports.availableMicroservices = availableMicroservices;
984
1140
  exports.blockchainCommands = blockchainCommands;
@@ -992,10 +1148,12 @@ exports.commenceSagaListener = commenceSagaListener;
992
1148
  exports.connectToEvents = connectToEvents;
993
1149
  exports.connectToSagaCommandEmitter = connectToSagaCommandEmitter;
994
1150
  exports.consume = consume;
1151
+ exports.createAuditLoggingResources = createAuditLoggingResources;
995
1152
  exports.createConsumers = createConsumers;
996
1153
  exports.createHeaderConsumers = createHeaderConsumers;
997
1154
  exports.eventCallback = eventCallback;
998
1155
  exports.exchange = exchange;
1156
+ exports.extractMicroserviceFromQueue = extractMicroserviceFromQueue;
999
1157
  exports.fibonacci = fibonacci;
1000
1158
  exports.gender = gender;
1001
1159
  exports.getConsumeChannel = getConsumeChannel;
package/dist/index.mjs CHANGED
@@ -68,7 +68,13 @@ var availableMicroservices = {
68
68
  /**
69
69
  * Represents the "legend-storage" microservice.
70
70
  */
71
- Storage: "legend-storage"
71
+ Storage: "legend-storage",
72
+ /**
73
+ * Represents the "audit-eda" microservice for event-driven architecture auditing.
74
+ * This microservice consumes audit events (audit.received, audit.processed, audit.dead_letter)
75
+ * to track event lifecycle and debugging purposes.
76
+ */
77
+ AuditEda: "audit-eda"
72
78
  };
73
79
 
74
80
  // src/@types/event/events.ts
@@ -91,6 +97,11 @@ var microserviceEvent = {
91
97
  "TEST.IMAGE": "test.image",
92
98
  "TEST.MINT": "test.mint",
93
99
  ///////////////////////////
100
+ // AUDIT EVENTS - For tracking event lifecycle
101
+ "AUDIT.RECEIVED": "audit.received",
102
+ "AUDIT.PROCESSED": "audit.processed",
103
+ "AUDIT.DEAD_LETTER": "audit.dead_letter",
104
+ ///////////////////////////
94
105
  "AUTH.DELETED_USER": "auth.deleted_user",
95
106
  "AUTH.LOGOUT_USER": "auth.logout_user",
96
107
  "AUTH.NEW_USER": "auth.new_user",
@@ -125,6 +136,13 @@ var microserviceEvent = {
125
136
 
126
137
  // src/@types/rabbit-mq.ts
127
138
  var queue = {
139
+ /**
140
+ * Audit queue names for separate audit event types
141
+ * @constant
142
+ */
143
+ AuditReceived: "audit_received_commands",
144
+ AuditProcessed: "audit_processed_commands",
145
+ AuditDeadLetter: "audit_dead_letter_commands",
128
146
  /**
129
147
  * Queue used for sending replies in response to saga events.
130
148
  */
@@ -135,6 +153,10 @@ var queue = {
135
153
  CommenceSaga: "commence_saga"
136
154
  };
137
155
  var exchange = {
156
+ /**
157
+ * Audit exchange name for direct routing of audit events
158
+ */
159
+ Audit: "audit_exchange",
138
160
  /**
139
161
  * Exchange dedicated to requeueing messages that require further processing in a saga process
140
162
  */
@@ -169,6 +191,9 @@ var authCommands = {
169
191
  CreateUser: "create_user"
170
192
  };
171
193
 
194
+ // src/@types/saga/commands/audit-eda.ts
195
+ var auditEdaCommands = {};
196
+
172
197
  // src/@types/saga/commands/blockchain.ts
173
198
  var blockchainCommands = {
174
199
  /**
@@ -451,6 +476,11 @@ var getEventObject = (event) => {
451
476
  };
452
477
  };
453
478
 
479
+ // src/utils/extractMicroservice.ts
480
+ function extractMicroserviceFromQueue(queueName) {
481
+ return queueName.replace(/_match_commands$/, "").replace(/_saga_commands$/, "");
482
+ }
483
+
454
484
  // src/Consumer/channels/Consume.ts
455
485
  var ConsumeChannel = class {
456
486
  /**
@@ -490,10 +520,10 @@ var ConsumeChannel = class {
490
520
  *
491
521
  * @see NACKING_DELAY_MS
492
522
  */
493
- nackWithDelay = (delay = NACKING_DELAY_MS, maxRetries) => {
523
+ nackWithDelay(delay = NACKING_DELAY_MS, maxRetries) {
494
524
  const { delay: delayNackRetry, count } = this.nack({ delay, maxRetries });
495
525
  return { count, delay: delayNackRetry };
496
- };
526
+ }
497
527
  /**
498
528
  * Negatively acknowledges (NACKs) the message using a Fibonacci backoff strategy.
499
529
  *
@@ -507,9 +537,9 @@ var ConsumeChannel = class {
507
537
  * - `occurrence`: The current occurrence count for the Fibonacci sequence.
508
538
  * @see MAX_OCCURRENCE
509
539
  */
510
- nackWithFibonacciStrategy = (maxOccurrence = MAX_OCCURRENCE, maxRetries) => {
540
+ nackWithFibonacciStrategy(maxOccurrence = MAX_OCCURRENCE, maxRetries) {
511
541
  return this.nack({ maxOccurrence, maxRetries });
512
- };
542
+ }
513
543
  /**
514
544
  * Private helper function to handle the actual NACK logic.
515
545
  *
@@ -519,11 +549,7 @@ var ConsumeChannel = class {
519
549
  * - `delay` and `maxRetries`: For linear backoff with a fixed delay and retry limit.
520
550
  * - `maxOccurrence`: For Fibonacci backoff with a maximum occurrence count.
521
551
  */
522
- nack = ({
523
- maxRetries,
524
- maxOccurrence,
525
- delay
526
- }) => {
552
+ nack({ maxRetries, maxOccurrence, delay }) {
527
553
  const { msg, queueName, channel } = this;
528
554
  channel.nack(msg, false, false);
529
555
  let count = 0;
@@ -580,7 +606,7 @@ var ConsumeChannel = class {
580
606
  });
581
607
  }
582
608
  return { count, delay: nackDelay, occurrence };
583
- };
609
+ }
584
610
  };
585
611
  var Consume_default = ConsumeChannel;
586
612
 
@@ -612,13 +638,109 @@ var commenceSagaConsumeCallback = (msg, channel, e, queueName) => {
612
638
  e.emit(saga.title, { saga, channel: responseChannel });
613
639
  };
614
640
 
641
+ // src/Broker/PublishAuditEvent.ts
642
+ async function publishAuditEvent(channel, eventType, payload) {
643
+ try {
644
+ const routingKey = eventType;
645
+ const messageBuffer = Buffer.from(JSON.stringify(payload));
646
+ channel.publish(exchange.Audit, routingKey, messageBuffer, {
647
+ contentType: "application/json",
648
+ deliveryMode: 2
649
+ // persistent
650
+ });
651
+ } catch (error) {
652
+ console.error(`Failed to publish audit event ${eventType}:`, error);
653
+ }
654
+ }
655
+ async function publishAuditReceived(channel, payload) {
656
+ await publishAuditEvent(channel, "audit.received", payload);
657
+ }
658
+ async function publishAuditProcessed(channel, payload) {
659
+ await publishAuditEvent(channel, "audit.processed", payload);
660
+ }
661
+ async function publishAuditDeadLetter(channel, payload) {
662
+ await publishAuditEvent(channel, "audit.dead_letter", payload);
663
+ }
664
+
615
665
  // src/Consumer/channels/Events.ts
616
666
  var EventsConsumeChannel = class extends Consume_default {
667
+ /**
668
+ * The microservice name that is processing the event
669
+ */
670
+ microservice;
671
+ /**
672
+ * The original event that was received
673
+ */
674
+ processedEvent;
675
+ /**
676
+ * Creates a new EventsConsumeChannel instance
677
+ *
678
+ * @param channel - The AMQP Channel
679
+ * @param msg - The consumed message
680
+ * @param queueName - The queue name
681
+ * @param microservice - The microservice name processing the event
682
+ * @param processedEvent - The event type being processed
683
+ */
684
+ constructor(channel, msg, queueName, microservice, processedEvent) {
685
+ super(channel, msg, queueName);
686
+ this.microservice = microservice;
687
+ this.processedEvent = processedEvent;
688
+ }
617
689
  /**
618
690
  * Acknowledges the consumed saga event/command.
691
+ * Automatically emits audit.processed event after successful ACK.
619
692
  */
620
693
  ackMessage() {
621
694
  this.channel.ack(this.msg, false);
695
+ const timestamp = Math.floor(Date.now() / 1e3);
696
+ publishAuditProcessed(this.channel, {
697
+ microservice: this.microservice,
698
+ processedEvent: this.processedEvent,
699
+ processedAt: timestamp,
700
+ queueName: this.queueName,
701
+ eventId: void 0
702
+ // Optional: can be enhanced later
703
+ }).catch((error) => {
704
+ console.error("Failed to emit audit.processed event:", error);
705
+ });
706
+ }
707
+ /**
708
+ * Override nackWithDelay to emit audit.dead_letter event
709
+ */
710
+ nackWithDelay(delay = NACKING_DELAY_MS, maxRetries) {
711
+ const parentNack = super.nackWithDelay(delay, maxRetries);
712
+ const timestamp = Math.floor(Date.now() / 1e3);
713
+ publishAuditDeadLetter(this.channel, {
714
+ microservice: this.microservice,
715
+ rejectedEvent: this.processedEvent,
716
+ rejectedAt: timestamp,
717
+ queueName: this.queueName,
718
+ rejectionReason: "delay",
719
+ retryCount: parentNack.count,
720
+ eventId: void 0
721
+ }).catch((error) => {
722
+ console.error("Failed to emit audit.dead_letter event:", error);
723
+ });
724
+ return parentNack;
725
+ }
726
+ /**
727
+ * Override nackWithFibonacciStrategy to emit audit.dead_letter event
728
+ */
729
+ nackWithFibonacciStrategy(maxOccurrence = MAX_OCCURRENCE, maxRetries) {
730
+ const parentNack = super.nackWithFibonacciStrategy(maxOccurrence, maxRetries);
731
+ const timestamp = Math.floor(Date.now() / 1e3);
732
+ publishAuditDeadLetter(this.channel, {
733
+ microservice: this.microservice,
734
+ rejectedEvent: this.processedEvent,
735
+ rejectedAt: timestamp,
736
+ queueName: this.queueName,
737
+ rejectionReason: "fibonacci_strategy",
738
+ retryCount: parentNack.count,
739
+ eventId: void 0
740
+ }).catch((error) => {
741
+ console.error("Failed to emit audit.dead_letter event:", error);
742
+ });
743
+ return parentNack;
622
744
  }
623
745
  };
624
746
 
@@ -661,7 +783,20 @@ var eventCallback = (msg, channel, e, queueName) => {
661
783
  { headersReceived: headers, eventsDetected: event }
662
784
  );
663
785
  }
664
- const responseChannel = new EventsConsumeChannel(channel, msg, queueName);
786
+ const microservice = extractMicroserviceFromQueue(queueName);
787
+ const receivedEvent = event[0];
788
+ const timestamp = Math.floor(Date.now() / 1e3);
789
+ publishAuditReceived(channel, {
790
+ microservice,
791
+ receivedEvent,
792
+ receivedAt: timestamp,
793
+ queueName,
794
+ eventId: void 0
795
+ // Optional: can be enhanced later with message ID tracking
796
+ }).catch((error) => {
797
+ console.error("Failed to emit audit.received event:", error);
798
+ });
799
+ const responseChannel = new EventsConsumeChannel(channel, msg, queueName, microservice, receivedEvent);
665
800
  e.emit(event[0], { payload, channel: responseChannel });
666
801
  };
667
802
 
@@ -828,6 +963,25 @@ var createHeaderConsumers = async (queueName, events) => {
828
963
  }
829
964
  }
830
965
  };
966
+
967
+ // src/Consumer/auditInfrastructure.ts
968
+ var createAuditLoggingResources = async () => {
969
+ const channel = await getConsumeChannel();
970
+ await Promise.all([
971
+ // Create direct exchange for audit events
972
+ channel.assertExchange(exchange.Audit, "direct", { durable: true }),
973
+ // Create queues for audit events
974
+ channel.assertQueue(queue.AuditReceived, { durable: true }),
975
+ channel.assertQueue(queue.AuditProcessed, { durable: true }),
976
+ channel.assertQueue(queue.AuditDeadLetter, { durable: true })
977
+ ]);
978
+ await Promise.all([
979
+ // Bind each queue to its specific routing key
980
+ channel.bindQueue(queue.AuditReceived, exchange.Audit, "audit.received"),
981
+ channel.bindQueue(queue.AuditProcessed, exchange.Audit, "audit.processed"),
982
+ channel.bindQueue(queue.AuditDeadLetter, exchange.Audit, "audit.dead_letter")
983
+ ]);
984
+ };
831
985
  var isReady = false;
832
986
  var prepare = async (url2) => {
833
987
  if (isReady) return;
@@ -887,6 +1041,7 @@ var connectToEvents = async (config) => {
887
1041
  const queueName = `${config.microservice}_match_commands`;
888
1042
  const e = mitt();
889
1043
  await createHeaderConsumers(queueName, config.events);
1044
+ await createAuditLoggingResources();
890
1045
  void consume(e, queueName, eventCallback);
891
1046
  return e;
892
1047
  };
@@ -961,4 +1116,4 @@ var publishEvent = async (msg, event) => {
961
1116
  });
962
1117
  };
963
1118
 
964
- export { EventsConsumeChannel, MAX_NACK_RETRIES, MAX_OCCURRENCE, MicroserviceConsumeChannel, NACKING_DELAY_MS, PaymentEmailTypes, RoomTypes, Saga, SagaCommenceConsumeChannel, SagaConsumeChannel, Transactional, authCommands, availableMicroservices, blockchainCommands, closeConsumeChannel, closeRabbitMQConn, closeSendChannel, coinsCommands, commenceSaga, commenceSagaConsumeCallback, commenceSagaListener, connectToEvents, connectToSagaCommandEmitter, consume, createConsumers, createHeaderConsumers, eventCallback, exchange, fibonacci, gender, getConsumeChannel, getEventKey, getEventObject, getQueueConsumer, getQueueName, getRabbitMQConn, getSendChannel, isConnectionHealthy, microserviceEvent, nodeDataDefaults, publishEvent, queue, rankingsCommands, rapidMessagingCommands, roomCreatorCommands, roomInventoryCommands, roomSnapshotCommands, sagaConsumeCallback, sagaStepCallback, sagaTitle, saveQueueForHealthCheck, saveUri, sendEmailCommands, sendToQueue, showcaseCommands, socialCommands, socialMediaRoomsCommands, startGlobalSagaStepListener, status, stopRabbitMQ, storageCommands, testImageCommands, testMintCommands };
1119
+ export { EventsConsumeChannel, MAX_NACK_RETRIES, MAX_OCCURRENCE, MicroserviceConsumeChannel, NACKING_DELAY_MS, PaymentEmailTypes, RoomTypes, Saga, SagaCommenceConsumeChannel, SagaConsumeChannel, Transactional, auditEdaCommands, authCommands, availableMicroservices, blockchainCommands, closeConsumeChannel, closeRabbitMQConn, closeSendChannel, coinsCommands, commenceSaga, commenceSagaConsumeCallback, commenceSagaListener, connectToEvents, connectToSagaCommandEmitter, consume, createAuditLoggingResources, createConsumers, createHeaderConsumers, eventCallback, exchange, extractMicroserviceFromQueue, fibonacci, gender, getConsumeChannel, getEventKey, getEventObject, getQueueConsumer, getQueueName, getRabbitMQConn, getSendChannel, isConnectionHealthy, microserviceEvent, nodeDataDefaults, publishEvent, queue, rankingsCommands, rapidMessagingCommands, roomCreatorCommands, roomInventoryCommands, roomSnapshotCommands, sagaConsumeCallback, sagaStepCallback, sagaTitle, saveQueueForHealthCheck, saveUri, sendEmailCommands, sendToQueue, showcaseCommands, socialCommands, socialMediaRoomsCommands, startGlobalSagaStepListener, status, stopRabbitMQ, storageCommands, testImageCommands, testMintCommands };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "legend-transactional",
3
- "version": "2.2.3",
3
+ "version": "2.3.0",
4
4
  "description": "A simple transactional, event-driven communication framework for microservices using RabbitMQ",
5
5
  "author": "Jorge Clavijo <jym272@gmail.com> (https://github.com/jym272)",
6
6
  "license": "MIT",