@oxyhq/services 5.13.1 → 5.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +71 -0
  2. package/lib/commonjs/core/HttpClient.js +238 -0
  3. package/lib/commonjs/core/HttpClient.js.map +1 -0
  4. package/lib/commonjs/core/OxyServices.js +538 -332
  5. package/lib/commonjs/core/OxyServices.js.map +1 -1
  6. package/lib/commonjs/core/RequestManager.js +199 -0
  7. package/lib/commonjs/core/RequestManager.js.map +1 -0
  8. package/lib/commonjs/core/index.js +38 -1
  9. package/lib/commonjs/core/index.js.map +1 -1
  10. package/lib/commonjs/index.js +36 -0
  11. package/lib/commonjs/index.js.map +1 -1
  12. package/lib/commonjs/ui/components/Avatar.js +94 -27
  13. package/lib/commonjs/ui/components/Avatar.js.map +1 -1
  14. package/lib/commonjs/ui/components/FollowButton.js +1 -0
  15. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  16. package/lib/commonjs/ui/components/internal/TextField.js +13 -8
  17. package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
  18. package/lib/commonjs/ui/context/OxyContext.js +183 -224
  19. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  20. package/lib/commonjs/ui/hooks/useSessionSocket.js +80 -22
  21. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  22. package/lib/commonjs/ui/index.js +4 -1
  23. package/lib/commonjs/ui/index.js.map +1 -1
  24. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +32 -2
  25. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  26. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +101 -59
  27. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  28. package/lib/commonjs/ui/screens/FileManagementScreen.js +3 -2
  29. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  30. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +75 -117
  31. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  32. package/lib/commonjs/ui/screens/SignInScreen.js +0 -11
  33. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  34. package/lib/commonjs/ui/screens/SignUpScreen.js +14 -16
  35. package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
  36. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +50 -18
  37. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  38. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +10 -10
  39. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  40. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js +16 -26
  41. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  42. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js +104 -212
  43. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  44. package/lib/commonjs/ui/stores/accountStore.js +237 -0
  45. package/lib/commonjs/ui/stores/accountStore.js.map +1 -0
  46. package/lib/commonjs/ui/stores/authStore.js +2 -1
  47. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  48. package/lib/commonjs/ui/styles/authStyles.js +14 -7
  49. package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
  50. package/lib/commonjs/utils/asyncUtils.js +9 -22
  51. package/lib/commonjs/utils/asyncUtils.js.map +1 -1
  52. package/lib/commonjs/utils/cache.js +259 -0
  53. package/lib/commonjs/utils/cache.js.map +1 -0
  54. package/lib/commonjs/utils/index.js +99 -0
  55. package/lib/commonjs/utils/index.js.map +1 -1
  56. package/lib/commonjs/utils/languageUtils.js +159 -0
  57. package/lib/commonjs/utils/languageUtils.js.map +1 -0
  58. package/lib/commonjs/utils/requestUtils.js +217 -0
  59. package/lib/commonjs/utils/requestUtils.js.map +1 -0
  60. package/lib/commonjs/utils/sessionUtils.js +191 -0
  61. package/lib/commonjs/utils/sessionUtils.js.map +1 -0
  62. package/lib/module/core/HttpClient.js +232 -0
  63. package/lib/module/core/HttpClient.js.map +1 -0
  64. package/lib/module/core/OxyServices.js +536 -326
  65. package/lib/module/core/OxyServices.js.map +1 -1
  66. package/lib/module/core/RequestManager.js +194 -0
  67. package/lib/module/core/RequestManager.js.map +1 -0
  68. package/lib/module/core/index.js +2 -0
  69. package/lib/module/core/index.js.map +1 -1
  70. package/lib/module/index.js +2 -0
  71. package/lib/module/index.js.map +1 -1
  72. package/lib/module/ui/components/Avatar.js +94 -27
  73. package/lib/module/ui/components/Avatar.js.map +1 -1
  74. package/lib/module/ui/components/FollowButton.js +1 -0
  75. package/lib/module/ui/components/FollowButton.js.map +1 -1
  76. package/lib/module/ui/components/internal/TextField.js +13 -8
  77. package/lib/module/ui/components/internal/TextField.js.map +1 -1
  78. package/lib/module/ui/context/OxyContext.js +182 -223
  79. package/lib/module/ui/context/OxyContext.js.map +1 -1
  80. package/lib/module/ui/hooks/useSessionSocket.js +80 -22
  81. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  82. package/lib/module/ui/index.js +4 -2
  83. package/lib/module/ui/index.js.map +1 -1
  84. package/lib/module/ui/screens/AccountSettingsScreen.js +33 -2
  85. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  86. package/lib/module/ui/screens/AccountSwitcherScreen.js +102 -60
  87. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  88. package/lib/module/ui/screens/FileManagementScreen.js +3 -2
  89. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  90. package/lib/module/ui/screens/LanguageSelectorScreen.js +73 -117
  91. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  92. package/lib/module/ui/screens/SignInScreen.js +0 -11
  93. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  94. package/lib/module/ui/screens/SignUpScreen.js +14 -16
  95. package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
  96. package/lib/module/ui/screens/WelcomeNewUserScreen.js +50 -18
  97. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  98. package/lib/module/ui/screens/internal/SignInPasswordStep.js +10 -10
  99. package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  100. package/lib/module/ui/screens/steps/SignInPasswordStep.js +16 -26
  101. package/lib/module/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  102. package/lib/module/ui/screens/steps/SignInUsernameStep.js +105 -214
  103. package/lib/module/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  104. package/lib/module/ui/stores/accountStore.js +229 -0
  105. package/lib/module/ui/stores/accountStore.js.map +1 -0
  106. package/lib/module/ui/stores/authStore.js +2 -1
  107. package/lib/module/ui/stores/authStore.js.map +1 -1
  108. package/lib/module/ui/styles/authStyles.js +14 -7
  109. package/lib/module/ui/styles/authStyles.js.map +1 -1
  110. package/lib/module/utils/asyncUtils.js +10 -22
  111. package/lib/module/utils/asyncUtils.js.map +1 -1
  112. package/lib/module/utils/cache.js +250 -0
  113. package/lib/module/utils/cache.js.map +1 -0
  114. package/lib/module/utils/index.js +7 -0
  115. package/lib/module/utils/index.js.map +1 -1
  116. package/lib/module/utils/languageUtils.js +151 -0
  117. package/lib/module/utils/languageUtils.js.map +1 -0
  118. package/lib/module/utils/requestUtils.js +210 -0
  119. package/lib/module/utils/requestUtils.js.map +1 -0
  120. package/lib/module/utils/sessionUtils.js +180 -0
  121. package/lib/module/utils/sessionUtils.js.map +1 -0
  122. package/lib/typescript/core/HttpClient.d.ts +64 -0
  123. package/lib/typescript/core/HttpClient.d.ts.map +1 -0
  124. package/lib/typescript/core/OxyServices.d.ts +88 -71
  125. package/lib/typescript/core/OxyServices.d.ts.map +1 -1
  126. package/lib/typescript/core/RequestManager.d.ts +67 -0
  127. package/lib/typescript/core/RequestManager.d.ts.map +1 -0
  128. package/lib/typescript/core/index.d.ts +2 -0
  129. package/lib/typescript/core/index.d.ts.map +1 -1
  130. package/lib/typescript/index.d.ts +2 -0
  131. package/lib/typescript/index.d.ts.map +1 -1
  132. package/lib/typescript/models/interfaces.d.ts +15 -0
  133. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  134. package/lib/typescript/models/session.d.ts +1 -0
  135. package/lib/typescript/models/session.d.ts.map +1 -1
  136. package/lib/typescript/ui/components/Avatar.d.ts +6 -7
  137. package/lib/typescript/ui/components/Avatar.d.ts.map +1 -1
  138. package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
  139. package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
  140. package/lib/typescript/ui/context/OxyContext.d.ts +4 -0
  141. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  142. package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
  143. package/lib/typescript/ui/index.d.ts +2 -2
  144. package/lib/typescript/ui/index.d.ts.map +1 -1
  145. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  146. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  147. package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts +3 -3
  148. package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  149. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  150. package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
  151. package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  152. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
  153. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts.map +1 -1
  154. package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts.map +1 -1
  155. package/lib/typescript/ui/stores/accountStore.d.ts +34 -0
  156. package/lib/typescript/ui/stores/accountStore.d.ts.map +1 -0
  157. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  158. package/lib/typescript/ui/styles/authStyles.d.ts +18 -2
  159. package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -1
  160. package/lib/typescript/utils/asyncUtils.d.ts +2 -0
  161. package/lib/typescript/utils/asyncUtils.d.ts.map +1 -1
  162. package/lib/typescript/utils/cache.d.ts +128 -0
  163. package/lib/typescript/utils/cache.d.ts.map +1 -0
  164. package/lib/typescript/utils/index.d.ts +4 -0
  165. package/lib/typescript/utils/index.d.ts.map +1 -1
  166. package/lib/typescript/utils/languageUtils.d.ts +38 -0
  167. package/lib/typescript/utils/languageUtils.d.ts.map +1 -0
  168. package/lib/typescript/utils/requestUtils.d.ts +122 -0
  169. package/lib/typescript/utils/requestUtils.d.ts.map +1 -0
  170. package/lib/typescript/utils/sessionUtils.d.ts +55 -0
  171. package/lib/typescript/utils/sessionUtils.d.ts.map +1 -0
  172. package/package.json +1 -1
  173. package/src/core/HttpClient.ts +277 -0
  174. package/src/core/OxyServices.ts +466 -351
  175. package/src/core/RequestManager.ts +240 -0
  176. package/src/core/index.ts +10 -0
  177. package/src/index.ts +10 -0
  178. package/src/models/interfaces.ts +19 -0
  179. package/src/models/session.ts +1 -1
  180. package/src/ui/components/Avatar.tsx +151 -35
  181. package/src/ui/components/FollowButton.tsx +1 -0
  182. package/src/ui/components/internal/TextField.tsx +7 -6
  183. package/src/ui/context/OxyContext.tsx +213 -217
  184. package/src/ui/hooks/useSessionSocket.ts +72 -18
  185. package/src/ui/index.ts +4 -1
  186. package/src/ui/screens/AccountSettingsScreen.tsx +34 -2
  187. package/src/ui/screens/AccountSwitcherScreen.tsx +102 -68
  188. package/src/ui/screens/FileManagementScreen.tsx +1 -1
  189. package/src/ui/screens/LanguageSelectorScreen.tsx +86 -143
  190. package/src/ui/screens/SignInScreen.tsx +0 -7
  191. package/src/ui/screens/SignUpScreen.tsx +14 -15
  192. package/src/ui/screens/WelcomeNewUserScreen.tsx +52 -15
  193. package/src/ui/screens/internal/SignInPasswordStep.tsx +4 -6
  194. package/src/ui/screens/steps/SignInPasswordStep.tsx +4 -8
  195. package/src/ui/screens/steps/SignInUsernameStep.tsx +110 -256
  196. package/src/ui/stores/accountStore.ts +285 -0
  197. package/src/ui/stores/authStore.ts +2 -1
  198. package/src/ui/styles/authStyles.ts +14 -7
  199. package/src/utils/asyncUtils.ts +10 -24
  200. package/src/utils/cache.ts +264 -0
  201. package/src/utils/index.ts +19 -0
  202. package/src/utils/languageUtils.ts +174 -0
  203. package/src/utils/requestUtils.ts +234 -0
  204. package/src/utils/sessionUtils.ts +206 -0
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SimpleLogger = exports.RequestQueue = exports.RequestDeduplicator = void 0;
7
+ /**
8
+ * Request utilities for HTTP clients
9
+ *
10
+ * Provides reusable components for request deduplication, queuing, and logging
11
+ */
12
+
13
+ /**
14
+ * Request deduplication - prevents duplicate concurrent requests
15
+ *
16
+ * When multiple requests with the same key are made simultaneously,
17
+ * only one request is executed and all callers receive the same result.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const deduplicator = new RequestDeduplicator();
22
+ *
23
+ * // Multiple calls with same key will share the same promise
24
+ * const promise1 = deduplicator.deduplicate('user-123', () => fetchUser('123'));
25
+ * const promise2 = deduplicator.deduplicate('user-123', () => fetchUser('123'));
26
+ * // promise1 === promise2, only one API call is made
27
+ * ```
28
+ */
29
+ class RequestDeduplicator {
30
+ pendingRequests = new Map();
31
+
32
+ /**
33
+ * Deduplicate a request by key
34
+ * @param key Unique key for the request
35
+ * @param requestFn Function that returns a promise
36
+ * @returns Promise that will be shared if key already exists
37
+ */
38
+ async deduplicate(key, requestFn) {
39
+ const existing = this.pendingRequests.get(key);
40
+ if (existing) {
41
+ return existing;
42
+ }
43
+ const promise = requestFn().finally(() => {
44
+ this.pendingRequests.delete(key);
45
+ });
46
+ this.pendingRequests.set(key, promise);
47
+ return promise;
48
+ }
49
+
50
+ /**
51
+ * Clear all pending requests
52
+ */
53
+ clear() {
54
+ this.pendingRequests.clear();
55
+ }
56
+
57
+ /**
58
+ * Get number of pending requests
59
+ */
60
+ size() {
61
+ return this.pendingRequests.size;
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Request queue with concurrency control
67
+ *
68
+ * Limits the number of concurrent requests and queues excess requests.
69
+ * Useful for rate limiting and preventing request flooding.
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const queue = new RequestQueue(5, 100); // Max 5 concurrent, queue up to 100
74
+ *
75
+ * // All requests will be queued and processed with max 5 concurrent
76
+ * await queue.enqueue(() => fetchUser('1'));
77
+ * await queue.enqueue(() => fetchUser('2'));
78
+ * // ...
79
+ * ```
80
+ */
81
+ exports.RequestDeduplicator = RequestDeduplicator;
82
+ class RequestQueue {
83
+ queue = [];
84
+ running = 0;
85
+ /**
86
+ * Create a new request queue
87
+ * @param maxConcurrent Maximum number of concurrent requests (default: 10)
88
+ * @param maxQueueSize Maximum queue size (default: 100)
89
+ */
90
+ constructor(maxConcurrent = 10, maxQueueSize = 100) {
91
+ this.maxConcurrent = maxConcurrent;
92
+ this.maxQueueSize = maxQueueSize;
93
+ }
94
+
95
+ /**
96
+ * Enqueue a request
97
+ * @param requestFn Function that returns a promise
98
+ * @returns Promise that resolves when request completes
99
+ */
100
+ async enqueue(requestFn) {
101
+ if (this.queue.length >= this.maxQueueSize) {
102
+ throw new Error('Request queue is full');
103
+ }
104
+ return new Promise((resolve, reject) => {
105
+ this.queue.push(async () => {
106
+ try {
107
+ const result = await requestFn();
108
+ resolve(result);
109
+ } catch (error) {
110
+ reject(error);
111
+ }
112
+ });
113
+ this.process();
114
+ });
115
+ }
116
+
117
+ /**
118
+ * Process queued requests
119
+ */
120
+ async process() {
121
+ if (this.running >= this.maxConcurrent || this.queue.length === 0) {
122
+ return;
123
+ }
124
+ this.running++;
125
+ const requestFn = this.queue.shift();
126
+ if (requestFn) {
127
+ try {
128
+ await requestFn();
129
+ } finally {
130
+ this.running--;
131
+ this.process();
132
+ }
133
+ } else {
134
+ this.running--;
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Clear all queued requests
140
+ */
141
+ clear() {
142
+ this.queue = [];
143
+ }
144
+
145
+ /**
146
+ * Get queue size
147
+ */
148
+ size() {
149
+ return this.queue.length;
150
+ }
151
+
152
+ /**
153
+ * Get number of currently running requests
154
+ */
155
+ runningCount() {
156
+ return this.running;
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Simple logger with level support
162
+ *
163
+ * Lightweight logger for HTTP clients and utilities.
164
+ * For more advanced logging, use loggerUtils.ts
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * const logger = new SimpleLogger(true, 'debug');
169
+ * logger.debug('Debug message');
170
+ * logger.info('Info message');
171
+ * logger.error('Error message');
172
+ * ```
173
+ */
174
+ exports.RequestQueue = RequestQueue;
175
+ class SimpleLogger {
176
+ /**
177
+ * Create a new simple logger
178
+ * @param enabled Whether logging is enabled
179
+ * @param level Minimum log level
180
+ * @param prefix Prefix for log messages (default: '')
181
+ */
182
+ constructor(enabled = false, level = 'error', prefix = '') {
183
+ this.enabled = enabled;
184
+ this.level = level;
185
+ this.prefix = prefix;
186
+ }
187
+ shouldLog(level) {
188
+ if (!this.enabled || this.level === 'none') return false;
189
+ const levels = ['none', 'error', 'warn', 'info', 'debug'];
190
+ return levels.indexOf(level) <= levels.indexOf(this.level);
191
+ }
192
+ formatMessage(...args) {
193
+ return this.prefix ? [`[${this.prefix}]`, ...args] : args;
194
+ }
195
+ error(...args) {
196
+ if (this.shouldLog('error')) {
197
+ console.error(...this.formatMessage(...args));
198
+ }
199
+ }
200
+ warn(...args) {
201
+ if (this.shouldLog('warn')) {
202
+ console.warn(...this.formatMessage(...args));
203
+ }
204
+ }
205
+ info(...args) {
206
+ if (this.shouldLog('info')) {
207
+ console.info(...this.formatMessage(...args));
208
+ }
209
+ }
210
+ debug(...args) {
211
+ if (this.shouldLog('debug')) {
212
+ console.log(...this.formatMessage(...args));
213
+ }
214
+ }
215
+ }
216
+ exports.SimpleLogger = SimpleLogger;
217
+ //# sourceMappingURL=requestUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["RequestDeduplicator","pendingRequests","Map","deduplicate","key","requestFn","existing","get","promise","finally","delete","set","clear","size","exports","RequestQueue","queue","running","constructor","maxConcurrent","maxQueueSize","enqueue","length","Error","Promise","resolve","reject","push","result","error","process","shift","runningCount","SimpleLogger","enabled","level","prefix","shouldLog","levels","indexOf","formatMessage","args","console","warn","info","debug","log"],"sourceRoot":"../../../src","sources":["utils/requestUtils.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.deduplicateSessions = deduplicateSessions;
7
+ exports.deduplicateSessionsByUserId = deduplicateSessionsByUserId;
8
+ exports.mergeSessions = mergeSessions;
9
+ exports.normalizeAndSortSessions = normalizeAndSortSessions;
10
+ exports.normalizeSession = normalizeSession;
11
+ exports.sessionsArraysEqual = sessionsArraysEqual;
12
+ exports.sessionsEqual = sessionsEqual;
13
+ exports.sortSessions = sortSessions;
14
+ /**
15
+ * Session management utilities
16
+ *
17
+ * Provides consistent session normalization, deduplication, and sorting
18
+ * to ensure sessions are always displayed in a predictable order.
19
+ */
20
+
21
+ /**
22
+ * Normalize a session to ensure all required fields are present
23
+ */
24
+ function normalizeSession(session) {
25
+ const now = new Date().toISOString();
26
+ return {
27
+ sessionId: session.sessionId,
28
+ deviceId: session.deviceId || '',
29
+ expiresAt: session.expiresAt || now,
30
+ lastActive: session.lastActive || now,
31
+ userId: session.userId || ''
32
+ };
33
+ }
34
+
35
+ /**
36
+ * Compare two sessions for equality
37
+ */
38
+ function sessionsEqual(a, b) {
39
+ return a.sessionId === b.sessionId;
40
+ }
41
+
42
+ /**
43
+ * Sort sessions by lastActive (most recent first), then by sessionId for stability
44
+ */
45
+ function sortSessions(sessions) {
46
+ return [...sessions].sort((a, b) => {
47
+ // Sort by lastActive descending (most recent first)
48
+ const timeA = new Date(a.lastActive).getTime();
49
+ const timeB = new Date(b.lastActive).getTime();
50
+ if (timeA !== timeB) {
51
+ return timeB - timeA; // Descending order
52
+ }
53
+ // If lastActive is the same, sort by sessionId for stability
54
+ return a.sessionId.localeCompare(b.sessionId);
55
+ });
56
+ }
57
+
58
+ /**
59
+ * Deduplicate sessions by sessionId, keeping the most recent version
60
+ */
61
+ function deduplicateSessions(sessions) {
62
+ const sessionMap = new Map();
63
+ for (const session of sessions) {
64
+ const existing = sessionMap.get(session.sessionId);
65
+ if (!existing) {
66
+ sessionMap.set(session.sessionId, session);
67
+ } else {
68
+ // Keep the one with more recent lastActive
69
+ const existingTime = new Date(existing.lastActive).getTime();
70
+ const currentTime = new Date(session.lastActive).getTime();
71
+ if (currentTime > existingTime) {
72
+ sessionMap.set(session.sessionId, session);
73
+ }
74
+ }
75
+ }
76
+ return Array.from(sessionMap.values());
77
+ }
78
+
79
+ /**
80
+ * Deduplicate sessions by userId, keeping only one session per user
81
+ * Priority: 1) Active session (if provided), 2) Most recent session
82
+ * This prevents showing duplicate accounts for the same user
83
+ */
84
+ function deduplicateSessionsByUserId(sessions, activeSessionId) {
85
+ if (!sessions.length) return [];
86
+ const userSessionMap = new Map();
87
+ for (const session of sessions) {
88
+ if (!session.userId) continue; // Skip sessions without userId
89
+
90
+ const existing = userSessionMap.get(session.userId);
91
+ if (!existing) {
92
+ userSessionMap.set(session.userId, session);
93
+ } else {
94
+ // Prioritize active session
95
+ const isCurrentActive = activeSessionId && session.sessionId === activeSessionId;
96
+ const isExistingActive = activeSessionId && existing.sessionId === activeSessionId;
97
+ if (isCurrentActive && !isExistingActive) {
98
+ userSessionMap.set(session.userId, session);
99
+ } else if (!isCurrentActive && isExistingActive) {
100
+ // Keep existing (active) session
101
+ continue;
102
+ } else {
103
+ // Neither is active, keep the one with more recent lastActive
104
+ const existingTime = new Date(existing.lastActive).getTime();
105
+ const currentTime = new Date(session.lastActive).getTime();
106
+ if (currentTime > existingTime) {
107
+ userSessionMap.set(session.userId, session);
108
+ }
109
+ }
110
+ }
111
+ }
112
+ return Array.from(userSessionMap.values());
113
+ }
114
+
115
+ /**
116
+ * Normalize, deduplicate, and sort sessions
117
+ * This ensures consistent session ordering across the application
118
+ *
119
+ * @param sessions - Array of sessions to normalize
120
+ * @param activeSessionId - Optional active session ID to prioritize
121
+ * @param deduplicateByUserId - If true, deduplicate by userId (one account per user). Default: true
122
+ */
123
+ function normalizeAndSortSessions(sessions, activeSessionId, deduplicateByUserId = true) {
124
+ if (!sessions.length) return [];
125
+
126
+ // Normalize all sessions
127
+ const normalized = sessions.map(normalizeSession);
128
+
129
+ // First deduplicate by sessionId (exact duplicates)
130
+ const deduplicatedBySessionId = deduplicateSessions(normalized);
131
+
132
+ // Then deduplicate by userId if requested (one account per user)
133
+ const finalSessions = deduplicateByUserId ? deduplicateSessionsByUserId(deduplicatedBySessionId, activeSessionId) : deduplicatedBySessionId;
134
+
135
+ // Sort consistently
136
+ return sortSessions(finalSessions);
137
+ }
138
+
139
+ /**
140
+ * Merge two session arrays, prioritizing newer data
141
+ * Returns normalized, deduplicated, and sorted sessions
142
+ *
143
+ * @param existing - Existing sessions array
144
+ * @param incoming - New sessions to merge in
145
+ * @param activeSessionId - Optional active session ID to prioritize
146
+ * @param deduplicateByUserId - If true, deduplicate by userId (one account per user). Default: true
147
+ */
148
+ function mergeSessions(existing, incoming, activeSessionId, deduplicateByUserId = true) {
149
+ if (!existing.length && !incoming.length) return [];
150
+ if (!existing.length) return normalizeAndSortSessions(incoming, activeSessionId, deduplicateByUserId);
151
+ if (!incoming.length) return normalizeAndSortSessions(existing, activeSessionId, deduplicateByUserId);
152
+
153
+ // Normalize both arrays
154
+ const normalizedExisting = existing.map(normalizeSession);
155
+ const normalizedIncoming = incoming.map(normalizeSession);
156
+
157
+ // Create a map with existing sessions (by sessionId)
158
+ const sessionMap = new Map();
159
+
160
+ // Add existing sessions first
161
+ for (const session of normalizedExisting) {
162
+ sessionMap.set(session.sessionId, session);
163
+ }
164
+
165
+ // Merge incoming sessions - backend data always replaces existing
166
+ for (const session of normalizedIncoming) {
167
+ sessionMap.set(session.sessionId, session);
168
+ }
169
+
170
+ // Convert to array
171
+ const merged = Array.from(sessionMap.values());
172
+
173
+ // Apply userId deduplication if requested
174
+ const finalSessions = deduplicateByUserId ? deduplicateSessionsByUserId(merged, activeSessionId) : merged;
175
+
176
+ // Sort consistently
177
+ return sortSessions(finalSessions);
178
+ }
179
+
180
+ /**
181
+ * Check if two session arrays are equal (same sessionIds in same order)
182
+ */
183
+ function sessionsArraysEqual(a, b) {
184
+ if (a.length !== b.length) {
185
+ return false;
186
+ }
187
+ const sortedA = sortSessions(a);
188
+ const sortedB = sortSessions(b);
189
+ return sortedA.every((session, index) => sessionsEqual(session, sortedB[index]));
190
+ }
191
+ //# sourceMappingURL=sessionUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["normalizeSession","session","now","Date","toISOString","sessionId","deviceId","expiresAt","lastActive","userId","sessionsEqual","a","b","sortSessions","sessions","sort","timeA","getTime","timeB","localeCompare","deduplicateSessions","sessionMap","Map","existing","get","set","existingTime","currentTime","Array","from","values","deduplicateSessionsByUserId","activeSessionId","length","userSessionMap","isCurrentActive","isExistingActive","normalizeAndSortSessions","deduplicateByUserId","normalized","map","deduplicatedBySessionId","finalSessions","mergeSessions","incoming","normalizedExisting","normalizedIncoming","merged","sessionsArraysEqual","sortedA","sortedB","every","index"],"sourceRoot":"../../../src","sources":["utils/sessionUtils.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * HTTP Client Service
5
+ *
6
+ * Handles all HTTP communication with authentication, interceptors, and error handling.
7
+ * This is the single source of truth for making authenticated HTTP requests.
8
+ */
9
+
10
+ import axios from 'axios';
11
+ import { jwtDecode } from 'jwt-decode';
12
+ import { handleHttpError } from '../utils/errorUtils';
13
+ import { SimpleLogger } from '../utils/requestUtils';
14
+ /**
15
+ * Token store for authentication
16
+ */
17
+ class TokenStore {
18
+ accessToken = null;
19
+ refreshToken = null;
20
+ constructor() {}
21
+ static getInstance() {
22
+ if (!TokenStore.instance) {
23
+ TokenStore.instance = new TokenStore();
24
+ }
25
+ return TokenStore.instance;
26
+ }
27
+ setTokens(accessToken, refreshToken = '') {
28
+ this.accessToken = accessToken;
29
+ this.refreshToken = refreshToken;
30
+ }
31
+ getAccessToken() {
32
+ return this.accessToken;
33
+ }
34
+ getRefreshToken() {
35
+ return this.refreshToken;
36
+ }
37
+ clearTokens() {
38
+ this.accessToken = null;
39
+ this.refreshToken = null;
40
+ }
41
+ hasAccessToken() {
42
+ return !!this.accessToken;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * HTTP Client Service
48
+ *
49
+ * Manages Axios instance with authentication interceptors.
50
+ * All HTTP requests should go through this service to ensure authentication.
51
+ */
52
+ export class HttpClient {
53
+ constructor(config) {
54
+ this.baseURL = config.baseURL;
55
+ this.tokenStore = TokenStore.getInstance();
56
+ this.logger = new SimpleLogger(config.enableLogging || false, config.logLevel || 'error', 'HttpClient');
57
+ const timeout = config.requestTimeout || 5000;
58
+
59
+ // Create Axios instance with optimized configuration
60
+ this.client = axios.create({
61
+ baseURL: config.baseURL,
62
+ timeout,
63
+ headers: {
64
+ 'Accept': 'application/json'
65
+ },
66
+ // Enable HTTP keep-alive for connection reuse (Node.js only)
67
+ ...(typeof process !== 'undefined' && process.env && typeof window === 'undefined' && typeof require !== 'undefined' ? {
68
+ httpAgent: new (require('http').Agent)({
69
+ keepAlive: true,
70
+ keepAliveMsecs: 1000,
71
+ maxSockets: 50
72
+ }),
73
+ httpsAgent: new (require('https').Agent)({
74
+ keepAlive: true,
75
+ keepAliveMsecs: 1000,
76
+ maxSockets: 50
77
+ })
78
+ } : {})
79
+ });
80
+ this.setupInterceptors();
81
+ }
82
+
83
+ /**
84
+ * Setup axios interceptors for authentication and error handling
85
+ */
86
+ setupInterceptors() {
87
+ // Request interceptor: Add authentication header
88
+ this.client.interceptors.request.use(async req => {
89
+ const accessToken = this.tokenStore.getAccessToken();
90
+ if (!accessToken) {
91
+ return req;
92
+ }
93
+ try {
94
+ const decoded = jwtDecode(accessToken);
95
+ const currentTime = Math.floor(Date.now() / 1000);
96
+
97
+ // If token expires in less than 60 seconds, refresh it
98
+ if (decoded.exp && decoded.exp - currentTime < 60) {
99
+ if (decoded.sessionId) {
100
+ try {
101
+ // Create a new axios instance to avoid interceptor recursion
102
+ const refreshClient = axios.create({
103
+ baseURL: this.client.defaults.baseURL,
104
+ timeout: this.client.defaults.timeout
105
+ });
106
+ const res = await refreshClient.get(`/api/session/token/${decoded.sessionId}`);
107
+ this.tokenStore.setTokens(res.data.accessToken);
108
+ req.headers.Authorization = `Bearer ${res.data.accessToken}`;
109
+ this.logger.debug('Token refreshed');
110
+ } catch (refreshError) {
111
+ // If refresh fails, use current token anyway
112
+ req.headers.Authorization = `Bearer ${accessToken}`;
113
+ this.logger.warn('Token refresh failed, using current token');
114
+ }
115
+ } else {
116
+ req.headers.Authorization = `Bearer ${accessToken}`;
117
+ }
118
+ } else {
119
+ req.headers.Authorization = `Bearer ${accessToken}`;
120
+ }
121
+ } catch (error) {
122
+ this.logger.error('Error processing token:', error);
123
+ // Even if there's an error, still try to use the token
124
+ req.headers.Authorization = `Bearer ${accessToken}`;
125
+ }
126
+ return req;
127
+ }, error => {
128
+ this.logger.error('Request interceptor error:', error);
129
+ return Promise.reject(error);
130
+ });
131
+
132
+ // Response interceptor: Handle auth errors
133
+ this.client.interceptors.response.use(response => response, error => {
134
+ if (error.response?.status === 401) {
135
+ this.logger.warn('401 Unauthorized, clearing tokens');
136
+ this.tokenStore.clearTokens();
137
+ }
138
+ return Promise.reject(error);
139
+ });
140
+ }
141
+
142
+ /**
143
+ * Get the underlying Axios instance
144
+ * Use this only when you need direct access to Axios features
145
+ */
146
+ getAxiosInstance() {
147
+ return this.client;
148
+ }
149
+
150
+ /**
151
+ * Make a raw HTTP request (no caching, deduplication, etc.)
152
+ * Use this for requests that need to bypass performance features
153
+ */
154
+ async request(config) {
155
+ try {
156
+ const response = await this.client.request({
157
+ method: config.method,
158
+ url: config.url,
159
+ data: config.data,
160
+ params: config.params,
161
+ timeout: config.timeout,
162
+ signal: config.signal
163
+ });
164
+
165
+ // Unwrap standardized API response format: { data: ... }
166
+ // This handles responses from sendSuccess() and sendPaginated() helpers
167
+ const responseData = response.data;
168
+
169
+ // Handle paginated responses: { data: [...], pagination: {...} }
170
+ // Return the data array directly - the calling method will wrap it appropriately
171
+ if (responseData && typeof responseData === 'object' && 'data' in responseData && 'pagination' in responseData) {
172
+ // For paginated responses, return the data array directly
173
+ // The calling methods like getUserFollowers/getUserFollowing will handle wrapping
174
+ // We return the whole response so methods can access both data and pagination
175
+ return responseData;
176
+ }
177
+
178
+ // Handle regular success responses: { data: ... }
179
+ if (responseData && typeof responseData === 'object' && 'data' in responseData) {
180
+ return responseData.data;
181
+ }
182
+
183
+ // Return as-is for responses that don't use sendSuccess wrapper
184
+ return responseData;
185
+ } catch (error) {
186
+ throw handleHttpError(error);
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Get base URL
192
+ */
193
+ getBaseURL() {
194
+ return this.baseURL;
195
+ }
196
+
197
+ /**
198
+ * Set authentication tokens
199
+ */
200
+ setTokens(accessToken, refreshToken = '') {
201
+ this.tokenStore.setTokens(accessToken, refreshToken);
202
+ }
203
+
204
+ /**
205
+ * Clear authentication tokens
206
+ */
207
+ clearTokens() {
208
+ this.tokenStore.clearTokens();
209
+ }
210
+
211
+ /**
212
+ * Get access token
213
+ */
214
+ getAccessToken() {
215
+ return this.tokenStore.getAccessToken();
216
+ }
217
+
218
+ /**
219
+ * Check if has access token
220
+ */
221
+ hasAccessToken() {
222
+ return this.tokenStore.hasAccessToken();
223
+ }
224
+
225
+ // Test-only utility to reset global tokens between jest tests
226
+ static __resetTokensForTests() {
227
+ try {
228
+ TokenStore.getInstance().clearTokens();
229
+ } catch {}
230
+ }
231
+ }
232
+ //# sourceMappingURL=HttpClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["axios","jwtDecode","handleHttpError","SimpleLogger","TokenStore","accessToken","refreshToken","constructor","getInstance","instance","setTokens","getAccessToken","getRefreshToken","clearTokens","hasAccessToken","HttpClient","config","baseURL","tokenStore","logger","enableLogging","logLevel","timeout","requestTimeout","client","create","headers","process","env","window","require","httpAgent","Agent","keepAlive","keepAliveMsecs","maxSockets","httpsAgent","setupInterceptors","interceptors","request","use","req","decoded","currentTime","Math","floor","Date","now","exp","sessionId","refreshClient","defaults","res","get","data","Authorization","debug","refreshError","warn","error","Promise","reject","response","status","getAxiosInstance","method","url","params","signal","responseData","getBaseURL","__resetTokensForTests"],"sourceRoot":"../../../src","sources":["core/HttpClient.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAOA,KAAK,MAAmF,OAAO;AACtG,SAASC,SAAS,QAAQ,YAAY;AAEtC,SAASC,eAAe,QAAQ,qBAAqB;AACrD,SAASC,YAAY,QAAQ,uBAAuB;AAUpD;AACA;AACA;AACA,MAAMC,UAAU,CAAC;EAEPC,WAAW,GAAkB,IAAI;EACjCC,YAAY,GAAkB,IAAI;EAElCC,WAAWA,CAAA,EAAG,CAAC;EAEvB,OAAOC,WAAWA,CAAA,EAAe;IAC/B,IAAI,CAACJ,UAAU,CAACK,QAAQ,EAAE;MACxBL,UAAU,CAACK,QAAQ,GAAG,IAAIL,UAAU,CAAC,CAAC;IACxC;IACA,OAAOA,UAAU,CAACK,QAAQ;EAC5B;EAEAC,SAASA,CAACL,WAAmB,EAAEC,YAAY,GAAG,EAAE,EAAQ;IACtD,IAAI,CAACD,WAAW,GAAGA,WAAW;IAC9B,IAAI,CAACC,YAAY,GAAGA,YAAY;EAClC;EAEAK,cAAcA,CAAA,EAAkB;IAC9B,OAAO,IAAI,CAACN,WAAW;EACzB;EAEAO,eAAeA,CAAA,EAAkB;IAC/B,OAAO,IAAI,CAACN,YAAY;EAC1B;EAEAO,WAAWA,CAAA,EAAS;IAClB,IAAI,CAACR,WAAW,GAAG,IAAI;IACvB,IAAI,CAACC,YAAY,GAAG,IAAI;EAC1B;EAEAQ,cAAcA,CAAA,EAAY;IACxB,OAAO,CAAC,CAAC,IAAI,CAACT,WAAW;EAC3B;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMU,UAAU,CAAC;EAMtBR,WAAWA,CAACS,MAAiB,EAAE;IAC7B,IAAI,CAACC,OAAO,GAAGD,MAAM,CAACC,OAAO;IAC7B,IAAI,CAACC,UAAU,GAAGd,UAAU,CAACI,WAAW,CAAC,CAAC;IAC1C,IAAI,CAACW,MAAM,GAAG,IAAIhB,YAAY,CAC5Ba,MAAM,CAACI,aAAa,IAAI,KAAK,EAC7BJ,MAAM,CAACK,QAAQ,IAAI,OAAO,EAC1B,YACF,CAAC;IAED,MAAMC,OAAO,GAAGN,MAAM,CAACO,cAAc,IAAI,IAAI;;IAE7C;IACA,IAAI,CAACC,MAAM,GAAGxB,KAAK,CAACyB,MAAM,CAAC;MACzBR,OAAO,EAAED,MAAM,CAACC,OAAO;MACvBK,OAAO;MACPI,OAAO,EAAE;QACP,QAAQ,EAAE;MACZ,CAAC;MACD;MACA,IAAI,OAAOC,OAAO,KAAK,WAAW,IAC9BA,OAAO,CAACC,GAAG,IACX,OAAOC,MAAM,KAAK,WAAW,IAC7B,OAAOC,OAAO,KAAK,WAAW,GAAG;QACnCC,SAAS,EAAE,KAAKD,OAAO,CAAC,MAAM,CAAC,CAACE,KAAK,EAAE;UACrCC,SAAS,EAAE,IAAI;UACfC,cAAc,EAAE,IAAI;UACpBC,UAAU,EAAE;QACd,CAAC,CAAC;QACFC,UAAU,EAAE,KAAKN,OAAO,CAAC,OAAO,CAAC,CAACE,KAAK,EAAE;UACvCC,SAAS,EAAE,IAAI;UACfC,cAAc,EAAE,IAAI;UACpBC,UAAU,EAAE;QACd,CAAC;MACH,CAAC,GAAG,CAAC,CAAC;IACR,CAAC,CAAC;IAEF,IAAI,CAACE,iBAAiB,CAAC,CAAC;EAC1B;;EAEA;AACF;AACA;EACUA,iBAAiBA,CAAA,EAAS;IAChC;IACA,IAAI,CAACb,MAAM,CAACc,YAAY,CAACC,OAAO,CAACC,GAAG,CAClC,MAAOC,GAA+B,IAAK;MACzC,MAAMpC,WAAW,GAAG,IAAI,CAACa,UAAU,CAACP,cAAc,CAAC,CAAC;MACpD,IAAI,CAACN,WAAW,EAAE;QAChB,OAAOoC,GAAG;MACZ;MAEA,IAAI;QACF,MAAMC,OAAO,GAAGzC,SAAS,CAAaI,WAAW,CAAC;QAClD,MAAMsC,WAAW,GAAGC,IAAI,CAACC,KAAK,CAACC,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;;QAEjD;QACA,IAAIL,OAAO,CAACM,GAAG,IAAIN,OAAO,CAACM,GAAG,GAAGL,WAAW,GAAG,EAAE,EAAE;UACjD,IAAID,OAAO,CAACO,SAAS,EAAE;YACrB,IAAI;cACF;cACA,MAAMC,aAAa,GAAGlD,KAAK,CAACyB,MAAM,CAAC;gBACjCR,OAAO,EAAE,IAAI,CAACO,MAAM,CAAC2B,QAAQ,CAAClC,OAAO;gBACrCK,OAAO,EAAE,IAAI,CAACE,MAAM,CAAC2B,QAAQ,CAAC7B;cAChC,CAAC,CAAC;cACF,MAAM8B,GAAG,GAAG,MAAMF,aAAa,CAACG,GAAG,CAAC,sBAAsBX,OAAO,CAACO,SAAS,EAAE,CAAC;cAC9E,IAAI,CAAC/B,UAAU,CAACR,SAAS,CAAC0C,GAAG,CAACE,IAAI,CAACjD,WAAW,CAAC;cAC/CoC,GAAG,CAACf,OAAO,CAAC6B,aAAa,GAAG,UAAUH,GAAG,CAACE,IAAI,CAACjD,WAAW,EAAE;cAC5D,IAAI,CAACc,MAAM,CAACqC,KAAK,CAAC,iBAAiB,CAAC;YACtC,CAAC,CAAC,OAAOC,YAAY,EAAE;cACrB;cACAhB,GAAG,CAACf,OAAO,CAAC6B,aAAa,GAAG,UAAUlD,WAAW,EAAE;cACnD,IAAI,CAACc,MAAM,CAACuC,IAAI,CAAC,2CAA2C,CAAC;YAC/D;UACF,CAAC,MAAM;YACLjB,GAAG,CAACf,OAAO,CAAC6B,aAAa,GAAG,UAAUlD,WAAW,EAAE;UACrD;QACF,CAAC,MAAM;UACLoC,GAAG,CAACf,OAAO,CAAC6B,aAAa,GAAG,UAAUlD,WAAW,EAAE;QACrD;MACF,CAAC,CAAC,OAAOsD,KAAK,EAAE;QACd,IAAI,CAACxC,MAAM,CAACwC,KAAK,CAAC,yBAAyB,EAAEA,KAAK,CAAC;QACnD;QACAlB,GAAG,CAACf,OAAO,CAAC6B,aAAa,GAAG,UAAUlD,WAAW,EAAE;MACrD;MAEA,OAAOoC,GAAG;IACZ,CAAC,EACAkB,KAAK,IAAK;MACT,IAAI,CAACxC,MAAM,CAACwC,KAAK,CAAC,4BAA4B,EAAEA,KAAK,CAAC;MACtD,OAAOC,OAAO,CAACC,MAAM,CAACF,KAAK,CAAC;IAC9B,CACF,CAAC;;IAED;IACA,IAAI,CAACnC,MAAM,CAACc,YAAY,CAACwB,QAAQ,CAACtB,GAAG,CAClCsB,QAAQ,IAAKA,QAAQ,EACrBH,KAAK,IAAK;MACT,IAAIA,KAAK,CAACG,QAAQ,EAAEC,MAAM,KAAK,GAAG,EAAE;QAClC,IAAI,CAAC5C,MAAM,CAACuC,IAAI,CAAC,mCAAmC,CAAC;QACrD,IAAI,CAACxC,UAAU,CAACL,WAAW,CAAC,CAAC;MAC/B;MACA,OAAO+C,OAAO,CAACC,MAAM,CAACF,KAAK,CAAC;IAC9B,CACF,CAAC;EACH;;EAEA;AACF;AACA;AACA;EACEK,gBAAgBA,CAAA,EAAkB;IAChC,OAAO,IAAI,CAACxC,MAAM;EACpB;;EAEA;AACF;AACA;AACA;EACE,MAAMe,OAAOA,CAAUvB,MAOtB,EAAc;IACb,IAAI;MACF,MAAM8C,QAAQ,GAAG,MAAM,IAAI,CAACtC,MAAM,CAACe,OAAO,CAAI;QAC5C0B,MAAM,EAAEjD,MAAM,CAACiD,MAAM;QACrBC,GAAG,EAAElD,MAAM,CAACkD,GAAG;QACfZ,IAAI,EAAEtC,MAAM,CAACsC,IAAI;QACjBa,MAAM,EAAEnD,MAAM,CAACmD,MAAM;QACrB7C,OAAO,EAAEN,MAAM,CAACM,OAAO;QACvB8C,MAAM,EAAEpD,MAAM,CAACoD;MACjB,CAAC,CAAC;;MAEF;MACA;MACA,MAAMC,YAAY,GAAGP,QAAQ,CAACR,IAAW;;MAEzC;MACA;MACA,IAAIe,YAAY,IAAI,OAAOA,YAAY,KAAK,QAAQ,IAAI,MAAM,IAAIA,YAAY,IAAI,YAAY,IAAIA,YAAY,EAAE;QAC9G;QACA;QACA;QACA,OAAOA,YAAY;MACrB;;MAEA;MACA,IAAIA,YAAY,IAAI,OAAOA,YAAY,KAAK,QAAQ,IAAI,MAAM,IAAIA,YAAY,EAAE;QAC9E,OAAOA,YAAY,CAACf,IAAI;MAC1B;;MAEA;MACA,OAAOe,YAAY;IACrB,CAAC,CAAC,OAAOV,KAAK,EAAE;MACd,MAAMzD,eAAe,CAACyD,KAAK,CAAC;IAC9B;EACF;;EAEA;AACF;AACA;EACEW,UAAUA,CAAA,EAAW;IACnB,OAAO,IAAI,CAACrD,OAAO;EACrB;;EAEA;AACF;AACA;EACEP,SAASA,CAACL,WAAmB,EAAEC,YAAY,GAAG,EAAE,EAAQ;IACtD,IAAI,CAACY,UAAU,CAACR,SAAS,CAACL,WAAW,EAAEC,YAAY,CAAC;EACtD;;EAEA;AACF;AACA;EACEO,WAAWA,CAAA,EAAS;IAClB,IAAI,CAACK,UAAU,CAACL,WAAW,CAAC,CAAC;EAC/B;;EAEA;AACF;AACA;EACEF,cAAcA,CAAA,EAAkB;IAC9B,OAAO,IAAI,CAACO,UAAU,CAACP,cAAc,CAAC,CAAC;EACzC;;EAEA;AACF;AACA;EACEG,cAAcA,CAAA,EAAY;IACxB,OAAO,IAAI,CAACI,UAAU,CAACJ,cAAc,CAAC,CAAC;EACzC;;EAEA;EACA,OAAOyD,qBAAqBA,CAAA,EAAS;IACnC,IAAI;MACFnE,UAAU,CAACI,WAAW,CAAC,CAAC,CAACK,WAAW,CAAC,CAAC;IACxC,CAAC,CAAC,MAAM,CAAC;EACX;AACF","ignoreList":[]}