@formo/analytics-react-native 1.0.1 → 1.1.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.
Files changed (96) hide show
  1. package/lib/commonjs/FormoAnalytics.js +15 -3
  2. package/lib/commonjs/FormoAnalytics.js.map +1 -1
  3. package/lib/commonjs/lib/crash/index.js +23 -7
  4. package/lib/commonjs/lib/crash/index.js.map +1 -1
  5. package/lib/commonjs/lib/event/EventFactory.js +11 -1
  6. package/lib/commonjs/lib/event/EventFactory.js.map +1 -1
  7. package/lib/commonjs/lib/event/EventQueue.js +367 -57
  8. package/lib/commonjs/lib/event/EventQueue.js.map +1 -1
  9. package/lib/commonjs/utils/sanitize.js +260 -0
  10. package/lib/commonjs/utils/sanitize.js.map +1 -0
  11. package/lib/commonjs/utils/trafficSource.js +10 -1
  12. package/lib/commonjs/utils/trafficSource.js.map +1 -1
  13. package/lib/commonjs/version.js +1 -1
  14. package/lib/module/FormoAnalytics.js +15 -3
  15. package/lib/module/FormoAnalytics.js.map +1 -1
  16. package/lib/module/lib/crash/index.js +23 -7
  17. package/lib/module/lib/crash/index.js.map +1 -1
  18. package/lib/module/lib/event/EventFactory.js +11 -1
  19. package/lib/module/lib/event/EventFactory.js.map +1 -1
  20. package/lib/module/lib/event/EventQueue.js +368 -57
  21. package/lib/module/lib/event/EventQueue.js.map +1 -1
  22. package/lib/module/utils/sanitize.js +253 -0
  23. package/lib/module/utils/sanitize.js.map +1 -0
  24. package/lib/module/utils/trafficSource.js +10 -1
  25. package/lib/module/utils/trafficSource.js.map +1 -1
  26. package/lib/module/version.js +1 -1
  27. package/lib/typescript/commonjs/FormoAnalytics.d.ts.map +1 -1
  28. package/lib/typescript/commonjs/lib/crash/index.d.ts.map +1 -1
  29. package/lib/typescript/commonjs/lib/event/EventFactory.d.ts.map +1 -1
  30. package/lib/typescript/commonjs/lib/event/EventQueue.d.ts +55 -0
  31. package/lib/typescript/commonjs/lib/event/EventQueue.d.ts.map +1 -1
  32. package/lib/typescript/commonjs/utils/sanitize.d.ts +31 -0
  33. package/lib/typescript/commonjs/utils/sanitize.d.ts.map +1 -0
  34. package/lib/typescript/commonjs/utils/trafficSource.d.ts +3 -0
  35. package/lib/typescript/commonjs/utils/trafficSource.d.ts.map +1 -1
  36. package/lib/typescript/commonjs/version.d.ts +1 -1
  37. package/lib/typescript/module/FormoAnalytics.d.ts +2 -2
  38. package/lib/typescript/module/FormoAnalytics.d.ts.map +1 -1
  39. package/lib/typescript/module/FormoAnalyticsProvider.d.ts +1 -1
  40. package/lib/typescript/module/FormoAnalyticsProvider.d.ts.map +1 -1
  41. package/lib/typescript/module/constants/index.d.ts +3 -3
  42. package/lib/typescript/module/constants/index.d.ts.map +1 -1
  43. package/lib/typescript/module/index.d.ts +5 -5
  44. package/lib/typescript/module/index.d.ts.map +1 -1
  45. package/lib/typescript/module/lib/crash/index.d.ts.map +1 -1
  46. package/lib/typescript/module/lib/event/EventFactory.d.ts +2 -2
  47. package/lib/typescript/module/lib/event/EventFactory.d.ts.map +1 -1
  48. package/lib/typescript/module/lib/event/EventManager.d.ts +2 -2
  49. package/lib/typescript/module/lib/event/EventManager.d.ts.map +1 -1
  50. package/lib/typescript/module/lib/event/EventQueue.d.ts +57 -2
  51. package/lib/typescript/module/lib/event/EventQueue.d.ts.map +1 -1
  52. package/lib/typescript/module/lib/event/index.d.ts +4 -4
  53. package/lib/typescript/module/lib/event/index.d.ts.map +1 -1
  54. package/lib/typescript/module/lib/event/types.d.ts +1 -1
  55. package/lib/typescript/module/lib/event/types.d.ts.map +1 -1
  56. package/lib/typescript/module/lib/session/index.d.ts +1 -1
  57. package/lib/typescript/module/lib/session/index.d.ts.map +1 -1
  58. package/lib/typescript/module/lib/storage/AsyncStorageAdapter.d.ts +2 -2
  59. package/lib/typescript/module/lib/storage/AsyncStorageAdapter.d.ts.map +1 -1
  60. package/lib/typescript/module/lib/storage/MemoryStorage.d.ts +1 -1
  61. package/lib/typescript/module/lib/storage/MemoryStorage.d.ts.map +1 -1
  62. package/lib/typescript/module/lib/storage/StorageBlueprint.d.ts +1 -1
  63. package/lib/typescript/module/lib/storage/StorageBlueprint.d.ts.map +1 -1
  64. package/lib/typescript/module/lib/storage/StorageManager.d.ts +1 -1
  65. package/lib/typescript/module/lib/storage/StorageManager.d.ts.map +1 -1
  66. package/lib/typescript/module/lib/storage/index.d.ts +4 -4
  67. package/lib/typescript/module/lib/storage/index.d.ts.map +1 -1
  68. package/lib/typescript/module/lib/wagmi/WagmiEventHandler.d.ts +2 -2
  69. package/lib/typescript/module/lib/wagmi/WagmiEventHandler.d.ts.map +1 -1
  70. package/lib/typescript/module/lib/wagmi/index.d.ts +2 -2
  71. package/lib/typescript/module/lib/wagmi/index.d.ts.map +1 -1
  72. package/lib/typescript/module/solana/address.d.ts +1 -1
  73. package/lib/typescript/module/solana/address.d.ts.map +1 -1
  74. package/lib/typescript/module/solana/index.d.ts +2 -2
  75. package/lib/typescript/module/solana/index.d.ts.map +1 -1
  76. package/lib/typescript/module/types/base.d.ts +3 -3
  77. package/lib/typescript/module/types/base.d.ts.map +1 -1
  78. package/lib/typescript/module/types/events.d.ts +2 -2
  79. package/lib/typescript/module/types/events.d.ts.map +1 -1
  80. package/lib/typescript/module/types/index.d.ts +2 -2
  81. package/lib/typescript/module/types/index.d.ts.map +1 -1
  82. package/lib/typescript/module/utils/index.d.ts +5 -5
  83. package/lib/typescript/module/utils/index.d.ts.map +1 -1
  84. package/lib/typescript/module/utils/sanitize.d.ts +31 -0
  85. package/lib/typescript/module/utils/sanitize.d.ts.map +1 -0
  86. package/lib/typescript/module/utils/trafficSource.d.ts +4 -1
  87. package/lib/typescript/module/utils/trafficSource.d.ts.map +1 -1
  88. package/lib/typescript/module/version.d.ts +1 -1
  89. package/package.json +2 -2
  90. package/src/FormoAnalytics.ts +18 -3
  91. package/src/lib/crash/index.ts +21 -7
  92. package/src/lib/event/EventFactory.ts +14 -1
  93. package/src/lib/event/EventQueue.ts +402 -61
  94. package/src/utils/sanitize.ts +274 -0
  95. package/src/utils/trafficSource.ts +19 -1
  96. package/src/version.ts +1 -1
