@winible/winible-typed 2.118.0 → 2.120.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.
@@ -643,4 +643,439 @@ describe('CacheService', () => {
643
643
  expect(result).toEqual({ value: null, text: 'example' });
644
644
  });
645
645
  });
646
+
647
+ describe('Sorted Set Operations (ZSET)', () => {
648
+ describe('zadd', () => {
649
+ it('should add single member with score to sorted set', async () => {
650
+ const result = await cacheService.zadd('leaderboard', [
651
+ { score: 100, member: 'player1' },
652
+ ]);
653
+ expect(result).toBe(1);
654
+
655
+ const count = await cacheService.zcard('leaderboard');
656
+ expect(count).toBe(1);
657
+ });
658
+
659
+ it('should add multiple members with scores to sorted set', async () => {
660
+ const result = await cacheService.zadd('leaderboard', [
661
+ { score: 100, member: 'player1' },
662
+ { score: 200, member: 'player2' },
663
+ { score: 150, member: 'player3' },
664
+ ]);
665
+ expect(result).toBe(3);
666
+
667
+ const count = await cacheService.zcard('leaderboard');
668
+ expect(count).toBe(3);
669
+ });
670
+
671
+ it('should update score when member already exists', async () => {
672
+ await cacheService.zadd('scores', [{ score: 100, member: 'user1' }]);
673
+ const result = await cacheService.zadd('scores', [{ score: 200, member: 'user1' }]);
674
+
675
+ // zadd returns 0 when updating existing member
676
+ expect(result).toBe(0);
677
+
678
+ const score = await cacheService.zscore('scores', 'user1');
679
+ expect(score).toBe(200);
680
+ });
681
+
682
+ it('should handle floating point scores', async () => {
683
+ const result = await cacheService.zadd('ratings', [
684
+ { score: 4.5, member: 'item1' },
685
+ { score: 3.2, member: 'item2' },
686
+ { score: 4.8, member: 'item3' },
687
+ ]);
688
+ expect(result).toBe(3);
689
+
690
+ const score = await cacheService.zscore('ratings', 'item1');
691
+ expect(score).toBe(4.5);
692
+ });
693
+
694
+ it('should handle negative scores', async () => {
695
+ const result = await cacheService.zadd('deltas', [
696
+ { score: -10, member: 'loss1' },
697
+ { score: 5, member: 'gain1' },
698
+ { score: -3, member: 'loss2' },
699
+ ]);
700
+ expect(result).toBe(3);
701
+
702
+ const score = await cacheService.zscore('deltas', 'loss1');
703
+ expect(score).toBe(-10);
704
+ });
705
+
706
+ it('should return 0 when not connected', async () => {
707
+ await cacheService.disconnect();
708
+ const result = await cacheService.zadd('test', [{ score: 100, member: 'item' }]);
709
+ expect(result).toBe(0);
710
+ });
711
+ });
712
+
713
+ describe('zrevrange', () => {
714
+ beforeEach(async () => {
715
+ await cacheService.zadd('leaderboard', [
716
+ { score: 100, member: 'player1' },
717
+ { score: 300, member: 'player2' },
718
+ { score: 200, member: 'player3' },
719
+ { score: 400, member: 'player4' },
720
+ { score: 150, member: 'player5' },
721
+ ]);
722
+ });
723
+
724
+ it('should get members in descending order by score', async () => {
725
+ const members = await cacheService.zrevrange('leaderboard', 0, 2);
726
+ expect(members).toEqual(['player4', 'player2', 'player3']);
727
+ });
728
+
729
+ it('should get all members when range covers entire set', async () => {
730
+ const members = await cacheService.zrevrange('leaderboard', 0, -1);
731
+ expect(members).toEqual(['player4', 'player2', 'player3', 'player5', 'player1']);
732
+ });
733
+
734
+ it('should get members with scores when withScores is true', async () => {
735
+ const result = await cacheService.zrevrange('leaderboard', 0, 2, true) as Array<{ member: string; score: number }>;
736
+ expect(result).toHaveLength(3);
737
+ expect(result[0]).toEqual({ member: 'player4', score: 400 });
738
+ expect(result[1]).toEqual({ member: 'player2', score: 300 });
739
+ expect(result[2]).toEqual({ member: 'player3', score: 200 });
740
+ });
741
+
742
+ it('should handle pagination with cursor ranges', async () => {
743
+ const firstPage = await cacheService.zrevrange('leaderboard', 0, 1);
744
+ expect(firstPage).toEqual(['player4', 'player2']);
745
+
746
+ const secondPage = await cacheService.zrevrange('leaderboard', 2, 3);
747
+ expect(secondPage).toEqual(['player3', 'player5']);
748
+ });
749
+
750
+ it('should return empty array when range is out of bounds', async () => {
751
+ const members = await cacheService.zrevrange('leaderboard', 10, 20);
752
+ expect(members).toEqual([]);
753
+ });
754
+
755
+ it('should return empty array for non-existent key', async () => {
756
+ const members = await cacheService.zrevrange('nonexistent', 0, -1);
757
+ expect(members).toEqual([]);
758
+ });
759
+
760
+ it('should return empty array when not connected', async () => {
761
+ await cacheService.disconnect();
762
+ const members = await cacheService.zrevrange('leaderboard', 0, -1);
763
+ expect(members).toEqual([]);
764
+ });
765
+
766
+ it('should handle single member result', async () => {
767
+ const members = await cacheService.zrevrange('leaderboard', 0, 0);
768
+ expect(members).toEqual(['player4']);
769
+ });
770
+
771
+ it('should handle negative indices', async () => {
772
+ const members = await cacheService.zrevrange('leaderboard', -2, -1);
773
+ expect(members).toEqual(['player5', 'player1']);
774
+ });
775
+ });
776
+
777
+ describe('zcard', () => {
778
+ it('should return 0 for non-existent sorted set', async () => {
779
+ const count = await cacheService.zcard('nonexistent');
780
+ expect(count).toBe(0);
781
+ });
782
+
783
+ it('should return count of members in sorted set', async () => {
784
+ await cacheService.zadd('trending', [
785
+ { score: 10, member: 'item1' },
786
+ { score: 20, member: 'item2' },
787
+ { score: 15, member: 'item3' },
788
+ ]);
789
+
790
+ const count = await cacheService.zcard('trending');
791
+ expect(count).toBe(3);
792
+ });
793
+
794
+ it('should return updated count after adding more members', async () => {
795
+ await cacheService.zadd('posts', [{ score: 5, member: 'post1' }]);
796
+ let count = await cacheService.zcard('posts');
797
+ expect(count).toBe(1);
798
+
799
+ await cacheService.zadd('posts', [
800
+ { score: 10, member: 'post2' },
801
+ { score: 7, member: 'post3' },
802
+ ]);
803
+ count = await cacheService.zcard('posts');
804
+ expect(count).toBe(3);
805
+ });
806
+
807
+ it('should return same count when updating existing member', async () => {
808
+ await cacheService.zadd('votes', [
809
+ { score: 100, member: 'comment1' },
810
+ { score: 50, member: 'comment2' },
811
+ ]);
812
+
813
+ let count = await cacheService.zcard('votes');
814
+ expect(count).toBe(2);
815
+
816
+ // Update score of existing member
817
+ await cacheService.zadd('votes', [{ score: 150, member: 'comment1' }]);
818
+ count = await cacheService.zcard('votes');
819
+ expect(count).toBe(2);
820
+ });
821
+
822
+ it('should return 0 when not connected', async () => {
823
+ await cacheService.disconnect();
824
+ const count = await cacheService.zcard('test');
825
+ expect(count).toBe(0);
826
+ });
827
+
828
+ it('should handle large sorted sets', async () => {
829
+ const members = Array.from({ length: 100 }, (_, i) => ({
830
+ score: i,
831
+ member: `item${i}`,
832
+ }));
833
+ await cacheService.zadd('large-set', members);
834
+
835
+ const count = await cacheService.zcard('large-set');
836
+ expect(count).toBe(100);
837
+ });
838
+ });
839
+
840
+ describe('zscore', () => {
841
+ beforeEach(async () => {
842
+ await cacheService.zadd('rankings', [
843
+ { score: 100, member: 'user1' },
844
+ { score: 200, member: 'user2' },
845
+ { score: 150.5, member: 'user3' },
846
+ ]);
847
+ });
848
+
849
+ it('should return score for existing member', async () => {
850
+ const score = await cacheService.zscore('rankings', 'user1');
851
+ expect(score).toBe(100);
852
+ });
853
+
854
+ it('should return null for non-existent member', async () => {
855
+ const score = await cacheService.zscore('rankings', 'nonexistent');
856
+ expect(score).toBeNull();
857
+ });
858
+
859
+ it('should return null for non-existent key', async () => {
860
+ const score = await cacheService.zscore('nonexistent', 'user1');
861
+ expect(score).toBeNull();
862
+ });
863
+
864
+ it('should handle floating point scores', async () => {
865
+ const score = await cacheService.zscore('rankings', 'user3');
866
+ expect(score).toBe(150.5);
867
+ });
868
+
869
+ it('should return updated score after member update', async () => {
870
+ let score = await cacheService.zscore('rankings', 'user1');
871
+ expect(score).toBe(100);
872
+
873
+ await cacheService.zadd('rankings', [{ score: 300, member: 'user1' }]);
874
+ score = await cacheService.zscore('rankings', 'user1');
875
+ expect(score).toBe(300);
876
+ });
877
+
878
+ it('should handle negative scores', async () => {
879
+ await cacheService.zadd('deltas', [{ score: -42.5, member: 'negative' }]);
880
+ const score = await cacheService.zscore('deltas', 'negative');
881
+ expect(score).toBe(-42.5);
882
+ });
883
+
884
+ it('should return null when not connected', async () => {
885
+ await cacheService.disconnect();
886
+ const score = await cacheService.zscore('rankings', 'user1');
887
+ expect(score).toBeNull();
888
+ });
889
+ });
890
+
891
+ describe('zremrangebyrank', () => {
892
+ beforeEach(async () => {
893
+ await cacheService.zadd('cleanup', [
894
+ { score: 10, member: 'item1' },
895
+ { score: 20, member: 'item2' },
896
+ { score: 30, member: 'item3' },
897
+ { score: 40, member: 'item4' },
898
+ { score: 50, member: 'item5' },
899
+ ]);
900
+ });
901
+
902
+ it('should remove members by rank range (ascending)', async () => {
903
+ const removed = await cacheService.zremrangebyrank('cleanup', 0, 1);
904
+ expect(removed).toBe(2);
905
+
906
+ const remaining = await cacheService.zcard('cleanup');
907
+ expect(remaining).toBe(3);
908
+
909
+ // Verify lowest scores were removed
910
+ const members = await cacheService.zrevrange('cleanup', 0, -1);
911
+ expect(members).toEqual(['item5', 'item4', 'item3']);
912
+ });
913
+
914
+ it('should remove all members when range covers entire set', async () => {
915
+ const removed = await cacheService.zremrangebyrank('cleanup', 0, -1);
916
+ expect(removed).toBe(5);
917
+
918
+ const count = await cacheService.zcard('cleanup');
919
+ expect(count).toBe(0);
920
+ });
921
+
922
+ it('should remove single member', async () => {
923
+ const removed = await cacheService.zremrangebyrank('cleanup', 0, 0);
924
+ expect(removed).toBe(1);
925
+
926
+ const count = await cacheService.zcard('cleanup');
927
+ expect(count).toBe(4);
928
+ });
929
+
930
+ it('should handle negative indices', async () => {
931
+ // Remove last 2 members (highest scores)
932
+ const removed = await cacheService.zremrangebyrank('cleanup', -2, -1);
933
+ expect(removed).toBe(2);
934
+
935
+ const members = await cacheService.zrevrange('cleanup', 0, -1);
936
+ expect(members).toEqual(['item3', 'item2', 'item1']);
937
+ });
938
+
939
+ it('should return 0 for non-existent key', async () => {
940
+ const removed = await cacheService.zremrangebyrank('nonexistent', 0, 10);
941
+ expect(removed).toBe(0);
942
+ });
943
+
944
+ it('should return 0 when range is out of bounds', async () => {
945
+ const removed = await cacheService.zremrangebyrank('cleanup', 10, 20);
946
+ expect(removed).toBe(0);
947
+
948
+ const count = await cacheService.zcard('cleanup');
949
+ expect(count).toBe(5);
950
+ });
951
+
952
+ it('should return 0 when not connected', async () => {
953
+ await cacheService.disconnect();
954
+ const removed = await cacheService.zremrangebyrank('cleanup', 0, 1);
955
+ expect(removed).toBe(0);
956
+ });
957
+
958
+ it('should remove middle range of members', async () => {
959
+ const removed = await cacheService.zremrangebyrank('cleanup', 1, 3);
960
+ expect(removed).toBe(3);
961
+
962
+ const members = await cacheService.zrevrange('cleanup', 0, -1);
963
+ expect(members).toEqual(['item5', 'item1']);
964
+ });
965
+
966
+ it('should handle cleanup of oldest entries to maintain limit', async () => {
967
+ // Add 100 items
968
+ const items = Array.from({ length: 100 }, (_, i) => ({
969
+ score: i,
970
+ member: `fixture${i}`,
971
+ }));
972
+ await cacheService.zadd('trending-fixtures', items);
973
+
974
+ const initialCount = await cacheService.zcard('trending-fixtures');
975
+ expect(initialCount).toBe(100);
976
+
977
+ // Keep only top 50 by removing bottom 50 (ranks 0-49)
978
+ const removed = await cacheService.zremrangebyrank('trending-fixtures', 0, 49);
979
+ expect(removed).toBe(50);
980
+
981
+ const finalCount = await cacheService.zcard('trending-fixtures');
982
+ expect(finalCount).toBe(50);
983
+
984
+ // Verify highest scores remain
985
+ const topMember = await cacheService.zrevrange('trending-fixtures', 0, 0);
986
+ expect(topMember).toEqual(['fixture99']);
987
+ });
988
+ });
989
+
990
+ describe('ZSET integration scenarios', () => {
991
+ it('should support trending fixtures use case', async () => {
992
+ // Add trending fixtures with bet counts
993
+ await cacheService.zadd('trending-fixtures', [
994
+ { score: 15, member: 'fixture-abc' },
995
+ { score: 42, member: 'fixture-def' },
996
+ { score: 28, member: 'fixture-ghi' },
997
+ { score: 9, member: 'fixture-jkl' },
998
+ ]);
999
+
1000
+ // Get top 3 trending fixtures
1001
+ const topFixtures = await cacheService.zrevrange('trending-fixtures', 0, 2);
1002
+ expect(topFixtures).toEqual(['fixture-def', 'fixture-ghi', 'fixture-abc']);
1003
+
1004
+ // Get fixture with score
1005
+ const withScores = await cacheService.zrevrange('trending-fixtures', 0, 0, true) as Array<{ member: string; score: number }>;
1006
+ expect(withScores[0]).toEqual({ member: 'fixture-def', score: 42 });
1007
+
1008
+ // Check total count
1009
+ const total = await cacheService.zcard('trending-fixtures');
1010
+ expect(total).toBe(4);
1011
+ });
1012
+
1013
+ it('should support pagination for infinite scroll', async () => {
1014
+ // Add 50 fixtures
1015
+ const fixtures = Array.from({ length: 50 }, (_, i) => ({
1016
+ score: 50 - i, // Descending scores
1017
+ member: `fixture-${i}`,
1018
+ }));
1019
+ await cacheService.zadd('paginated-fixtures', fixtures);
1020
+
1021
+ // First page (0-19)
1022
+ const page1 = await cacheService.zrevrange('paginated-fixtures', 0, 19);
1023
+ expect(page1).toHaveLength(20);
1024
+ expect(page1[0]).toBe('fixture-0'); // Highest score
1025
+
1026
+ // Second page (20-39)
1027
+ const page2 = await cacheService.zrevrange('paginated-fixtures', 20, 39);
1028
+ expect(page2).toHaveLength(20);
1029
+ expect(page2[0]).toBe('fixture-20');
1030
+
1031
+ // Last page (40-49)
1032
+ const page3 = await cacheService.zrevrange('paginated-fixtures', 40, 49);
1033
+ expect(page3).toHaveLength(10);
1034
+
1035
+ // Beyond last page
1036
+ const page4 = await cacheService.zrevrange('paginated-fixtures', 50, 69);
1037
+ expect(page4).toHaveLength(0);
1038
+ });
1039
+
1040
+ it('should update trending fixture score when bet count changes', async () => {
1041
+ await cacheService.zadd('live-trending', [
1042
+ { score: 10, member: 'fixture-123' },
1043
+ ]);
1044
+
1045
+ let score = await cacheService.zscore('live-trending', 'fixture-123');
1046
+ expect(score).toBe(10);
1047
+
1048
+ // Simulate bet count increase
1049
+ await cacheService.zadd('live-trending', [
1050
+ { score: 25, member: 'fixture-123' },
1051
+ ]);
1052
+
1053
+ score = await cacheService.zscore('live-trending', 'fixture-123');
1054
+ expect(score).toBe(25);
1055
+
1056
+ // Verify count didn't change
1057
+ const count = await cacheService.zcard('live-trending');
1058
+ expect(count).toBe(1);
1059
+ });
1060
+
1061
+ it('should maintain top 100 limit by removing oldest entries', async () => {
1062
+ // Add 120 fixtures
1063
+ const fixtures = Array.from({ length: 120 }, (_, i) => ({
1064
+ score: Math.floor(Math.random() * 1000),
1065
+ member: `fixture-${i}`,
1066
+ }));
1067
+ await cacheService.zadd('limited-trending', fixtures);
1068
+
1069
+ let count = await cacheService.zcard('limited-trending');
1070
+ expect(count).toBe(120);
1071
+
1072
+ // Remove bottom 20 to keep only top 100
1073
+ const removed = await cacheService.zremrangebyrank('limited-trending', 0, 19);
1074
+ expect(removed).toBe(20);
1075
+
1076
+ count = await cacheService.zcard('limited-trending');
1077
+ expect(count).toBe(100);
1078
+ });
1079
+ });
1080
+ });
646
1081
  });