@@ -6,6 +6,15 @@ import { clampNumber, getActionDescriptor, millisecondsToSecond, isNetworkError
6
6
  import { hash } from "../../utils/hash.js";
7
7
  import { toDateHourMinute } from "../../utils/timestamp.js";
8
8
  import { logger } from "../logger/index.js";
9
+
10
+ /**
11
+ * A send failure tagged with whether another attempt could ever succeed.
12
+ * `retryable: false` means the API rejected the payload itself (4xx other
13
+ * than 429) — re-posting the identical batch will fail identically forever.
14
+ * Left undefined for unexpected errors, which are treated as retryable so an
15
+ * unrecognised fault never silently discards events.
16
+ */
17
+
9
18
  const DEFAULT_RETRY = 3;
10
19
  const MAX_RETRY = 5;
11
20
  const MIN_RETRY = 1;
@@ -16,12 +25,37 @@ const DEFAULT_QUEUE_SIZE = 1_024 * 500; // 500kB
16
25
  const MAX_QUEUE_SIZE = 1_024 * 500; // 500kB
17
26
  const MIN_QUEUE_SIZE = 200; // 200 bytes
18
27
 
28
+ // How long cleanup() waits for an already-in-flight send before abandoning it.
29
+ // Teardown must finish promptly: the provider blocks re-initialization on the
30
+ // pending cleanup, so an unbounded wait would strand the SDK.
31
+ const CLEANUP_FLUSH_WAIT = 1_000 * 5; // 5 seconds
32
+
19
33
  const DEFAULT_FLUSH_INTERVAL = 1_000 * 30; // 30 seconds
20
34
  const MAX_FLUSH_INTERVAL = 1_000 * 300; // 5 minutes
21
35
  const MIN_FLUSH_INTERVAL = 1_000 * 10; // 10 seconds
22
36
 
23
37
  const noop = () => {};
24
38
 
39
+ /**
40
+ * Invoke a consumer-supplied callback without letting it escape the SDK.
41
+ * These callbacks are arbitrary app code; a throw from one must not surface
42
+ * as an unhandled rejection from flush() or abort the remaining callbacks.
43
+ */
44
+ const safeCall = (fn, ...args) => {
45
+ try {
46
+ const result = fn(...args);
47
+ // An `async` callback signals failure by returning a rejected promise
48
+ // rather than throwing, which the catch below would never see.
49
+ if (result && typeof result.then === "function") {
50
+ Promise.resolve(result).catch(error => {
51
+ logger.error("EventQueue: Async callback rejected, ignoring", error);
52
+ });
53
+ }
54
+ } catch (error) {
55
+ logger.error("EventQueue: Callback threw, ignoring", error);
56
+ }
57
+ };
58
+
25
59
  /**
26
60
  * Event queue for React Native
27
61
  * Handles batching, flushing, and retries with app lifecycle awareness
@@ -32,6 +66,35 @@ export class EventQueue {
32
66
  payloadHashes = new Set();
33
67
  flushMutex = Promise.resolve();
34
68
  appStateSubscription = null;
69
+ /**
70
+ * Whether anything has been flushed yet this app session. Starts false so
71
+ * the first event is sent immediately (see enqueue). A cold start opened
72
+ * from an ad click or deep link produces its attribution events right away,
73
+ * and those are exactly the events lost if the process is killed before the
74
+ * batch timer fires or AppState reports background — a force-quit from the
75
+ * app switcher, an OS memory kill, or a crash never gives us that chance.
76
+ */
77
+ flushed = false;
78
+ /**
79
+ * Set once cleanup starts. A flush already in flight can fail and re-queue
80
+ * its items after teardown has begun; without this it would arm a timer on
81
+ * an instance that is going away, firing network calls post-cleanup.
82
+ */
83
+ closed = false;
84
+ /**
85
+ * Bumped by clear(). flush() splices its batch out of the queue before
86
+ * sending, so a clear() during opt-out cannot see those items; without this
87
+ * a later send failure would unshift them back and they would be delivered
88
+ * after consent was withdrawn.
89
+ */
90
+ generation = 0;
91
+ /**
92
+ * The in-progress teardown, if any. cleanup() is public and the provider can
93
+ * call it more than once; a second run would start its own drain flush that
94
+ * is exempt from the closed check, splice the events the first run had just
95
+ * re-queued, and send them after the first cleanup() had already resolved.
96
+ */
97
+ cleanupPromise = null;
35
98
  constructor(writeKey, options) {
36
99
  this.writeKey = writeKey;
37
100
  this.apiHost = options.apiHost;
@@ -55,6 +118,11 @@ export class EventQueue {
55
118
  * Handle app state changes
56
119
  */
57
120
  handleAppStateChange(nextAppState) {
121
+ // Teardown is already draining the queue. A flush queued here would wait
122
+ // on the mutex and could run — and re-queue on failure — after cleanup()
123
+ // has returned, leaving network work with no owner.
124
+ if (this.closed) return;
125
+
58
126
  // Flush when app goes to background or becomes inactive
59
127
  if (nextAppState === "background" || nextAppState === "inactive") {
60
128
  logger.debug("EventQueue: App going to background, flushing events");
@@ -90,9 +158,31 @@ export class EventQueue {
90
158
  * Add event to queue
91
159
  */
92
160
  async enqueue(event, callback) {
161
+ if (this.closed) {
162
+ logger.debug("EventQueue: Ignoring event enqueued after cleanup");
163
+ return;
164
+ }
93
165
  callback = callback || noop;
166
+ const generation = this.generation;
94
167
  const message_id = await this.generateMessageId(event);
95
168
 
169
+ // Hashing is async, so cleanup() can complete while this call is suspended
170
+ // above. Re-check, or a caller that did not await enqueue() would resume
171
+ // after teardown, push onto a queue nobody will drain, and — if this is the
172
+ // session's first event — fire a network request on a torn-down instance.
173
+ if (this.closed) {
174
+ logger.debug("EventQueue: Ignoring event enqueued after cleanup");
175
+ return;
176
+ }
177
+
178
+ // Same window, but for opt-out: clear() cannot see an event that has not
179
+ // reached the queue yet, so an enqueue suspended across it would land
180
+ // afterwards and be delivered despite consent having been withdrawn.
181
+ if (this.generation !== generation) {
182
+ logger.debug("EventQueue: Ignoring event enqueued before opt-out");
183
+ return;
184
+ }
185
+
96
186
  // Check for duplicate
97
187
  if (this.isDuplicate(message_id)) {
98
188
  logger.warn(`Event already enqueued, try again after ${millisecondsToSecond(this.flushIntervalMs)} seconds.`);
@@ -120,21 +210,47 @@ export class EventQueue {
120
210
  }));
121
211
  const hasReachedFlushAt = this.queue.length >= this.flushAt;
122
212
  const hasReachedQueueSize = this.queue.reduce((acc, item) => acc + JSON.stringify(item).length, 0) >= this.maxQueueSize;
123
- if (hasReachedFlushAt || hasReachedQueueSize) {
213
+
214
+ // Ship the first event of the app session as a batch of one rather than
215
+ // holding it for flushAt/flushInterval; subsequent events keep batching.
216
+ if (hasReachedFlushAt || hasReachedQueueSize || !this.flushed) {
124
217
  // Clear timer to prevent double flush
125
218
  if (this.timer) {
126
219
  clearTimeout(this.timer);
127
220
  this.timer = null;
128
221
  }
222
+ this.flushed = true;
129
223
  // Flush uses internal mutex to serialize operations
224
+ // A failed flush re-queues its items and re-arms the interval itself, so
225
+ // a cold start whose immediate flush fails — the likeliest case, since
226
+ // the radio may still be waking — still retries the attribution event.
130
227
  this.flush().catch(error => {
131
228
  logger.error("EventQueue: Failed to flush on threshold", error);
132
229
  });
133
230
  return;
134
231
  }
135
- if (this.flushIntervalMs && !this.timer) {
136
- this.timer = setTimeout(this.flush.bind(this), this.flushIntervalMs);
137
- }
232
+ this.scheduleFlush();
233
+ }
234
+
235
+ /**
236
+ * Arm the batch-interval timer, if there is queued work and nothing is
237
+ * already scheduled. Safe to call repeatedly; it never stacks timers.
238
+ */
239
+ scheduleFlush() {
240
+ if (this.closed) return;
241
+ if (!this.flushIntervalMs || this.timer || !this.queue.length) return;
242
+ this.timer = setTimeout(() => {
243
+ // flush() rethrows once sendWithRetry is exhausted. Passing it to
244
+ // setTimeout bare left that rejection unhandled, surfacing in the host
245
+ // app as an "Uncaught (in promise)" on every failed interval flush —
246
+ // observed against a 4xx from the events API. The threshold and
247
+ // background paths already log and swallow; this one has to as well.
248
+ // flush() re-arms on failure, so a queue that outlives a transient
249
+ // outage keeps retrying and drains once connectivity returns.
250
+ this.flush().catch(error => {
251
+ logger.error("EventQueue: Failed to flush on interval", error);
252
+ });
253
+ }, this.flushIntervalMs);
138
254
  }
139
255
 
140
256
  /**
@@ -143,6 +259,18 @@ export class EventQueue {
143
259
  * preventing race conditions with re-queued items on failure.
144
260
  */
145
261
  async flush(callback) {
262
+ return this.runFlush(callback, false);
263
+ }
264
+
265
+ /**
266
+ * The flush body. `duringCleanup` marks the calls teardown makes itself, so
267
+ * they are exempt from the closed check below — every other flush must be
268
+ * abandoned once teardown has begun. It has to identify the specific call
269
+ * rather than a window of time, because cleanup spends most of its drain
270
+ * loop awaiting one of these, and a concurrent flush arriving then would
271
+ * look internal.
272
+ */
273
+ async runFlush(callback, duringCleanup) {
146
274
  callback = callback || noop;
147
275
  if (this.timer) {
148
276
  clearTimeout(this.timer);
@@ -158,36 +286,90 @@ export class EventQueue {
158
286
  try {
159
287
  // Wait for any previous flush to complete
160
288
  await previousMutex;
289
+
290
+ // Teardown began while this flush was waiting its turn. The instant the
291
+ // flush ahead released the mutex it would otherwise splice and send —
292
+ // before cleanup() had even observed that flush finishing — delivering
293
+ // events after teardown resolved.
294
+ if (this.closed && !duringCleanup) {
295
+ // Deliberately no callback: this resumes only once the flush ahead
296
+ // settles, which can be long after cleanup() resolved, and nothing may
297
+ // call back into a torn-down instance. The returned promise still
298
+ // resolves, so an awaiting caller is never left hanging.
299
+ logger.debug("EventQueue: Abandoning flush that outlived cleanup");
300
+ return;
301
+ }
161
302
  if (!this.queue.length) {
162
- callback();
303
+ safeCall(callback);
163
304
  return;
164
305
  }
165
306
  const items = this.queue.splice(0, this.flushAt);
307
+ // Snapshot after the splice: from here on these items live only in this
308
+ // closure, so a clear() cannot reach them and we have to detect it.
309
+ const generation = this.generation;
166
310
  const sentAt = new Date().toISOString();
167
311
  const data = items.map(item => ({
168
312
  ...item.message,
169
313
  sent_at: sentAt
170
314
  }));
171
315
  const done = err => {
316
+ // A batch cleanup() abandoned must not call back into an app that has
317
+ // already torn the SDK down: its request has no timeout, so it can
318
+ // settle long after cleanup() resolved and the provider moved on to a
319
+ // replacement instance. A plain clear() (opt-out) still notifies, so
320
+ // the consumer does learn those events were dropped.
321
+ if (this.closed && this.generation !== generation) return;
172
322
  items.forEach(({
173
323
  message,
174
324
  callback: itemCallback
175
- }) => itemCallback(err, message, data));
176
- callback(err, data);
325
+ }) => safeCall(itemCallback, err, message, data));
326
+ safeCall(callback, err, data);
177
327
  };
178
328
  try {
179
- await this.sendWithRetry(data);
180
- // Only remove hashes after successful send
181
- items.forEach(item => this.payloadHashes.delete(item.hash));
329
+ await this.sendWithRetry(data, generation);
330
+ // Only remove hashes after successful send, and only if clear() has
331
+ // not run meanwhile: it already emptied the set, so an identical event
332
+ // may have been enqueued since and now owns that hash. Deleting it
333
+ // here would strip the new item's dedup entry and let a duplicate
334
+ // through.
335
+ if (this.generation === generation) {
336
+ items.forEach(item => this.payloadHashes.delete(item.hash));
337
+ }
182
338
  done();
183
339
  logger.info(`Events sent successfully: ${data.length} events`);
184
340
  } catch (err) {
185
- // Re-add items to the front of the queue for retry on next flush
186
- // Note: We intentionally keep hashes in payloadHashes to prevent duplicate
187
- // events from being enqueued while these items are pending retry.
188
- this.queue.unshift(...items);
189
- done(err);
190
- logger.error("Error sending events, re-queued for retry:", err);
341
+ if (this.generation !== generation) {
342
+ // clear() ran while this batch was in flight the consumer opted
343
+ // out. Putting these back would deliver events after consent was
344
+ // withdrawn, and clear() already emptied payloadHashes, so a
345
+ // resurrected item would also no longer be deduped.
346
+ done(err);
347
+ logger.debug(`EventQueue: Discarding ${items.length} in-flight event(s) cleared mid-flush`);
348
+ } else if (err?.retryable === false) {
349
+ // The API rejected this payload itself, so the identical batch can
350
+ // never succeed. Keeping it queued would re-post it every interval
351
+ // forever, re-invoking callbacks and burning the user's battery and
352
+ // data. Drop it, and release the hashes so equivalent events are not
353
+ // blocked from being enqueued again later. The web SDK likewise does
354
+ // not re-queue a failed batch.
355
+ items.forEach(item => this.payloadHashes.delete(item.hash));
356
+ done(err);
357
+ logger.error(`Dropping ${items.length} event(s), permanently rejected by the API:`, err);
358
+ } else {
359
+ // Re-add items to the front of the queue for retry on next flush
360
+ // Note: We intentionally keep hashes in payloadHashes to prevent duplicate
361
+ // events from being enqueued while these items are pending retry.
362
+ this.queue.unshift(...items);
363
+ done(err);
364
+ logger.error("Error sending events, re-queued for retry:", err);
365
+ }
366
+
367
+ // Re-arm here rather than in each caller's catch, so EVERY entry point
368
+ // is covered — the background AppState flush and a consumer's manual
369
+ // flush() included. flush() clears the timer on entry, so without this
370
+ // a failed background flush would re-queue its items and leave nothing
371
+ // scheduled to retry them. No-ops when the queue is empty or closed.
372
+ this.scheduleFlush();
191
373
  throw err;
192
374
  }
193
375
  } finally {
@@ -195,10 +377,24 @@ export class EventQueue {
195
377
  }
196
378
  }
197
379
 
380
+ /**
381
+ * Abort a batch whose events were cleared while it sat in retry backoff.
382
+ * Retries span seconds, so a consumer can opt out between attempts; posting
383
+ * the next one would deliver events after consent was withdrawn.
384
+ */
385
+ assertNotCleared(generation) {
386
+ if (this.generation !== generation) {
387
+ const error = new Error("EventQueue: batch cleared during retry backoff");
388
+ // Never re-queue: these events were explicitly discarded.
389
+ error.retryable = false;
390
+ throw error;
391
+ }
392
+ }
393
+
198
394
  /**
199
395
  * Send events with retry logic
200
396
  */
201
- async sendWithRetry(data, attempt = 0) {
397
+ async sendWithRetry(data, generation, attempt = 0) {
202
398
  try {
203
399
  const response = await fetch(this.apiHost, {
204
400
  method: "POST",
@@ -210,16 +406,27 @@ export class EventQueue {
210
406
  if (shouldRetry && attempt < this.retryCount) {
211
407
  const delay = Math.pow(2, attempt) * 1000;
212
408
  await new Promise(resolve => setTimeout(() => resolve(), delay));
213
- return this.sendWithRetry(data, attempt + 1);
409
+ this.assertNotCleared(generation);
410
+ return this.sendWithRetry(data, generation, attempt + 1);
214
411
  }
215
- throw new Error(`HTTP error! status: ${response.status}`);
412
+ const error = new Error(`HTTP error! status: ${response.status}`);
413
+ // A 4xx that is not 429 rejects this payload permanently — an invalid
414
+ // write key or a malformed batch. Tag it so flush() drops the batch
415
+ // instead of re-posting it on every interval for the process lifetime.
416
+ error.retryable = shouldRetry;
417
+ throw error;
216
418
  }
217
419
  } catch (error) {
218
- if (isNetworkError(error) && attempt < this.retryCount) {
219
- const delay = Math.pow(2, attempt) * 1000;
220
- logger.warn(`Network error, retrying in ${delay}ms...`);
221
- await new Promise(resolve => setTimeout(() => resolve(), delay));
222
- return this.sendWithRetry(data, attempt + 1);
420
+ if (isNetworkError(error)) {
421
+ if (attempt < this.retryCount) {
422
+ const delay = Math.pow(2, attempt) * 1000;
423
+ logger.warn(`Network error, retrying in ${delay}ms...`);
424
+ await new Promise(resolve => setTimeout(() => resolve(), delay));
425
+ this.assertNotCleared(generation);
426
+ return this.sendWithRetry(data, generation, attempt + 1);
427
+ }
428
+ // Connectivity comes back; keep these for a later attempt.
429
+ error.retryable = true;
223
430
  }
224
431
  throw error;
225
432
  }
@@ -229,8 +436,11 @@ export class EventQueue {
229
436
  * Check if error should be retried
230
437
  */
231
438
  shouldRetry(status) {
232
- // Retry on server errors (5xx) and rate limiting (429)
233
- return status >= 500 && status <= 599 || status === 429;
439
+ // Retry on server errors (5xx), rate limiting (429) and request timeout
440
+ // (408). 408 matters now that a non-retryable status drops the batch: a
441
+ // proxy or server timing out a request is transient, and treating it as
442
+ // permanent would silently lose those events.
443
+ return status >= 500 && status <= 599 || status === 429 || status === 408;
234
444
  }
235
445
 
236
446
  /**
@@ -239,6 +449,9 @@ export class EventQueue {
239
449
  * from being sent after consent is revoked.
240
450
  */
241
451
  clear() {
452
+ // Invalidate any batch already in flight so a later send failure cannot
453
+ // unshift it back onto the queue we are emptying here.
454
+ this.generation++;
242
455
  this.queue = [];
243
456
  this.payloadHashes.clear();
244
457
  if (this.timer) {
@@ -248,49 +461,147 @@ export class EventQueue {
248
461
  logger.debug("EventQueue: Cleared all pending events");
249
462
  }
250
463
 
464
+ /**
465
+ * Give up on the events still queued at teardown, and make sure a send that
466
+ * is still holding a batch cannot put them back.
467
+ */
468
+ abandonQueuedEvents(reason) {
469
+ logger.warn(`EventQueue: ${reason}, abandoning ${this.queue.length} event(s)`);
470
+ // clear() rather than emptying the queue by hand: it also bumps the
471
+ // generation, which is what actually invalidates a batch a stalled flush
472
+ // is still holding. Without the bump that flush would later fail, unshift
473
+ // its items back onto the queue we just emptied, and a flush chained
474
+ // behind it would send them and invoke their callbacks a second time —
475
+ // after teardown had already returned.
476
+ this.clear();
477
+ }
478
+
251
479
  /**
252
480
  * Clean up resources, flushing any pending events first
253
481
  */
254
482
  async cleanup() {
255
- // Flush all remaining queued events before teardown
256
- // Loop until queue is empty since flush() only sends flushAt events per call
257
- // Safety limit prevents infinite loops if flush silently fails
258
- const maxAttempts = Math.ceil(this.queue.length / this.flushAt) + 3;
259
- let attempts = 0;
260
- const initialQueueLength = this.queue.length;
261
- while (this.queue.length > 0 && attempts < maxAttempts) {
262
- const queueLengthBefore = this.queue.length;
263
- try {
264
- await this.flush();
265
- } catch (error) {
266
- logger.error("EventQueue: Failed to flush during cleanup", error);
267
- // Break on error to avoid infinite loop if flush keeps failing
268
- break;
269
- }
270
-
271
- // If queue length didn't decrease, flush is silently failing
272
- if (this.queue.length >= queueLengthBefore) {
273
- logger.warn("EventQueue: Flush did not reduce queue size, aborting cleanup");
274
- break;
275
- }
276
- attempts++;
277
- }
278
- if (attempts >= maxAttempts && this.queue.length > 0) {
279
- logger.warn(`EventQueue: Cleanup safety limit reached. Discarding ${this.queue.length} events.`);
280
- this.queue = [];
281
- this.payloadHashes.clear();
282
- }
283
- if (initialQueueLength > 0) {
284
- logger.debug(`EventQueue: Cleanup completed, flushed ${initialQueueLength - this.queue.length} events`);
483
+ // Teardown is idempotent: a caller that asks twice joins the run already
484
+ // under way rather than starting a competing one.
485
+ if (!this.cleanupPromise) {
486
+ // Teardown is best-effort and must always settle: a rejection here would
487
+ // be memoised, so every later cleanup() would return the same rejected
488
+ // promise and never retry — and the provider, which awaits the pending
489
+ // cleanup before building a replacement, would reject with it forever.
490
+ this.cleanupPromise = this.runCleanup().catch(error => {
491
+ logger.error("EventQueue: Cleanup failed", error);
492
+ // Whatever failed, the instance is going away: make sure nothing is
493
+ // left queued for a straggling flush to pick up.
494
+ this.clear();
495
+ });
285
496
  }
497
+ return this.cleanupPromise;
498
+ }
499
+ async runCleanup() {
500
+ // Stop anything from arming a new timer for the rest of teardown.
501
+ this.closed = true;
286
502
  if (this.timer) {
287
503
  clearTimeout(this.timer);
288
504
  this.timer = null;
289
505
  }
506
+
507
+ // Detach up front rather than at the end: while the drain loop below is
508
+ // awaiting a send, a backgrounding app would otherwise queue a flush that
509
+ // outlives cleanup(). The closed check in the handler covers the same
510
+ // window; removing the listener means the event never reaches it at all.
290
511
  if (this.appStateSubscription) {
291
- this.appStateSubscription.remove();
512
+ try {
513
+ this.appStateSubscription.remove();
514
+ } catch (error) {
515
+ // A native-module failure here must not abort teardown before the
516
+ // queue has been drained or invalidated below.
517
+ logger.error("EventQueue: Failed to remove AppState listener", error);
518
+ }
292
519
  this.appStateSubscription = null;
293
520
  }
521
+
522
+ // One deadline for the whole of teardown, not per wait.
523
+ //
524
+ // `fetch` here has no request timeout, so any send this method waits on —
525
+ // a flush already in flight, or one the drain loop starts itself — can
526
+ // stall forever. Bounding only the first would leave the ordinary case
527
+ // unbounded: with nothing in flight the first wait returns immediately and
528
+ // the drain loop then opens a fresh request. A single deadline also keeps
529
+ // total teardown bounded rather than 5s per flush attempt.
530
+ //
531
+ // This matters beyond a stuck cleanup(): FormoAnalyticsProvider awaits the
532
+ // pending cleanup before constructing a replacement instance, so a hang
533
+ // here means the SDK can never be reconfigured again.
534
+ let deadlineTimer;
535
+ const deadline = new Promise(resolve => {
536
+ deadlineTimer = setTimeout(() => resolve("timeout"), CLEANUP_FLUSH_WAIT);
537
+ });
538
+ const withinDeadline = work => Promise.race([work, deadline]);
539
+ const timedOut = `Teardown exceeded ${millisecondsToSecond(CLEANUP_FLUSH_WAIT)}s`;
540
+ try {
541
+ // A flush may already be in flight with its items spliced out of the
542
+ // queue, which would make the drain loop below see an empty queue and
543
+ // return before delivery finished. Wait for it to settle first — on a
544
+ // transient failure it puts those items back, and the loop then retries
545
+ // them.
546
+ if ((await withinDeadline(this.flushMutex.then(() => "settled"))) === "timeout") {
547
+ this.abandonQueuedEvents(timedOut);
548
+ return;
549
+ }
550
+
551
+ // Flush all remaining queued events before teardown
552
+ // Loop until queue is empty since flush() only sends flushAt events per call
553
+ // Safety limit prevents infinite loops if flush silently fails
554
+ const maxAttempts = Math.ceil(this.queue.length / this.flushAt) + 3;
555
+ let attempts = 0;
556
+ const initialQueueLength = this.queue.length;
557
+ while (this.queue.length > 0 && attempts < maxAttempts) {
558
+ const queueLengthBefore = this.queue.length;
559
+ const outcome = await withinDeadline(
560
+ // Settle rather than reject, so only the deadline can win the race
561
+ // on an error and a rejection cannot escape unhandled.
562
+ this.runFlush(undefined, true).then(() => "flushed", error => {
563
+ logger.error("EventQueue: Failed to flush during cleanup", error);
564
+ return "failed";
565
+ }));
566
+ if (outcome === "timeout") {
567
+ this.abandonQueuedEvents(timedOut);
568
+ return;
569
+ }
570
+ // Break on error to avoid infinite loop if flush keeps failing
571
+ if (outcome === "failed") break;
572
+
573
+ // If queue length didn't decrease, flush is silently failing
574
+ if (this.queue.length >= queueLengthBefore) {
575
+ logger.warn("EventQueue: Flush did not reduce queue size, aborting cleanup");
576
+ break;
577
+ }
578
+ attempts++;
579
+ }
580
+ if (initialQueueLength > 0) {
581
+ logger.debug(`EventQueue: Cleanup completed, flushed ${initialQueueLength - this.queue.length} events`);
582
+ }
583
+
584
+ // Teardown always ends with an empty, invalidated queue — not only when
585
+ // the safety limit is hit. Each `break` above (a failed flush, a flush
586
+ // that did not shrink the queue) otherwise left events behind with the
587
+ // generation unchanged, and a flush queued behind cleanup's own — a
588
+ // concurrent public flush(), or a second cleanup() — would then send
589
+ // them and invoke their callbacks after this call had resolved.
590
+ if (this.queue.length > 0) {
591
+ this.abandonQueuedEvents(attempts >= maxAttempts ? "Cleanup safety limit reached" : "Teardown finished with events still queued");
592
+ }
593
+ } finally {
594
+ if (deadlineTimer) clearTimeout(deadlineTimer);
595
+
596
+ // The AppState listener was already detached at the top of cleanup, and
597
+ // `closed` stops anything arming a timer, so nothing can have been
598
+ // scheduled since. This is the last-resort clear for a timer that a flush
599
+ // in the drain loop above might have left behind.
600
+ if (this.timer) {
601
+ clearTimeout(this.timer);
602
+ this.timer = null;
603
+ }
604
+ }
294
605
  }
295
606
  }
296
607
  //# sourceMappingURL=EventQueue.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["AppState","EVENTS_API_REQUEST_HEADER","clampNumber","getActionDescriptor","millisecondsToSecond","isNetworkError","hash","toDateHourMinute","logger","DEFAULT_RETRY","MAX_RETRY","MIN_RETRY","DEFAULT_FLUSH_AT","MAX_FLUSH_AT","MIN_FLUSH_AT","DEFAULT_QUEUE_SIZE","MAX_QUEUE_SIZE","MIN_QUEUE_SIZE","DEFAULT_FLUSH_INTERVAL","MAX_FLUSH_INTERVAL","MIN_FLUSH_INTERVAL","noop","EventQueue","queue","timer","payloadHashes","Set","flushMutex","Promise","resolve","appStateSubscription","constructor","writeKey","options","apiHost","retryCount","flushAt","maxQueueSize","flushIntervalMs","flushInterval","setupAppStateListener","addEventListener","handleAppStateChange","bind","nextAppState","debug","flush","catch","error","generateMessageId","event","formattedTimestamp","Date","original_timestamp","eventForHashing","eventString","JSON","stringify","isDuplicate","eventId","has","add","enqueue","callback","message_id","warn","push","message","log","type","properties","ctx","context","session_id","anonymous_id","user_agent","page_url","hasReachedFlushAt","length","hasReachedQueueSize","reduce","acc","item","clearTimeout","setTimeout","previousMutex","resolveMutex","items","splice","sentAt","toISOString","data","map","sent_at","done","err","forEach","itemCallback","sendWithRetry","delete","info","unshift","attempt","response","fetch","method","headers","body","ok","shouldRetry","status","delay","Math","pow","Error","clear","cleanup","maxAttempts","ceil","attempts","initialQueueLength","queueLengthBefore","remove"],"sourceRoot":"../../../../src","sources":["lib/event/EventQueue.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["AppState","EVENTS_API_REQUEST_HEADER","clampNumber","getActionDescriptor","millisecondsToSecond","isNetworkError","hash","toDateHourMinute","logger","DEFAULT_RETRY","MAX_RETRY","MIN_RETRY","DEFAULT_FLUSH_AT","MAX_FLUSH_AT","MIN_FLUSH_AT","DEFAULT_QUEUE_SIZE","MAX_QUEUE_SIZE","MIN_QUEUE_SIZE","CLEANUP_FLUSH_WAIT","DEFAULT_FLUSH_INTERVAL","MAX_FLUSH_INTERVAL","MIN_FLUSH_INTERVAL","noop","safeCall","fn","args","result","then","Promise","resolve","catch","error","EventQueue","queue","timer","payloadHashes","Set","flushMutex","appStateSubscription","flushed","closed","generation","cleanupPromise","constructor","writeKey","options","apiHost","retryCount","flushAt","maxQueueSize","flushIntervalMs","flushInterval","setupAppStateListener","addEventListener","handleAppStateChange","bind","nextAppState","debug","flush","generateMessageId","event","formattedTimestamp","Date","original_timestamp","eventForHashing","eventString","JSON","stringify","isDuplicate","eventId","has","add","enqueue","callback","message_id","warn","push","message","log","type","properties","ctx","context","session_id","anonymous_id","user_agent","page_url","hasReachedFlushAt","length","hasReachedQueueSize","reduce","acc","item","clearTimeout","scheduleFlush","setTimeout","runFlush","duringCleanup","previousMutex","resolveMutex","items","splice","sentAt","toISOString","data","map","sent_at","done","err","forEach","itemCallback","sendWithRetry","delete","info","retryable","unshift","assertNotCleared","Error","attempt","response","fetch","method","headers","body","ok","shouldRetry","status","delay","Math","pow","clear","abandonQueuedEvents","reason","cleanup","runCleanup","remove","deadlineTimer","deadline","withinDeadline","work","race","timedOut","maxAttempts","ceil","attempts","initialQueueLength","queueLengthBefore","outcome","undefined"],"sourceRoot":"../../../../src","sources":["lib/event/EventQueue.ts"],"mappings":";;AAAA,SAASA,QAAQ,QAAwB,cAAc;AAEvD,SAASC,yBAAyB,QAAQ,0BAAiB;AAC3D,SACEC,WAAW,EACXC,mBAAmB,EACnBC,oBAAoB,EACpBC,cAAc,QACT,sBAAa;AACpB,SAASC,IAAI,QAAQ,qBAAkB;AACvC,SAASC,gBAAgB,QAAQ,0BAAuB;AACxD,SAASC,MAAM,QAAQ,oBAAW;;AAalC;AACA;AACA;AACA;AACA;AACA;AACA;;AAWA,MAAMC,aAAa,GAAG,CAAC;AACvB,MAAMC,SAAS,GAAG,CAAC;AACnB,MAAMC,SAAS,GAAG,CAAC;AAEnB,MAAMC,gBAAgB,GAAG,EAAE;AAC3B,MAAMC,YAAY,GAAG,EAAE;AACvB,MAAMC,YAAY,GAAG,CAAC;AAEtB,MAAMC,kBAAkB,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC;AACxC,MAAMC,cAAc,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC;AACpC,MAAMC,cAAc,GAAG,GAAG,CAAC,CAAC;;AAE5B;AACA;AACA;AACA,MAAMC,kBAAkB,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC;;AAEtC,MAAMC,sBAAsB,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC;AAC3C,MAAMC,kBAAkB,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC;AACxC,MAAMC,kBAAkB,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC;;AAEvC,MAAMC,IAAI,GAAGA,CAAA,KAAM,CAAC,CAAC;;AAErB;AACA;AACA;AACA;AACA;AACA,MAAMC,QAAQ,GAAGA,CAACC,EAAmC,EAAE,GAAGC,IAAe,KAAK;EAC5E,IAAI;IACF,MAAMC,MAAM,GAAGF,EAAE,CAAC,GAAGC,IAAI,CAAC;IAC1B;IACA;IACA,IAAIC,MAAM,IAAI,OAAQA,MAAM,CAA0BC,IAAI,KAAK,UAAU,EAAE;MACzEC,OAAO,CAACC,OAAO,CAACH,MAAM,CAAC,CAACI,KAAK,CAAEC,KAAK,IAAK;QACvCvB,MAAM,CAACuB,KAAK,CAAC,+CAA+C,EAAEA,KAAK,CAAC;MACtE,CAAC,CAAC;IACJ;EACF,CAAC,CAAC,OAAOA,KAAK,EAAE;IACdvB,MAAM,CAACuB,KAAK,CAAC,sCAAsC,EAAEA,KAAK,CAAC;EAC7D;AACF,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,MAAMC,UAAU,CAAwB;EAGrCC,KAAK,GAAgB,EAAE;EACvBC,KAAK,GAAyC,IAAI;EAKlDC,aAAa,GAAgB,IAAIC,GAAG,CAAC,CAAC;EACtCC,UAAU,GAAkBT,OAAO,CAACC,OAAO,CAAC,CAAC;EAC7CS,oBAAoB,GAAkC,IAAI;EAClE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACUC,OAAO,GAAG,KAAK;EACvB;AACF;AACA;AACA;AACA;EACUC,MAAM,GAAG,KAAK;EACtB;AACF;AACA;AACA;AACA;AACA;EACUC,UAAU,GAAG,CAAC;EACtB;AACF;AACA;AACA;AACA;AACA;EACUC,cAAc,GAAyB,IAAI;EAEnDC,WAAWA,CAACC,QAAgB,EAAEC,OAAgB,EAAE;IAC9C,IAAI,CAACD,QAAQ,GAAGA,QAAQ;IACxB,IAAI,CAACE,OAAO,GAAGD,OAAO,CAACC,OAAO;IAC9B,IAAI,CAACC,UAAU,GAAG7C,WAAW,CAC3B2C,OAAO,CAACE,UAAU,IAAItC,aAAa,EACnCC,SAAS,EACTC,SACF,CAAC;IACD,IAAI,CAACqC,OAAO,GAAG9C,WAAW,CACxB2C,OAAO,CAACG,OAAO,IAAIpC,gBAAgB,EACnCC,YAAY,EACZC,YACF,CAAC;IACD,IAAI,CAACmC,YAAY,GAAG/C,WAAW,CAC7B2C,OAAO,CAACI,YAAY,IAAIlC,kBAAkB,EAC1CC,cAAc,EACdC,cACF,CAAC;IACD,IAAI,CAACiC,eAAe,GAAGhD,WAAW,CAChC2C,OAAO,CAACM,aAAa,IAAIhC,sBAAsB,EAC/CC,kBAAkB,EAClBC,kBACF,CAAC;IACD;IACA,IAAI,CAAC+B,qBAAqB,CAAC,CAAC;EAC9B;;EAEA;AACF;AACA;AACA;EACUA,qBAAqBA,CAAA,EAAS;IACpC,IAAI,CAACd,oBAAoB,GAAGtC,QAAQ,CAACqD,gBAAgB,CACnD,QAAQ,EACR,IAAI,CAACC,oBAAoB,CAACC,IAAI,CAAC,IAAI,CACrC,CAAC;EACH;;EAEA;AACF;AACA;EACUD,oBAAoBA,CAACE,YAA4B,EAAQ;IAC/D;IACA;IACA;IACA,IAAI,IAAI,CAAChB,MAAM,EAAE;;IAEjB;IACA,IAAIgB,YAAY,KAAK,YAAY,IAAIA,YAAY,KAAK,UAAU,EAAE;MAChEhD,MAAM,CAACiD,KAAK,CAAC,sDAAsD,CAAC;MACpE,IAAI,CAACC,KAAK,CAAC,CAAC,CAAC5B,KAAK,CAAEC,KAAK,IAAK;QAC5BvB,MAAM,CAACuB,KAAK,CAAC,2CAA2C,EAAEA,KAAK,CAAC;MAClE,CAAC,CAAC;IACJ;EACF;;EAEA;AACF;AACA;EACE,MAAc4B,iBAAiBA,CAACC,KAAkB,EAAmB;IACnE,MAAMC,kBAAkB,GAAGtD,gBAAgB,CACzC,IAAIuD,IAAI,CAACF,KAAK,CAACG,kBAAkB,CACnC,CAAC;IACD,MAAMC,eAAe,GAAG;MAAE,GAAGJ,KAAK;MAAEG,kBAAkB,EAAEF;IAAmB,CAAC;IAC5E,MAAMI,WAAW,GAAGC,IAAI,CAACC,SAAS,CAACH,eAAe,CAAC;IACnD,OAAO1D,IAAI,CAAC2D,WAAW,CAAC;EAC1B;;EAEA;AACF;AACA;EACUG,WAAWA,CAACC,OAAe,EAAW;IAC5C,IAAI,IAAI,CAAClC,aAAa,CAACmC,GAAG,CAACD,OAAO,CAAC,EAAE,OAAO,IAAI;IAChD,IAAI,CAAClC,aAAa,CAACoC,GAAG,CAACF,OAAO,CAAC;IAC/B,OAAO,KAAK;EACd;;EAEA;AACF;AACA;EACE,MAAMG,OAAOA,CACXZ,KAAkB,EAClBa,QAAuC,EACxB;IACf,IAAI,IAAI,CAACjC,MAAM,EAAE;MACfhC,MAAM,CAACiD,KAAK,CAAC,mDAAmD,CAAC;MACjE;IACF;IAEAgB,QAAQ,GAAGA,QAAQ,IAAInD,IAAI;IAE3B,MAAMmB,UAAU,GAAG,IAAI,CAACA,UAAU;IAClC,MAAMiC,UAAU,GAAG,MAAM,IAAI,CAACf,iBAAiB,CAACC,KAAK,CAAC;;IAEtD;IACA;IACA;IACA;IACA,IAAI,IAAI,CAACpB,MAAM,EAAE;MACfhC,MAAM,CAACiD,KAAK,CAAC,mDAAmD,CAAC;MACjE;IACF;;IAEA;IACA;IACA;IACA,IAAI,IAAI,CAAChB,UAAU,KAAKA,UAAU,EAAE;MAClCjC,MAAM,CAACiD,KAAK,CAAC,oDAAoD,CAAC;MAClE;IACF;;IAEA;IACA,IAAI,IAAI,CAACW,WAAW,CAACM,UAAU,CAAC,EAAE;MAChClE,MAAM,CAACmE,IAAI,CACT,2CAA2CvE,oBAAoB,CAC7D,IAAI,CAAC8C,eACP,CAAC,WACH,CAAC;MACD;IACF;IAEA,IAAI,CAACjB,KAAK,CAAC2C,IAAI,CAAC;MACdC,OAAO,EAAE;QAAE,GAAGjB,KAAK;QAAEc;MAAW,CAAC;MACjCD,QAAQ;MACRnE,IAAI,EAAEoE;IACR,CAAC,CAAC;IAEFlE,MAAM,CAACsE,GAAG,CACR,mBAAmB3E,mBAAmB,CAACyD,KAAK,CAACmB,IAAI,EAAEnB,KAAK,CAACoB,UAAU,CAAC,EACtE,CAAC;;IAED;IACA,MAAMC,GAAG,GAAIrB,KAAK,CAACsB,OAAO,IAAI,CAAC,CAA6B;IAC5D1E,MAAM,CAACiD,KAAK,CACV,eAAe,EACfS,IAAI,CAACC,SAAS,CAAC;MACbY,IAAI,EAAEnB,KAAK,CAACmB,IAAI;MAChBnB,KAAK,EAAEA,KAAK,CAACA,KAAK;MAClBuB,UAAU,EAAEvB,KAAK,CAACuB,UAAU;MAC5BC,YAAY,EAAExB,KAAK,CAACwB,YAAY;MAChCC,UAAU,EAAEJ,GAAG,CAACI,UAAU;MAC1BC,QAAQ,EAAEL,GAAG,CAACK;IAChB,CAAC,CACH,CAAC;IAED,MAAMC,iBAAiB,GAAG,IAAI,CAACtD,KAAK,CAACuD,MAAM,IAAI,IAAI,CAACxC,OAAO;IAC3D,MAAMyC,mBAAmB,GACvB,IAAI,CAACxD,KAAK,CAACyD,MAAM,CACf,CAACC,GAAG,EAAEC,IAAI,KAAKD,GAAG,GAAGzB,IAAI,CAACC,SAAS,CAACyB,IAAI,CAAC,CAACJ,MAAM,EAChD,CACF,CAAC,IAAI,IAAI,CAACvC,YAAY;;IAExB;IACA;IACA,IAAIsC,iBAAiB,IAAIE,mBAAmB,IAAI,CAAC,IAAI,CAAClD,OAAO,EAAE;MAC7D;MACA,IAAI,IAAI,CAACL,KAAK,EAAE;QACd2D,YAAY,CAAC,IAAI,CAAC3D,KAAK,CAAC;QACxB,IAAI,CAACA,KAAK,GAAG,IAAI;MACnB;MACA,IAAI,CAACK,OAAO,GAAG,IAAI;MACnB;MACA;MACA;MACA;MACA,IAAI,CAACmB,KAAK,CAAC,CAAC,CAAC5B,KAAK,CAAEC,KAAK,IAAK;QAC5BvB,MAAM,CAACuB,KAAK,CAAC,0CAA0C,EAAEA,KAAK,CAAC;MACjE,CAAC,CAAC;MACF;IACF;IAEA,IAAI,CAAC+D,aAAa,CAAC,CAAC;EACtB;;EAEA;AACF;AACA;AACA;EACUA,aAAaA,CAAA,EAAS;IAC5B,IAAI,IAAI,CAACtD,MAAM,EAAE;IACjB,IAAI,CAAC,IAAI,CAACU,eAAe,IAAI,IAAI,CAAChB,KAAK,IAAI,CAAC,IAAI,CAACD,KAAK,CAACuD,MAAM,EAAE;IAE/D,IAAI,CAACtD,KAAK,GAAG6D,UAAU,CAAC,MAAM;MAC5B;MACA;MACA;MACA;MACA;MACA;MACA;MACA,IAAI,CAACrC,KAAK,CAAC,CAAC,CAAC5B,KAAK,CAAEC,KAAK,IAAK;QAC5BvB,MAAM,CAACuB,KAAK,CAAC,yCAAyC,EAAEA,KAAK,CAAC;MAChE,CAAC,CAAC;IACJ,CAAC,EAAE,IAAI,CAACmB,eAAe,CAAC;EAC1B;;EAEA;AACF;AACA;AACA;AACA;EACE,MAAMQ,KAAKA,CAACe,QAAuC,EAAiB;IAClE,OAAO,IAAI,CAACuB,QAAQ,CAACvB,QAAQ,EAAE,KAAK,CAAC;EACvC;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACE,MAAcuB,QAAQA,CACpBvB,QAAoD,EACpDwB,aAAsB,EACP;IACfxB,QAAQ,GAAGA,QAAQ,IAAInD,IAAI;IAE3B,IAAI,IAAI,CAACY,KAAK,EAAE;MACd2D,YAAY,CAAC,IAAI,CAAC3D,KAAK,CAAC;MACxB,IAAI,CAACA,KAAK,GAAG,IAAI;IACnB;;IAEA;IACA,MAAMgE,aAAa,GAAG,IAAI,CAAC7D,UAAU;IACrC,IAAI8D,YAAwB;IAC5B,IAAI,CAAC9D,UAAU,GAAG,IAAIT,OAAO,CAAEC,OAAO,IAAK;MACzCsE,YAAY,GAAGtE,OAAO;IACxB,CAAC,CAAC;IAEF,IAAI;MACF;MACA,MAAMqE,aAAa;;MAEnB;MACA;MACA;MACA;MACA,IAAI,IAAI,CAAC1D,MAAM,IAAI,CAACyD,aAAa,EAAE;QACjC;QACA;QACA;QACA;QACAzF,MAAM,CAACiD,KAAK,CAAC,oDAAoD,CAAC;QAClE;MACF;MAEA,IAAI,CAAC,IAAI,CAACxB,KAAK,CAACuD,MAAM,EAAE;QACtBjE,QAAQ,CAACkD,QAAQ,CAAC;QAClB;MACF;MAEA,MAAM2B,KAAK,GAAG,IAAI,CAACnE,KAAK,CAACoE,MAAM,CAAC,CAAC,EAAE,IAAI,CAACrD,OAAO,CAAC;MAChD;MACA;MACA,MAAMP,UAAU,GAAG,IAAI,CAACA,UAAU;MAElC,MAAM6D,MAAM,GAAG,IAAIxC,IAAI,CAAC,CAAC,CAACyC,WAAW,CAAC,CAAC;MACvC,MAAMC,IAA+B,GAAGJ,KAAK,CAACK,GAAG,CAAEb,IAAI,KAAM;QAC3D,GAAGA,IAAI,CAACf,OAAO;QACf6B,OAAO,EAAEJ;MACX,CAAC,CAAC,CAAC;MAEH,MAAMK,IAAI,GAAIC,GAAW,IAAK;QAC5B;QACA;QACA;QACA;QACA;QACA,IAAI,IAAI,CAACpE,MAAM,IAAI,IAAI,CAACC,UAAU,KAAKA,UAAU,EAAE;QAEnD2D,KAAK,CAACS,OAAO,CAAC,CAAC;UAAEhC,OAAO;UAAEJ,QAAQ,EAAEqC;QAAa,CAAC,KAChDvF,QAAQ,CAACuF,YAAY,EAAEF,GAAG,EAAE/B,OAAO,EAAE2B,IAAI,CAC3C,CAAC;QACDjF,QAAQ,CAACkD,QAAQ,EAAGmC,GAAG,EAAEJ,IAAI,CAAC;MAChC,CAAC;MAED,IAAI;QACF,MAAM,IAAI,CAACO,aAAa,CAACP,IAAI,EAAE/D,UAAU,CAAC;QAC1C;QACA;QACA;QACA;QACA;QACA,IAAI,IAAI,CAACA,UAAU,KAAKA,UAAU,EAAE;UAClC2D,KAAK,CAACS,OAAO,CAAEjB,IAAI,IAAK,IAAI,CAACzD,aAAa,CAAC6E,MAAM,CAACpB,IAAI,CAACtF,IAAI,CAAC,CAAC;QAC/D;QACAqG,IAAI,CAAC,CAAC;QACNnG,MAAM,CAACyG,IAAI,CAAC,6BAA6BT,IAAI,CAAChB,MAAM,SAAS,CAAC;MAChE,CAAC,CAAC,OAAOoB,GAAG,EAAE;QACZ,IAAI,IAAI,CAACnE,UAAU,KAAKA,UAAU,EAAE;UAClC;UACA;UACA;UACA;UACAkE,IAAI,CAACC,GAAY,CAAC;UAClBpG,MAAM,CAACiD,KAAK,CACV,0BAA0B2C,KAAK,CAACZ,MAAM,uCACxC,CAAC;QACH,CAAC,MAAM,IAAKoB,GAAG,EAAgBM,SAAS,KAAK,KAAK,EAAE;UAClD;UACA;UACA;UACA;UACA;UACA;UACAd,KAAK,CAACS,OAAO,CAAEjB,IAAI,IAAK,IAAI,CAACzD,aAAa,CAAC6E,MAAM,CAACpB,IAAI,CAACtF,IAAI,CAAC,CAAC;UAC7DqG,IAAI,CAACC,GAAY,CAAC;UAClBpG,MAAM,CAACuB,KAAK,CACV,YAAYqE,KAAK,CAACZ,MAAM,6CAA6C,EACrEoB,GACF,CAAC;QACH,CAAC,MAAM;UACL;UACA;UACA;UACA,IAAI,CAAC3E,KAAK,CAACkF,OAAO,CAAC,GAAGf,KAAK,CAAC;UAC5BO,IAAI,CAACC,GAAY,CAAC;UAClBpG,MAAM,CAACuB,KAAK,CAAC,4CAA4C,EAAE6E,GAAG,CAAC;QACjE;;QAEA;QACA;QACA;QACA;QACA;QACA,IAAI,CAACd,aAAa,CAAC,CAAC;QACpB,MAAMc,GAAG;MACX;IACF,CAAC,SAAS;MACRT,YAAY,CAAE,CAAC;IACjB;EACF;;EAEA;AACF;AACA;AACA;AACA;EACUiB,gBAAgBA,CAAC3E,UAAkB,EAAQ;IACjD,IAAI,IAAI,CAACA,UAAU,KAAKA,UAAU,EAAE;MAClC,MAAMV,KAAgB,GAAG,IAAIsF,KAAK,CAChC,gDACF,CAAC;MACD;MACAtF,KAAK,CAACmF,SAAS,GAAG,KAAK;MACvB,MAAMnF,KAAK;IACb;EACF;;EAEA;AACF;AACA;EACE,MAAcgF,aAAaA,CACzBP,IAA+B,EAC/B/D,UAAkB,EAClB6E,OAAO,GAAG,CAAC,EACI;IACf,IAAI;MACF,MAAMC,QAAQ,GAAG,MAAMC,KAAK,CAAC,IAAI,CAAC1E,OAAO,EAAE;QACzC2E,MAAM,EAAE,MAAM;QACdC,OAAO,EAAEzH,yBAAyB,CAAC,IAAI,CAAC2C,QAAQ,CAAC;QACjD+E,IAAI,EAAEzD,IAAI,CAACC,SAAS,CAACqC,IAAI;MAC3B,CAAC,CAAC;MAEF,IAAI,CAACe,QAAQ,CAACK,EAAE,EAAE;QAChB,MAAMC,WAAW,GAAG,IAAI,CAACA,WAAW,CAACN,QAAQ,CAACO,MAAM,CAAC;QACrD,IAAID,WAAW,IAAIP,OAAO,GAAG,IAAI,CAACvE,UAAU,EAAE;UAC5C,MAAMgF,KAAK,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEX,OAAO,CAAC,GAAG,IAAI;UACzC,MAAM,IAAI1F,OAAO,CAAQC,OAAO,IAAKkE,UAAU,CAAC,MAAMlE,OAAO,CAAC,CAAC,EAAEkG,KAAK,CAAC,CAAC;UACxE,IAAI,CAACX,gBAAgB,CAAC3E,UAAU,CAAC;UACjC,OAAO,IAAI,CAACsE,aAAa,CAACP,IAAI,EAAE/D,UAAU,EAAE6E,OAAO,GAAG,CAAC,CAAC;QAC1D;QACA,MAAMvF,KAAgB,GAAG,IAAIsF,KAAK,CAChC,uBAAuBE,QAAQ,CAACO,MAAM,EACxC,CAAC;QACD;QACA;QACA;QACA/F,KAAK,CAACmF,SAAS,GAAGW,WAAW;QAC7B,MAAM9F,KAAK;MACb;IACF,CAAC,CAAC,OAAOA,KAAK,EAAE;MACd,IAAI1B,cAAc,CAAC0B,KAAK,CAAC,EAAE;QACzB,IAAIuF,OAAO,GAAG,IAAI,CAACvE,UAAU,EAAE;UAC7B,MAAMgF,KAAK,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEX,OAAO,CAAC,GAAG,IAAI;UACzC9G,MAAM,CAACmE,IAAI,CAAC,8BAA8BoD,KAAK,OAAO,CAAC;UACvD,MAAM,IAAInG,OAAO,CAAQC,OAAO,IAAKkE,UAAU,CAAC,MAAMlE,OAAO,CAAC,CAAC,EAAEkG,KAAK,CAAC,CAAC;UACxE,IAAI,CAACX,gBAAgB,CAAC3E,UAAU,CAAC;UACjC,OAAO,IAAI,CAACsE,aAAa,CAACP,IAAI,EAAE/D,UAAU,EAAE6E,OAAO,GAAG,CAAC,CAAC;QAC1D;QACA;QACCvF,KAAK,CAAemF,SAAS,GAAG,IAAI;MACvC;MACA,MAAMnF,KAAK;IACb;EACF;;EAEA;AACF;AACA;EACU8F,WAAWA,CAACC,MAAc,EAAW;IAC3C;IACA;IACA;IACA;IACA,OAAQA,MAAM,IAAI,GAAG,IAAIA,MAAM,IAAI,GAAG,IAAKA,MAAM,KAAK,GAAG,IAAIA,MAAM,KAAK,GAAG;EAC7E;;EAEA;AACF;AACA;AACA;AACA;EACSI,KAAKA,CAAA,EAAS;IACnB;IACA;IACA,IAAI,CAACzF,UAAU,EAAE;IACjB,IAAI,CAACR,KAAK,GAAG,EAAE;IACf,IAAI,CAACE,aAAa,CAAC+F,KAAK,CAAC,CAAC;IAE1B,IAAI,IAAI,CAAChG,KAAK,EAAE;MACd2D,YAAY,CAAC,IAAI,CAAC3D,KAAK,CAAC;MACxB,IAAI,CAACA,KAAK,GAAG,IAAI;IACnB;IAEA1B,MAAM,CAACiD,KAAK,CAAC,wCAAwC,CAAC;EACxD;;EAEA;AACF;AACA;AACA;EACU0E,mBAAmBA,CAACC,MAAc,EAAQ;IAChD5H,MAAM,CAACmE,IAAI,CACT,eAAeyD,MAAM,gBAAgB,IAAI,CAACnG,KAAK,CAACuD,MAAM,WACxD,CAAC;IACD;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,CAAC0C,KAAK,CAAC,CAAC;EACd;;EAEA;AACF;AACA;EACE,MAAaG,OAAOA,CAAA,EAAkB;IACpC;IACA;IACA,IAAI,CAAC,IAAI,CAAC3F,cAAc,EAAE;MACxB;MACA;MACA;MACA;MACA,IAAI,CAACA,cAAc,GAAG,IAAI,CAAC4F,UAAU,CAAC,CAAC,CAACxG,KAAK,CAAEC,KAAK,IAAK;QACvDvB,MAAM,CAACuB,KAAK,CAAC,4BAA4B,EAAEA,KAAK,CAAC;QACjD;QACA;QACA,IAAI,CAACmG,KAAK,CAAC,CAAC;MACd,CAAC,CAAC;IACJ;IACA,OAAO,IAAI,CAACxF,cAAc;EAC5B;EAEA,MAAc4F,UAAUA,CAAA,EAAkB;IACxC;IACA,IAAI,CAAC9F,MAAM,GAAG,IAAI;IAClB,IAAI,IAAI,CAACN,KAAK,EAAE;MACd2D,YAAY,CAAC,IAAI,CAAC3D,KAAK,CAAC;MACxB,IAAI,CAACA,KAAK,GAAG,IAAI;IACnB;;IAEA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAACI,oBAAoB,EAAE;MAC7B,IAAI;QACF,IAAI,CAACA,oBAAoB,CAACiG,MAAM,CAAC,CAAC;MACpC,CAAC,CAAC,OAAOxG,KAAK,EAAE;QACd;QACA;QACAvB,MAAM,CAACuB,KAAK,CAAC,gDAAgD,EAAEA,KAAK,CAAC;MACvE;MACA,IAAI,CAACO,oBAAoB,GAAG,IAAI;IAClC;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAIkG,aAAwD;IAC5D,MAAMC,QAAQ,GAAG,IAAI7G,OAAO,CAAaC,OAAO,IAAK;MACnD2G,aAAa,GAAGzC,UAAU,CAAC,MAAMlE,OAAO,CAAC,SAAS,CAAC,EAAEX,kBAAkB,CAAC;IAC1E,CAAC,CAAC;IACF,MAAMwH,cAAc,GAAOC,IAAgB,IACzC/G,OAAO,CAACgH,IAAI,CAAC,CAACD,IAAI,EAAEF,QAAQ,CAAC,CAAC;IAChC,MAAMI,QAAQ,GAAG,qBAAqBzI,oBAAoB,CACxDc,kBACF,CAAC,GAAG;IAEJ,IAAI;MACF;MACA;MACA;MACA;MACA;MACA,IACE,CAAC,MAAMwH,cAAc,CAAC,IAAI,CAACrG,UAAU,CAACV,IAAI,CAAC,MAAM,SAAkB,CAAC,CAAC,MACrE,SAAS,EACT;QACA,IAAI,CAACwG,mBAAmB,CAACU,QAAQ,CAAC;QAClC;MACF;;MAEA;MACA;MACA;MACA,MAAMC,WAAW,GAAGd,IAAI,CAACe,IAAI,CAAC,IAAI,CAAC9G,KAAK,CAACuD,MAAM,GAAG,IAAI,CAACxC,OAAO,CAAC,GAAG,CAAC;MACnE,IAAIgG,QAAQ,GAAG,CAAC;MAChB,MAAMC,kBAAkB,GAAG,IAAI,CAAChH,KAAK,CAACuD,MAAM;MAE5C,OAAO,IAAI,CAACvD,KAAK,CAACuD,MAAM,GAAG,CAAC,IAAIwD,QAAQ,GAAGF,WAAW,EAAE;QACtD,MAAMI,iBAAiB,GAAG,IAAI,CAACjH,KAAK,CAACuD,MAAM;QAE3C,MAAM2D,OAAO,GAAG,MAAMT,cAAc;QAClC;QACA;QACA,IAAI,CAAC1C,QAAQ,CAACoD,SAAS,EAAE,IAAI,CAAC,CAACzH,IAAI,CACjC,MAAM,SAAkB,EACvBI,KAAK,IAAK;UACTvB,MAAM,CAACuB,KAAK,CAAC,4CAA4C,EAAEA,KAAK,CAAC;UACjE,OAAO,QAAQ;QACjB,CACF,CACF,CAAC;QAED,IAAIoH,OAAO,KAAK,SAAS,EAAE;UACzB,IAAI,CAAChB,mBAAmB,CAACU,QAAQ,CAAC;UAClC;QACF;QACA;QACA,IAAIM,OAAO,KAAK,QAAQ,EAAE;;QAE1B;QACA,IAAI,IAAI,CAAClH,KAAK,CAACuD,MAAM,IAAI0D,iBAAiB,EAAE;UAC1C1I,MAAM,CAACmE,IAAI,CAAC,+DAA+D,CAAC;UAC5E;QACF;QAEAqE,QAAQ,EAAE;MACZ;MAEA,IAAIC,kBAAkB,GAAG,CAAC,EAAE;QAC1BzI,MAAM,CAACiD,KAAK,CAAC,0CAA0CwF,kBAAkB,GAAG,IAAI,CAAChH,KAAK,CAACuD,MAAM,SAAS,CAAC;MACzG;;MAEA;MACA;MACA;MACA;MACA;MACA;MACA,IAAI,IAAI,CAACvD,KAAK,CAACuD,MAAM,GAAG,CAAC,EAAE;QACzB,IAAI,CAAC2C,mBAAmB,CACtBa,QAAQ,IAAIF,WAAW,GACnB,8BAA8B,GAC9B,4CACN,CAAC;MACH;IACF,CAAC,SAAS;MACR,IAAIN,aAAa,EAAE3C,YAAY,CAAC2C,aAAa,CAAC;;MAE9C;MACA;MACA;MACA;MACA,IAAI,IAAI,CAACtG,KAAK,EAAE;QACd2D,YAAY,CAAC,IAAI,CAAC3D,KAAK,CAAC;QACxB,IAAI,CAACA,KAAK,GAAG,IAAI;MACnB;IACF;EACF;AACF","ignoreList":[]}