@@ -57,14 +57,32 @@ class CacheService {
57
57
  additionalData?: any;
58
58
  }
59
59
  ): void {
60
- if (this.errorHandler) {
61
- error.name = context.method;
62
- this.errorHandler(error, undefined, context);
63
- } else {
64
- // Fallback to logger if no error handler is set
60
+ try {
61
+ if (this.errorHandler) {
62
+ // Override the name property using Object.defineProperty to avoid read-only restriction
63
+ if (context?.method) {
64
+ Object.defineProperty(error, 'name', {
65
+ value: context.method,
66
+ writable: true,
67
+ enumerable: false,
68
+ configurable: true,
69
+ });
70
+ }
71
+ this.errorHandler(error, undefined, context);
72
+ } else {
73
+ // Fallback to logger if no error handler is set
74
+ logger(message, {
75
+ level: "error",
76
+ method: context?.method || "CacheService",
77
+ action: context?.action || "error",
78
+ error,
79
+ additionalData: context?.additionalData,
80
+ });
81
+ }
82
+ } catch (error) {
65
83
  logger(message, {
66
84
  level: "error",
67
- method: context?.method || "CacheService",
85
+ method: "CacheService.ErrorHandler",
68
86
  action: context?.action || "error",
69
87
  error,
70
88
  additionalData: context?.additionalData,
@@ -615,6 +633,169 @@ class CacheService {
615
633
  }
616
634
  }
617
635
 
636
+ /**
637
+ * Add members with scores to a sorted set
638
+ * @param key - The sorted set key
639
+ * @param members - Array of member-score pairs
640
+ * @returns The number of elements added to the sorted set (not including elements already existing for which the score was updated)
641
+ */
642
+ async zadd(
643
+ key: string,
644
+ members: Array<{ score: number; member: string }>
645
+ ): Promise<number> {
646
+ if (!this.isConnected) return 0;
647
+
648
+ try {
649
+ const args: Array<number | string> = [];
650
+ members.forEach(({ score, member }) => {
651
+ args.push(score, member);
652
+ });
653
+ const result = await this.client!.zadd(key, ...args);
654
+ return result;
655
+ } catch (error) {
656
+ this.handleError(error, null, {
657
+ method: "CacheService.zadd",
658
+ action: "error",
659
+ additionalData: {
660
+ message: "Failed to add members to sorted set",
661
+ key,
662
+ count: members.length,
663
+ },
664
+ });
665
+ return 0;
666
+ }
667
+ }
668
+
669
+ /**
670
+ * Get members from a sorted set by score, highest to lowest (descending order)
671
+ * @param key - The sorted set key
672
+ * @param start - Start index (0-based)
673
+ * @param stop - Stop index (-1 for all remaining)
674
+ * @param withScores - Whether to include scores in the result
675
+ * @returns Array of members, or array of {member, score} objects if withScores is true
676
+ */
677
+ async zrevrange(
678
+ key: string,
679
+ start: number,
680
+ stop: number,
681
+ withScores?: boolean
682
+ ): Promise<string[] | Array<{ member: string; score: number }>> {
683
+ if (!this.isConnected) return [];
684
+
685
+ try {
686
+ if (withScores) {
687
+ const result = await this.client!.zrevrange(
688
+ key,
689
+ start,
690
+ stop,
691
+ "WITHSCORES"
692
+ );
693
+ const pairs: Array<{ member: string; score: number }> = [];
694
+ for (let i = 0; i < result.length; i += 2) {
695
+ pairs.push({
696
+ member: result[i],
697
+ score: parseFloat(result[i + 1]),
698
+ });
699
+ }
700
+ return pairs;
701
+ } else {
702
+ return await this.client!.zrevrange(key, start, stop);
703
+ }
704
+ } catch (error) {
705
+ this.handleError(error, null, {
706
+ method: "CacheService.zrevrange",
707
+ action: "error",
708
+ additionalData: {
709
+ message: "Failed to get members from sorted set",
710
+ key,
711
+ start,
712
+ stop,
713
+ },
714
+ });
715
+ return [];
716
+ }
717
+ }
718
+
719
+ /**
720
+ * Get the number of members in a sorted set
721
+ * @param key - The sorted set key
722
+ * @returns The cardinality (number of members) of the sorted set
723
+ */
724
+ async zcard(key: string): Promise<number> {
725
+ if (!this.isConnected) return 0;
726
+
727
+ try {
728
+ return await this.client!.zcard(key);
729
+ } catch (error) {
730
+ this.handleError(error, null, {
731
+ method: "CacheService.zcard",
732
+ action: "error",
733
+ additionalData: {
734
+ message: "Failed to get cardinality of sorted set",
735
+ key,
736
+ },
737
+ });
738
+ return 0;
739
+ }
740
+ }
741
+
742
+ /**
743
+ * Get the score of a member in a sorted set
744
+ * @param key - The sorted set key
745
+ * @param member - The member to get the score for
746
+ * @returns The score of the member, or null if the member doesn't exist
747
+ */
748
+ async zscore(key: string, member: string): Promise<number | null> {
749
+ if (!this.isConnected) return null;
750
+
751
+ try {
752
+ const score = await this.client!.zscore(key, member);
753
+ return score !== null ? parseFloat(score) : null;
754
+ } catch (error) {
755
+ this.handleError(error, null, {
756
+ method: "CacheService.zscore",
757
+ action: "error",
758
+ additionalData: {
759
+ message: "Failed to get score from sorted set",
760
+ key,
761
+ member,
762
+ },
763
+ });
764
+ return null;
765
+ }
766
+ }
767
+
768
+ /**
769
+ * Remove all members in a sorted set within the given rank range
770
+ * @param key - The sorted set key
771
+ * @param start - Start rank (0-based)
772
+ * @param stop - Stop rank
773
+ * @returns The number of members removed
774
+ */
775
+ async zremrangebyrank(
776
+ key: string,
777
+ start: number,
778
+ stop: number
779
+ ): Promise<number> {
780
+ if (!this.isConnected) return 0;
781
+
782
+ try {
783
+ return await this.client!.zremrangebyrank(key, start, stop);
784
+ } catch (error) {
785
+ this.handleError(error, null, {
786
+ method: "CacheService.zremrangebyrank",
787
+ action: "error",
788
+ additionalData: {
789
+ message: "Failed to remove members from sorted set by rank",
790
+ key,
791
+ start,
792
+ stop,
793
+ },
794
+ });
795
+ return 0;
796
+ }
797
+ }
798
+
618
799
  /**
619
800
  * Disconnect the cache client
620
801
  * Use this for graceful shutdown
package/utils/index.ts CHANGED
@@ -2,3 +2,4 @@ export { default as campaignUtils } from "./campaignUtils";
2
2
  export { default as generalUtils } from "./generalUtils";
3
3
  export { default as logger } from "./logger";
4
4
  export { default as CacheService, cacheService } from "./cacheService/cacheService";
5
+ export { initializeOpenSearchClient } from "./openSearch/openSearchClient";