@dvina/sdk 4.0.215 → 4.0.220

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 (31) hide show
  1. package/dist/adapters/angular/index.cjs +4 -4
  2. package/dist/adapters/angular/index.d.cts +2 -2
  3. package/dist/adapters/angular/index.d.ts +2 -2
  4. package/dist/adapters/angular/index.js +2 -2
  5. package/dist/billing/index.cjs +5 -5
  6. package/dist/billing/index.js +1 -1
  7. package/dist/{chunk-BJDU4UX4.js → chunk-6PAEAOGQ.js} +508 -247
  8. package/dist/chunk-6PAEAOGQ.js.map +1 -0
  9. package/dist/{chunk-XK5PW7IX.cjs → chunk-CGJTK2BE.cjs} +531 -270
  10. package/dist/chunk-CGJTK2BE.cjs.map +1 -0
  11. package/dist/{chunk-Y4OD5SDF.cjs → chunk-VDPZQ5F3.cjs} +41 -6
  12. package/dist/chunk-VDPZQ5F3.cjs.map +1 -0
  13. package/dist/{chunk-Q5XGHH7D.js → chunk-ZGGY4WK7.js} +42 -5
  14. package/dist/chunk-ZGGY4WK7.js.map +1 -0
  15. package/dist/{client-Bn-0nJ8y.d.ts → client-C0CA6PHq.d.ts} +1 -1
  16. package/dist/{client-Ca2wlmC4.d.cts → client-XvsWJ1Z1.d.cts} +1 -1
  17. package/dist/{index-D50r0Gl0.d.ts → index-Bld5-Yr1.d.ts} +1 -1
  18. package/dist/{index-Ct2Mh0zl.d.cts → index-DF59UYzN.d.cts} +1 -1
  19. package/dist/index.cjs +387 -387
  20. package/dist/index.d.cts +6 -6
  21. package/dist/index.d.ts +6 -6
  22. package/dist/index.js +2 -2
  23. package/dist/pagination/index.d.cts +2 -2
  24. package/dist/pagination/index.d.ts +2 -2
  25. package/dist/{sync-engine-D35aV8Zc.d.ts → sync-engine-CZ0U9XBy.d.ts} +14 -9
  26. package/dist/{sync-engine-21OlgS5_.d.cts → sync-engine-DXESBFX0.d.cts} +14 -9
  27. package/package.json +1 -1
  28. package/dist/chunk-BJDU4UX4.js.map +0 -1
  29. package/dist/chunk-Q5XGHH7D.js.map +0 -1
  30. package/dist/chunk-XK5PW7IX.cjs.map +0 -1
  31. package/dist/chunk-Y4OD5SDF.cjs.map +0 -1
@@ -2,7 +2,7 @@
2
2
 
3
3
  var chunk342BFYZZ_cjs = require('./chunk-342BFYZZ.cjs');
4
4
  var chunkUELAE75E_cjs = require('./chunk-UELAE75E.cjs');
5
- var chunkY4OD5SDF_cjs = require('./chunk-Y4OD5SDF.cjs');
5
+ var chunkVDPZQ5F3_cjs = require('./chunk-VDPZQ5F3.cjs');
6
6
  var chunkKV5SP7RP_cjs = require('./chunk-KV5SP7RP.cjs');
7
7
  var chunk32A6N4YK_cjs = require('./chunk-32A6N4YK.cjs');
8
8
  var chunkDZUJEN5N_cjs = require('./chunk-DZUJEN5N.cjs');
@@ -6035,6 +6035,7 @@ var require_dexie = chunkDZUJEN5N_cjs.__commonJS({
6035
6035
  // src/chat-stream.ts
6036
6036
  var INITIAL_RECONNECT_DELAY_MS = 1e3;
6037
6037
  var MAX_RECONNECT_DELAY_MS = 3e4;
6038
+ var RECONNECT_BACKOFF_MULTIPLIER = 2;
6038
6039
  var MAX_CONSECUTIVE_AUTH_FAILURES = 3;
6039
6040
  var AuthChatStreamError = class extends Error {
6040
6041
  constructor(status) {
@@ -6048,63 +6049,24 @@ var ChatStreamConnection = class {
6048
6049
  this.chatId = chatId;
6049
6050
  this.options = options;
6050
6051
  this.onEmpty = onEmpty;
6051
- this.supervisor = new chunkY4OD5SDF_cjs.ConnectionSupervisor({
6052
- authRetryDelayMs: INITIAL_RECONNECT_DELAY_MS,
6053
- baseReconnectDelayMs: INITIAL_RECONNECT_DELAY_MS,
6054
- getToken: options.getToken,
6055
- id: chatId,
6056
- isAuthError: (error) => error instanceof AuthChatStreamError,
6057
- kind: "chat-sse",
6058
- maxConsecutiveAuthFailures: MAX_CONSECUTIVE_AUTH_FAILURES,
6059
- maxReconnectDelayMs: MAX_RECONNECT_DELAY_MS,
6060
- onFatalError: () => {
6061
- const authError = new chunkKV5SP7RP_cjs.DvinaAuthenticationError("Chat SSE stream authentication failed permanently");
6062
- this.options.onError?.(authError);
6063
- this.close(authError);
6064
- },
6065
- dial: async (context) => {
6066
- const url = new URL(`${this.options.baseUrl}/${encodeURIComponent(this.chatId)}/stream`);
6067
- if (this.lastEventId) {
6068
- url.searchParams.set("lastEventId", this.lastEventId);
6069
- }
6070
- const response = await fetch(url.toString(), {
6071
- method: "GET",
6072
- headers: {
6073
- Accept: "text/event-stream",
6074
- Authorization: `Bearer ${context.token}`,
6075
- "Cache-Control": "no-cache",
6076
- ...this.lastEventId ? { "Last-Event-ID": this.lastEventId } : {}
6077
- },
6078
- signal: context.signal
6079
- });
6080
- if (!response.ok) {
6081
- if (response.status === 401 || response.status === 403) {
6082
- throw new AuthChatStreamError(response.status);
6083
- }
6084
- throw new Error(`Chat stream connection failed: ${response.status} ${response.statusText}`);
6085
- }
6086
- if (!response.body) {
6087
- throw new Error("Chat stream response has no body");
6088
- }
6089
- context.markConnected();
6090
- await chunkY4OD5SDF_cjs.consumeSseStream(response.body, context.signal, {
6091
- onChunk: () => context.markActivity(),
6092
- onEventBlock: (block) => this.processEventBlock(block, context.requestTokenRefresh)
6093
- });
6094
- }
6095
- });
6096
6052
  }
6053
+ abortController;
6054
+ consecutiveAuthFailures = 0;
6097
6055
  destroyed = false;
6098
6056
  lastEventId;
6057
+ needsForceRefresh = false;
6058
+ reconnectDelay = INITIAL_RECONNECT_DELAY_MS;
6059
+ reconnectTimer;
6060
+ shouldReconnect = false;
6099
6061
  subscribers = /* @__PURE__ */ new Set();
6100
- supervisor;
6101
6062
  addSubscriber(subscriber) {
6102
6063
  if (this.destroyed) {
6103
6064
  throw new Error(`Chat stream '${this.chatId}' is closed`);
6104
6065
  }
6105
6066
  this.subscribers.add(subscriber);
6106
- if (this.subscribers.size === 1) {
6107
- void this.supervisor.start();
6067
+ if (!this.shouldReconnect) {
6068
+ this.shouldReconnect = true;
6069
+ void this.doConnect();
6108
6070
  }
6109
6071
  }
6110
6072
  removeSubscriber(subscriber) {
@@ -6114,17 +6076,30 @@ var ChatStreamConnection = class {
6114
6076
  }
6115
6077
  }
6116
6078
  reconnect() {
6117
- if (this.destroyed || this.subscribers.size === 0) {
6079
+ if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6118
6080
  return;
6119
6081
  }
6120
- this.supervisor.reconnect();
6082
+ if (this.reconnectTimer) {
6083
+ clearTimeout(this.reconnectTimer);
6084
+ this.reconnectTimer = void 0;
6085
+ }
6086
+ if (this.abortController) {
6087
+ this.abortController.abort();
6088
+ this.abortController = void 0;
6089
+ }
6090
+ void this.doConnect();
6121
6091
  }
6122
6092
  close(error) {
6123
- if (this.destroyed) {
6124
- return;
6125
- }
6093
+ this.shouldReconnect = false;
6126
6094
  this.destroyed = true;
6127
- this.supervisor.close();
6095
+ if (this.reconnectTimer) {
6096
+ clearTimeout(this.reconnectTimer);
6097
+ this.reconnectTimer = void 0;
6098
+ }
6099
+ if (this.abortController) {
6100
+ this.abortController.abort();
6101
+ this.abortController = void 0;
6102
+ }
6128
6103
  for (const subscriber of Array.from(this.subscribers)) {
6129
6104
  subscriber.finish(error);
6130
6105
  }
@@ -6134,7 +6109,94 @@ var ChatStreamConnection = class {
6134
6109
  get isDestroyed() {
6135
6110
  return this.destroyed;
6136
6111
  }
6137
- processEventBlock(block, requestTokenRefresh) {
6112
+ async doConnect() {
6113
+ if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6114
+ return;
6115
+ }
6116
+ this.abortController = new AbortController();
6117
+ try {
6118
+ const forceRefresh = this.needsForceRefresh;
6119
+ this.needsForceRefresh = false;
6120
+ const token = await this.options.getToken(forceRefresh ? { forceRefresh: true } : void 0);
6121
+ const url = new URL(`${this.options.baseUrl}/${encodeURIComponent(this.chatId)}/stream`);
6122
+ if (this.lastEventId) {
6123
+ url.searchParams.set("lastEventId", this.lastEventId);
6124
+ }
6125
+ const response = await fetch(url.toString(), {
6126
+ method: "GET",
6127
+ headers: {
6128
+ Accept: "text/event-stream",
6129
+ Authorization: `Bearer ${token}`,
6130
+ "Cache-Control": "no-cache",
6131
+ ...this.lastEventId ? { "Last-Event-ID": this.lastEventId } : {}
6132
+ },
6133
+ signal: this.abortController.signal
6134
+ });
6135
+ if (!response.ok) {
6136
+ if (response.status === 401 || response.status === 403) {
6137
+ throw new AuthChatStreamError(response.status);
6138
+ }
6139
+ throw new Error(`Chat stream connection failed: ${response.status} ${response.statusText}`);
6140
+ }
6141
+ if (!response.body) {
6142
+ throw new Error("Chat stream response has no body");
6143
+ }
6144
+ this.consecutiveAuthFailures = 0;
6145
+ this.reconnectDelay = INITIAL_RECONNECT_DELAY_MS;
6146
+ await this.parseSseStream(response.body, this.abortController.signal);
6147
+ } catch (error) {
6148
+ if (error.name === "AbortError") {
6149
+ return;
6150
+ }
6151
+ if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6152
+ return;
6153
+ }
6154
+ const isAuthError2 = error instanceof AuthChatStreamError;
6155
+ if (isAuthError2) {
6156
+ this.consecutiveAuthFailures += 1;
6157
+ if (this.consecutiveAuthFailures >= MAX_CONSECUTIVE_AUTH_FAILURES) {
6158
+ const authError = new chunkKV5SP7RP_cjs.DvinaAuthenticationError("Chat SSE stream authentication failed permanently");
6159
+ this.options.onError?.(authError);
6160
+ this.close(authError);
6161
+ return;
6162
+ }
6163
+ this.needsForceRefresh = true;
6164
+ }
6165
+ const delay = isAuthError2 ? INITIAL_RECONNECT_DELAY_MS : this.reconnectDelay;
6166
+ this.scheduleReconnect(delay);
6167
+ if (!isAuthError2) {
6168
+ this.reconnectDelay = Math.min(
6169
+ this.reconnectDelay * RECONNECT_BACKOFF_MULTIPLIER,
6170
+ MAX_RECONNECT_DELAY_MS
6171
+ );
6172
+ }
6173
+ }
6174
+ }
6175
+ async parseSseStream(body, signal) {
6176
+ const reader = body.getReader();
6177
+ const decoder = new TextDecoder();
6178
+ let buffer = "";
6179
+ try {
6180
+ while (!signal.aborted && this.shouldReconnect && !this.destroyed) {
6181
+ const { done, value } = await reader.read();
6182
+ if (done) {
6183
+ break;
6184
+ }
6185
+ buffer += decoder.decode(value, { stream: true });
6186
+ const parts = buffer.split(/(?:\r\n|\r|\n){2}/);
6187
+ buffer = parts.pop() ?? "";
6188
+ for (const part of parts) {
6189
+ this.processEventBlock(part.trim());
6190
+ }
6191
+ }
6192
+ } finally {
6193
+ reader.releaseLock();
6194
+ }
6195
+ if (this.shouldReconnect && !this.destroyed && this.subscribers.size > 0) {
6196
+ this.scheduleReconnect(this.reconnectDelay);
6197
+ }
6198
+ }
6199
+ processEventBlock(block) {
6138
6200
  if (!block || block.startsWith(":")) {
6139
6201
  return;
6140
6202
  }
@@ -6151,8 +6213,8 @@ var ChatStreamConnection = class {
6151
6213
  }
6152
6214
  }
6153
6215
  if (eventType === "token-expired") {
6154
- requestTokenRefresh();
6155
- throw new AuthChatStreamError(401);
6216
+ this.needsForceRefresh = true;
6217
+ return;
6156
6218
  }
6157
6219
  if (!eventId || dataLines.length === 0) {
6158
6220
  return;
@@ -6169,64 +6231,40 @@ var ChatStreamConnection = class {
6169
6231
  subscriber.push(value);
6170
6232
  }
6171
6233
  }
6234
+ scheduleReconnect(delay) {
6235
+ if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6236
+ return;
6237
+ }
6238
+ if (this.reconnectTimer) {
6239
+ clearTimeout(this.reconnectTimer);
6240
+ }
6241
+ this.reconnectTimer = setTimeout(() => {
6242
+ this.reconnectTimer = void 0;
6243
+ void this.doConnect();
6244
+ }, delay);
6245
+ }
6172
6246
  };
6173
6247
  var ActiveChatStreamConnection = class {
6174
6248
  constructor(options, onEmpty) {
6175
6249
  this.options = options;
6176
6250
  this.onEmpty = onEmpty;
6177
- this.supervisor = new chunkY4OD5SDF_cjs.ConnectionSupervisor({
6178
- authRetryDelayMs: INITIAL_RECONNECT_DELAY_MS,
6179
- baseReconnectDelayMs: INITIAL_RECONNECT_DELAY_MS,
6180
- getToken: options.getToken,
6181
- id: "active",
6182
- isAuthError: (error) => error instanceof AuthChatStreamError,
6183
- kind: "active-chat-sse",
6184
- maxConsecutiveAuthFailures: MAX_CONSECUTIVE_AUTH_FAILURES,
6185
- maxReconnectDelayMs: MAX_RECONNECT_DELAY_MS,
6186
- onFatalError: () => {
6187
- const authError = new chunkKV5SP7RP_cjs.DvinaAuthenticationError(
6188
- "Active chat SSE stream authentication failed permanently"
6189
- );
6190
- this.options.onError?.(authError);
6191
- this.close(authError);
6192
- },
6193
- dial: async (context) => {
6194
- const response = await fetch(new URL(`${this.options.baseUrl}/active`).toString(), {
6195
- method: "GET",
6196
- headers: {
6197
- Accept: "text/event-stream",
6198
- Authorization: `Bearer ${context.token}`,
6199
- "Cache-Control": "no-cache"
6200
- },
6201
- signal: context.signal
6202
- });
6203
- if (!response.ok) {
6204
- if (response.status === 401 || response.status === 403) {
6205
- throw new AuthChatStreamError(response.status);
6206
- }
6207
- throw new Error(`Active chat stream connection failed: ${response.status} ${response.statusText}`);
6208
- }
6209
- if (!response.body) {
6210
- throw new Error("Active chat stream response has no body");
6211
- }
6212
- context.markConnected();
6213
- await chunkY4OD5SDF_cjs.consumeSseStream(response.body, context.signal, {
6214
- onChunk: () => context.markActivity(),
6215
- onEventBlock: (block) => this.processEventBlock(block, context.requestTokenRefresh)
6216
- });
6217
- }
6218
- });
6219
6251
  }
6252
+ abortController;
6253
+ consecutiveAuthFailures = 0;
6220
6254
  destroyed = false;
6255
+ needsForceRefresh = false;
6256
+ reconnectDelay = INITIAL_RECONNECT_DELAY_MS;
6257
+ reconnectTimer;
6258
+ shouldReconnect = false;
6221
6259
  subscribers = /* @__PURE__ */ new Set();
6222
- supervisor;
6223
6260
  addSubscriber(subscriber) {
6224
6261
  if (this.destroyed) {
6225
6262
  throw new Error("Active chat stream is closed");
6226
6263
  }
6227
6264
  this.subscribers.add(subscriber);
6228
- if (this.subscribers.size === 1) {
6229
- void this.supervisor.start();
6265
+ if (!this.shouldReconnect) {
6266
+ this.shouldReconnect = true;
6267
+ void this.doConnect();
6230
6268
  }
6231
6269
  }
6232
6270
  removeSubscriber(subscriber) {
@@ -6236,17 +6274,30 @@ var ActiveChatStreamConnection = class {
6236
6274
  }
6237
6275
  }
6238
6276
  reconnect() {
6239
- if (this.destroyed || this.subscribers.size === 0) {
6277
+ if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6240
6278
  return;
6241
6279
  }
6242
- this.supervisor.reconnect();
6280
+ if (this.reconnectTimer) {
6281
+ clearTimeout(this.reconnectTimer);
6282
+ this.reconnectTimer = void 0;
6283
+ }
6284
+ if (this.abortController) {
6285
+ this.abortController.abort();
6286
+ this.abortController = void 0;
6287
+ }
6288
+ void this.doConnect();
6243
6289
  }
6244
6290
  close(error) {
6245
- if (this.destroyed) {
6246
- return;
6247
- }
6291
+ this.shouldReconnect = false;
6248
6292
  this.destroyed = true;
6249
- this.supervisor.close();
6293
+ if (this.reconnectTimer) {
6294
+ clearTimeout(this.reconnectTimer);
6295
+ this.reconnectTimer = void 0;
6296
+ }
6297
+ if (this.abortController) {
6298
+ this.abortController.abort();
6299
+ this.abortController = void 0;
6300
+ }
6250
6301
  for (const subscriber of Array.from(this.subscribers)) {
6251
6302
  subscriber.finish(error);
6252
6303
  }
@@ -6256,7 +6307,91 @@ var ActiveChatStreamConnection = class {
6256
6307
  get isDestroyed() {
6257
6308
  return this.destroyed;
6258
6309
  }
6259
- processEventBlock(block, requestTokenRefresh) {
6310
+ async doConnect() {
6311
+ if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6312
+ return;
6313
+ }
6314
+ this.abortController = new AbortController();
6315
+ try {
6316
+ const forceRefresh = this.needsForceRefresh;
6317
+ this.needsForceRefresh = false;
6318
+ const token = await this.options.getToken(forceRefresh ? { forceRefresh: true } : void 0);
6319
+ const response = await fetch(new URL(`${this.options.baseUrl}/active`).toString(), {
6320
+ method: "GET",
6321
+ headers: {
6322
+ Accept: "text/event-stream",
6323
+ Authorization: `Bearer ${token}`,
6324
+ "Cache-Control": "no-cache"
6325
+ },
6326
+ signal: this.abortController.signal
6327
+ });
6328
+ if (!response.ok) {
6329
+ if (response.status === 401 || response.status === 403) {
6330
+ throw new AuthChatStreamError(response.status);
6331
+ }
6332
+ throw new Error(`Active chat stream connection failed: ${response.status} ${response.statusText}`);
6333
+ }
6334
+ if (!response.body) {
6335
+ throw new Error("Active chat stream response has no body");
6336
+ }
6337
+ this.consecutiveAuthFailures = 0;
6338
+ this.reconnectDelay = INITIAL_RECONNECT_DELAY_MS;
6339
+ await this.parseSseStream(response.body, this.abortController.signal);
6340
+ } catch (error) {
6341
+ if (error.name === "AbortError") {
6342
+ return;
6343
+ }
6344
+ if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6345
+ return;
6346
+ }
6347
+ const isAuthError2 = error instanceof AuthChatStreamError;
6348
+ if (isAuthError2) {
6349
+ this.consecutiveAuthFailures += 1;
6350
+ if (this.consecutiveAuthFailures >= MAX_CONSECUTIVE_AUTH_FAILURES) {
6351
+ const authError = new chunkKV5SP7RP_cjs.DvinaAuthenticationError(
6352
+ "Active chat SSE stream authentication failed permanently"
6353
+ );
6354
+ this.options.onError?.(authError);
6355
+ this.close(authError);
6356
+ return;
6357
+ }
6358
+ this.needsForceRefresh = true;
6359
+ }
6360
+ const delay = isAuthError2 ? INITIAL_RECONNECT_DELAY_MS : this.reconnectDelay;
6361
+ this.scheduleReconnect(delay);
6362
+ if (!isAuthError2) {
6363
+ this.reconnectDelay = Math.min(
6364
+ this.reconnectDelay * RECONNECT_BACKOFF_MULTIPLIER,
6365
+ MAX_RECONNECT_DELAY_MS
6366
+ );
6367
+ }
6368
+ }
6369
+ }
6370
+ async parseSseStream(body, signal) {
6371
+ const reader = body.getReader();
6372
+ const decoder = new TextDecoder();
6373
+ let buffer = "";
6374
+ try {
6375
+ while (!signal.aborted && this.shouldReconnect && !this.destroyed) {
6376
+ const { done, value } = await reader.read();
6377
+ if (done) {
6378
+ break;
6379
+ }
6380
+ buffer += decoder.decode(value, { stream: true });
6381
+ const parts = buffer.split(/(?:\r\n|\r|\n){2}/);
6382
+ buffer = parts.pop() ?? "";
6383
+ for (const part of parts) {
6384
+ this.processEventBlock(part.trim());
6385
+ }
6386
+ }
6387
+ } finally {
6388
+ reader.releaseLock();
6389
+ }
6390
+ if (this.shouldReconnect && !this.destroyed && this.subscribers.size > 0) {
6391
+ this.scheduleReconnect(this.reconnectDelay);
6392
+ }
6393
+ }
6394
+ processEventBlock(block) {
6260
6395
  if (!block || block.startsWith(":")) {
6261
6396
  return;
6262
6397
  }
@@ -6270,8 +6405,8 @@ var ActiveChatStreamConnection = class {
6270
6405
  }
6271
6406
  }
6272
6407
  if (eventType === "token-expired") {
6273
- requestTokenRefresh();
6274
- throw new AuthChatStreamError(401);
6408
+ this.needsForceRefresh = true;
6409
+ return;
6275
6410
  }
6276
6411
  if (eventType !== "active" || dataLines.length === 0) {
6277
6412
  return;
@@ -6290,6 +6425,18 @@ var ActiveChatStreamConnection = class {
6290
6425
  subscriber.push(value);
6291
6426
  }
6292
6427
  }
6428
+ scheduleReconnect(delay) {
6429
+ if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6430
+ return;
6431
+ }
6432
+ if (this.reconnectTimer) {
6433
+ clearTimeout(this.reconnectTimer);
6434
+ }
6435
+ this.reconnectTimer = setTimeout(() => {
6436
+ this.reconnectTimer = void 0;
6437
+ void this.doConnect();
6438
+ }, delay);
6439
+ }
6293
6440
  };
6294
6441
  function createChatStreamClient(options) {
6295
6442
  const connections = /* @__PURE__ */ new Map();
@@ -7227,7 +7374,7 @@ function createWsTransport(options) {
7227
7374
  let nextToken;
7228
7375
  let currentToken;
7229
7376
  async function refreshToken() {
7230
- const token = await chunkY4OD5SDF_cjs.refreshTokenSingleFlight(options.getToken, currentToken);
7377
+ const token = await chunkVDPZQ5F3_cjs.refreshTokenSingleFlight(options.getToken, currentToken);
7231
7378
  if (!token) {
7232
7379
  throw new chunkKV5SP7RP_cjs.DvinaAuthenticationError("Token refresh did not produce a new token", currentToken);
7233
7380
  }
@@ -7279,7 +7426,7 @@ function createWsTransport(options) {
7279
7426
  }
7280
7427
  });
7281
7428
  function subscribe(document2, variables) {
7282
- const query = chunkY4OD5SDF_cjs.print(document2);
7429
+ const query = chunkVDPZQ5F3_cjs.print(document2);
7283
7430
  const subscribeOnce = () => ({
7284
7431
  [Symbol.asyncIterator]() {
7285
7432
  const queue = [];
@@ -7967,47 +8114,44 @@ var AuthSseError = class extends Error {
7967
8114
  };
7968
8115
  var INITIAL_RECONNECT_DELAY_MS2 = 1e3;
7969
8116
  var MAX_RECONNECT_DELAY_MS2 = 3e4;
8117
+ var RECONNECT_BACKOFF_MULTIPLIER2 = 2;
7970
8118
  var MAX_CONSECUTIVE_AUTH_FAILURES2 = 3;
7971
8119
  var SUBSCRIPTION_REFRESH_INTERVAL_MS = 5 * 60 * 1e3;
7972
- function mapSupervisorState(state) {
7973
- if (state === "connected") {
7974
- return "connected";
7975
- }
7976
- if (state === "connecting") {
7977
- return "connecting";
7978
- }
7979
- return "disconnected";
7980
- }
7981
8120
  function createSseTransport(options) {
8121
+ let abortController;
7982
8122
  let isConnected = false;
7983
- let currentLastSyncId;
8123
+ let reconnectDelay = INITIAL_RECONNECT_DELAY_MS2;
8124
+ let reconnectTimer;
7984
8125
  let refreshTimer;
8126
+ let shouldReconnect = false;
8127
+ let currentLastSyncId;
8128
+ let needsForceRefresh = false;
8129
+ let consecutiveAuthFailures = 0;
7985
8130
  let hasConnectedOnce = false;
7986
- let lastLegacyState;
7987
8131
  const activeSubscriptions = /* @__PURE__ */ new Map();
7988
- const emitLegacyState = (state) => {
7989
- const mapped = mapSupervisorState(state);
7990
- if (mapped === lastLegacyState) {
8132
+ async function connect(lastSyncId) {
8133
+ disconnect();
8134
+ shouldReconnect = true;
8135
+ currentLastSyncId = lastSyncId;
8136
+ await doConnect();
8137
+ }
8138
+ function reconnect() {
8139
+ const lastSyncId = currentLastSyncId;
8140
+ disconnect();
8141
+ shouldReconnect = true;
8142
+ currentLastSyncId = lastSyncId;
8143
+ void doConnect();
8144
+ }
8145
+ async function doConnect() {
8146
+ if (!shouldReconnect) {
7991
8147
  return;
7992
8148
  }
7993
- lastLegacyState = mapped;
7994
- isConnected = mapped === "connected";
7995
- if (!isConnected) {
7996
- stopSubscriptionRefresh();
7997
- }
7998
- options.onStateChange?.(mapped);
7999
- };
8000
- const supervisor = new chunkY4OD5SDF_cjs.ConnectionSupervisor({
8001
- authRetryDelayMs: INITIAL_RECONNECT_DELAY_MS2,
8002
- baseReconnectDelayMs: INITIAL_RECONNECT_DELAY_MS2,
8003
- getToken: options.getToken,
8004
- id: "primary",
8005
- isAuthError: (error) => error instanceof AuthSseError,
8006
- kind: "sync-sse",
8007
- maxConsecutiveAuthFailures: MAX_CONSECUTIVE_AUTH_FAILURES2,
8008
- maxReconnectDelayMs: MAX_RECONNECT_DELAY_MS2,
8009
- onStateChange: (snapshot) => emitLegacyState(snapshot.state),
8010
- dial: async (context) => {
8149
+ abortController = new AbortController();
8150
+ options.onStateChange?.("connecting");
8151
+ try {
8152
+ const forceRefresh = needsForceRefresh;
8153
+ needsForceRefresh = false;
8154
+ const token = await options.getToken(forceRefresh ? { forceRefresh: true } : void 0);
8011
8155
  const url = new URL(options.url);
8012
8156
  if (currentLastSyncId && currentLastSyncId !== "0") {
8013
8157
  url.searchParams.set("lastSyncId", currentLastSyncId);
@@ -8015,11 +8159,11 @@ function createSseTransport(options) {
8015
8159
  const response = await fetch(url.toString(), {
8016
8160
  method: "GET",
8017
8161
  headers: {
8018
- Authorization: `Bearer ${context.token}`,
8162
+ Authorization: `Bearer ${token}`,
8019
8163
  Accept: "text/event-stream",
8020
8164
  "Cache-Control": "no-cache"
8021
8165
  },
8022
- signal: context.signal
8166
+ signal: abortController.signal
8023
8167
  });
8024
8168
  if (!response.ok) {
8025
8169
  if (response.status === 401 || response.status === 403) {
@@ -8030,36 +8174,143 @@ function createSseTransport(options) {
8030
8174
  if (!response.body) {
8031
8175
  throw new Error("SSE response has no body");
8032
8176
  }
8177
+ isConnected = true;
8178
+ consecutiveAuthFailures = 0;
8179
+ reconnectDelay = INITIAL_RECONNECT_DELAY_MS2;
8180
+ options.onStateChange?.("connected");
8033
8181
  const isReconnect = hasConnectedOnce;
8034
8182
  hasConnectedOnce = true;
8035
- context.markConnected();
8036
- await syncActiveSubscriptions(context.token);
8183
+ await syncActiveSubscriptions(token);
8037
8184
  startSubscriptionRefresh();
8038
8185
  if (isReconnect && activeSubscriptions.size > 0) {
8039
8186
  options.onReconnect?.();
8040
8187
  }
8041
- await chunkY4OD5SDF_cjs.consumeSseStream(response.body, context.signal, {
8042
- onChunk: () => context.markActivity(),
8043
- onEventBlock: (block) => processEventBlock(block, context.requestTokenRefresh)
8044
- });
8188
+ await parseSseStream(response.body, abortController.signal);
8189
+ } catch (error) {
8190
+ if (error.name === "AbortError") {
8191
+ return;
8192
+ }
8193
+ isConnected = false;
8194
+ stopSubscriptionRefresh();
8195
+ options.onStateChange?.("disconnected");
8196
+ if (!shouldReconnect) {
8197
+ return;
8198
+ }
8199
+ const isAuthError2 = error instanceof AuthSseError;
8200
+ if (isAuthError2) {
8201
+ consecutiveAuthFailures += 1;
8202
+ if (consecutiveAuthFailures >= MAX_CONSECUTIVE_AUTH_FAILURES2) {
8203
+ disconnect();
8204
+ return;
8205
+ }
8206
+ needsForceRefresh = true;
8207
+ }
8208
+ const delay = isAuthError2 ? INITIAL_RECONNECT_DELAY_MS2 : reconnectDelay;
8209
+ reconnectTimer = setTimeout(() => {
8210
+ void doConnect();
8211
+ }, delay);
8212
+ if (!isAuthError2) {
8213
+ reconnectDelay = Math.min(reconnectDelay * RECONNECT_BACKOFF_MULTIPLIER2, MAX_RECONNECT_DELAY_MS2);
8214
+ }
8045
8215
  }
8046
- });
8047
- async function connect(lastSyncId) {
8048
- currentLastSyncId = lastSyncId;
8049
- disconnect();
8050
- await supervisor.start();
8051
8216
  }
8052
- function disconnect() {
8053
- supervisor.stop();
8217
+ async function parseSseStream(body, signal) {
8218
+ const reader = body.getReader();
8219
+ const decoder = new TextDecoder();
8220
+ let buffer = "";
8221
+ try {
8222
+ while (!signal.aborted) {
8223
+ const { done, value } = await reader.read();
8224
+ if (done) {
8225
+ break;
8226
+ }
8227
+ buffer += decoder.decode(value, { stream: true });
8228
+ const parts = buffer.split(/(?:\r\n|\r|\n){2}/);
8229
+ buffer = parts.pop() ?? "";
8230
+ for (const part of parts) {
8231
+ processEventBlock(part.trim());
8232
+ }
8233
+ }
8234
+ } finally {
8235
+ reader.releaseLock();
8236
+ }
8237
+ if (!shouldReconnect) {
8238
+ return;
8239
+ }
8054
8240
  isConnected = false;
8055
8241
  stopSubscriptionRefresh();
8056
- if (lastLegacyState !== "disconnected") {
8057
- lastLegacyState = "disconnected";
8058
- options.onStateChange?.("disconnected");
8242
+ options.onStateChange?.("disconnected");
8243
+ reconnectTimer = setTimeout(() => {
8244
+ void doConnect();
8245
+ }, reconnectDelay);
8246
+ }
8247
+ function processEventBlock(block) {
8248
+ if (!block || block.startsWith(":")) {
8249
+ return;
8250
+ }
8251
+ let eventId;
8252
+ let eventType;
8253
+ let eventData;
8254
+ for (const line of block.split(/\r\n|\r|\n/)) {
8255
+ if (line.startsWith("id: ")) {
8256
+ eventId = line.slice(4).trim();
8257
+ } else if (line.startsWith("event: ")) {
8258
+ eventType = line.slice(7).trim();
8259
+ } else if (line.startsWith("data: ")) {
8260
+ eventData = line.slice(6);
8261
+ }
8262
+ }
8263
+ if (eventType === "token-expired") {
8264
+ needsForceRefresh = true;
8265
+ return;
8266
+ }
8267
+ if (eventType === "full-resync") {
8268
+ options.onFullResync?.();
8269
+ return;
8270
+ }
8271
+ if ((eventType === "query-add" || eventType === "query-remove") && eventData) {
8272
+ try {
8273
+ const parsed = JSON.parse(eventData);
8274
+ options.onQueryEvent?.({
8275
+ type: eventType === "query-add" ? "add" : "remove",
8276
+ ...parsed
8277
+ });
8278
+ } catch {
8279
+ }
8280
+ return;
8281
+ }
8282
+ if (!eventId) {
8283
+ return;
8284
+ }
8285
+ currentLastSyncId = eventId;
8286
+ if (eventType === "cursor") {
8287
+ options.onCursor?.(eventId);
8288
+ return;
8289
+ }
8290
+ if (eventType === "sync" && eventData) {
8291
+ try {
8292
+ const parsed = JSON.parse(eventData);
8293
+ options.onEvent({
8294
+ id: eventId,
8295
+ ...parsed
8296
+ });
8297
+ } catch {
8298
+ }
8059
8299
  }
8060
8300
  }
8061
- function reconnect() {
8062
- supervisor.reconnect();
8301
+ function disconnect() {
8302
+ shouldReconnect = false;
8303
+ isConnected = false;
8304
+ stopSubscriptionRefresh();
8305
+ if (reconnectTimer) {
8306
+ clearTimeout(reconnectTimer);
8307
+ reconnectTimer = void 0;
8308
+ }
8309
+ if (abortController) {
8310
+ abortController.abort();
8311
+ abortController = void 0;
8312
+ }
8313
+ options.onStateChange?.("disconnected");
8063
8314
  }
8064
8315
  function subscribe(descriptor) {
8065
8316
  activeSubscriptions.set(descriptor.id, descriptor);
@@ -8120,61 +8371,7 @@ function createSseTransport(options) {
8120
8371
  if (response.status !== 401 && response.status !== 403) {
8121
8372
  return;
8122
8373
  }
8123
- resolvedToken = await chunkY4OD5SDF_cjs.refreshTokenSingleFlight(options.getToken, resolvedToken);
8124
- }
8125
- }
8126
- function processEventBlock(block, requestTokenRefresh) {
8127
- if (!block || block.startsWith(":")) {
8128
- return;
8129
- }
8130
- let eventId;
8131
- let eventType;
8132
- let eventData;
8133
- for (const line of block.split(/\r\n|\r|\n/)) {
8134
- if (line.startsWith("id: ")) {
8135
- eventId = line.slice(4).trim();
8136
- } else if (line.startsWith("event: ")) {
8137
- eventType = line.slice(7).trim();
8138
- } else if (line.startsWith("data: ")) {
8139
- eventData = line.slice(6);
8140
- }
8141
- }
8142
- if (eventType === "token-expired") {
8143
- requestTokenRefresh();
8144
- throw new AuthSseError(401);
8145
- }
8146
- if (eventType === "full-resync") {
8147
- options.onFullResync?.();
8148
- return;
8149
- }
8150
- if ((eventType === "query-add" || eventType === "query-remove") && eventData) {
8151
- try {
8152
- const parsed = JSON.parse(eventData);
8153
- options.onQueryEvent?.({
8154
- type: eventType === "query-add" ? "add" : "remove",
8155
- ...parsed
8156
- });
8157
- } catch {
8158
- }
8159
- return;
8160
- }
8161
- if (!eventId) {
8162
- return;
8163
- }
8164
- currentLastSyncId = eventId;
8165
- if (eventType === "cursor") {
8166
- options.onCursor?.(eventId);
8167
- return;
8168
- }
8169
- if (eventType === "sync" && eventData) {
8170
- try {
8171
- const parsed = JSON.parse(eventData);
8172
- options.onEvent({
8173
- id: eventId,
8174
- ...parsed
8175
- });
8176
- } catch {
8177
- }
8374
+ resolvedToken = await chunkVDPZQ5F3_cjs.refreshTokenSingleFlight(options.getToken, resolvedToken);
8178
8375
  }
8179
8376
  }
8180
8377
  return {
@@ -8812,9 +9009,12 @@ var CacheManager = class {
8812
9009
  */
8813
9010
  async invalidateQuery(operationName, variables) {
8814
9011
  const key = buildQueryKey(operationName, variables);
9012
+ await this.invalidateQueryKey(key);
9013
+ }
9014
+ async invalidateQueryKey(queryKey) {
8815
9015
  await this._db.transaction("rw", [this._db._queryResults, this._db._sync], async () => {
8816
- await this._db._queryResults.delete(key);
8817
- await this._db._sync.delete(getQueryFreshnessKey(key));
9016
+ await this._db._queryResults.delete(queryKey);
9017
+ await this._db._sync.delete(getQueryFreshnessKey(queryKey));
8818
9018
  });
8819
9019
  }
8820
9020
  /**
@@ -9509,6 +9709,7 @@ async function resolveRelationByReference(db, params) {
9509
9709
  }
9510
9710
 
9511
9711
  // src/store/sync-engine.ts
9712
+ var REVALIDATION_RETRY_DELAY_MS = 1e3;
9512
9713
  var SyncEngine = class {
9513
9714
  _db;
9514
9715
  _sse;
@@ -9525,6 +9726,8 @@ var SyncEngine = class {
9525
9726
  _subscriptionToQuery = /* @__PURE__ */ new Map();
9526
9727
  /** Last per-query revalidation timestamp to avoid refetch storms. */
9527
9728
  _lastRevalidatedAt = /* @__PURE__ */ new Map();
9729
+ /** Retry timers for recovery refetches that failed and need another attempt. */
9730
+ _revalidationRetryTimers = /* @__PURE__ */ new Map();
9528
9731
  /**
9529
9732
  * Last mutation/sync touch timestamp by entity type.
9530
9733
  * Used to detect stale cached query results on watch re-entry.
@@ -9562,27 +9765,24 @@ var SyncEngine = class {
9562
9765
  /**
9563
9766
  * Handle a full-resync signal from the server.
9564
9767
  *
9565
- * Clears all cached entities and query results, resets the sync cursor,
9566
- * then restarts the SSE connection so the client gets a fresh cursor.
9567
- * When SSE is available, active subscription-backed watchers are revalidated
9568
- * after the reconnect callback re-registers them with the server.
9569
- * Without SSE, revalidation happens immediately.
9768
+ * Clears all cached entities and query results, restarts delta sync, and
9769
+ * refetches active subscription-backed queries once so filtered connections
9770
+ * are rebuilt from source of truth instead of waiting for future delta events.
9570
9771
  */
9571
9772
  async handleFullResync() {
9572
9773
  this.stopSync();
9573
9774
  await this.clearAll();
9574
9775
  if (this._sse) {
9575
9776
  void this.startSync();
9576
- return;
9577
9777
  }
9578
9778
  await this._revalidateAllActiveSubscriptions();
9579
9779
  }
9580
9780
  /**
9581
- * Revalidate active subscription-backed queries after the SSE transport
9582
- * reconnects and re-registers them with the server.
9781
+ * Ordinary transport reconnects should recover from the sync cursor and
9782
+ * server-side subscription state without eagerly refetching every active query.
9583
9783
  */
9584
9784
  async handleTransportReconnect() {
9585
- await this._revalidateAllActiveSubscriptions();
9785
+ return;
9586
9786
  }
9587
9787
  /**
9588
9788
  * Process an incoming SSE sync event.
@@ -9645,8 +9845,15 @@ var SyncEngine = class {
9645
9845
  void this._revalidateSubscriptionIfStale(subscriptionDescriptor.id);
9646
9846
  const originalDispose = ref.dispose.bind(ref);
9647
9847
  ref.dispose = () => {
9848
+ const hasOtherActiveSubscription = this._hasOtherActiveSubscriptionForQueryKey(
9849
+ queryKey,
9850
+ subscriptionDescriptor.id
9851
+ );
9648
9852
  this._subscriptionToQueryKey.delete(subscriptionDescriptor.id);
9649
9853
  this._subscriptionToQuery.delete(subscriptionDescriptor.id);
9854
+ if (!hasOtherActiveSubscription) {
9855
+ this._clearRevalidationRetry(queryKey);
9856
+ }
9650
9857
  if (this._sse) {
9651
9858
  this._sse.unsubscribe(subscriptionDescriptor.id);
9652
9859
  }
@@ -9818,7 +10025,7 @@ var SyncEngine = class {
9818
10025
  if (!cached) return;
9819
10026
  const fetchedAt = await this._cache.getQueryFetchedAt(sub.queryKey, cached);
9820
10027
  if ((fetchedAt ?? cached.fetchedAt) >= touchedAt) return;
9821
- await this.query(sub.document, sub.variables, sub.operationName).catch(() => void 0);
10028
+ await this._revalidateSubscriptionQuery(sub, { force: true });
9822
10029
  }
9823
10030
  async _revalidateAllActiveSubscriptions() {
9824
10031
  await this._revalidateSubscriptions(Array.from(this._subscriptionToQuery.values()), { force: true });
@@ -9832,15 +10039,60 @@ var SyncEngine = class {
9832
10039
  pendingByQueryKey.set(sub.queryKey, sub);
9833
10040
  }
9834
10041
  if (pendingByQueryKey.size === 0) return;
9835
- for (const sub of pendingByQueryKey.values()) {
9836
- this._lastRevalidatedAt.set(sub.queryKey, now);
9837
- }
9838
10042
  await Promise.all(
9839
- Array.from(pendingByQueryKey.values()).map(
9840
- (sub) => this.query(sub.document, sub.variables, sub.operationName).catch(() => void 0)
9841
- )
10043
+ Array.from(pendingByQueryKey.values()).map((sub) => this._revalidateSubscriptionQuery(sub, options))
9842
10044
  );
9843
10045
  }
10046
+ async _revalidateSubscriptionQuery(subscription, options) {
10047
+ const startedAt = Date.now();
10048
+ this._lastRevalidatedAt.set(subscription.queryKey, startedAt);
10049
+ try {
10050
+ await this.query(subscription.document, subscription.variables, subscription.operationName);
10051
+ this._clearRevalidationRetry(subscription.queryKey);
10052
+ } catch {
10053
+ this._lastRevalidatedAt.delete(subscription.queryKey);
10054
+ await this._cache.invalidateQueryKey(subscription.queryKey).catch(() => void 0);
10055
+ if (options?.force || this._hasActiveSubscriptionForQueryKey(subscription.queryKey)) {
10056
+ this._scheduleRevalidationRetry(subscription.queryKey);
10057
+ }
10058
+ }
10059
+ }
10060
+ _scheduleRevalidationRetry(queryKey) {
10061
+ if (this._revalidationRetryTimers.has(queryKey)) {
10062
+ return;
10063
+ }
10064
+ const timer = setTimeout(() => {
10065
+ this._revalidationRetryTimers.delete(queryKey);
10066
+ const subscription = this._getActiveSubscriptionByQueryKey(queryKey);
10067
+ if (!subscription) {
10068
+ return;
10069
+ }
10070
+ void this._revalidateSubscriptionQuery(subscription, { force: true });
10071
+ }, REVALIDATION_RETRY_DELAY_MS);
10072
+ this._revalidationRetryTimers.set(queryKey, timer);
10073
+ }
10074
+ _clearRevalidationRetry(queryKey) {
10075
+ const timer = this._revalidationRetryTimers.get(queryKey);
10076
+ if (!timer) {
10077
+ return;
10078
+ }
10079
+ clearTimeout(timer);
10080
+ this._revalidationRetryTimers.delete(queryKey);
10081
+ }
10082
+ _getActiveSubscriptionByQueryKey(queryKey) {
10083
+ return Array.from(this._subscriptionToQuery.values()).find((sub) => sub.queryKey === queryKey);
10084
+ }
10085
+ _hasActiveSubscriptionForQueryKey(queryKey) {
10086
+ return this._getActiveSubscriptionByQueryKey(queryKey) !== void 0;
10087
+ }
10088
+ _hasOtherActiveSubscriptionForQueryKey(queryKey, subscriptionId) {
10089
+ for (const [activeSubscriptionId, subscription] of this._subscriptionToQuery.entries()) {
10090
+ if (activeSubscriptionId !== subscriptionId && subscription.queryKey === queryKey) {
10091
+ return true;
10092
+ }
10093
+ }
10094
+ return false;
10095
+ }
9844
10096
  _getActiveSubscriptionsForEntityType(entityType) {
9845
10097
  return Array.from(this._subscriptionToQuery.values()).filter((sub) => sub.entityType === entityType);
9846
10098
  }
@@ -10118,10 +10370,6 @@ function createLazySyncEngine(httpTransport, sseUrl, syncPolicyUrl, getToken, ge
10118
10370
  onFullResync: () => {
10119
10371
  realEngine?.handleFullResync().catch(() => {
10120
10372
  });
10121
- },
10122
- onReconnect: () => {
10123
- realEngine?.handleTransportReconnect().catch(() => {
10124
- });
10125
10373
  }
10126
10374
  });
10127
10375
  sseTransport = transport;
@@ -10378,6 +10626,9 @@ var DEFAULT_BASE_URL = "api.dvina.ai";
10378
10626
  var DB_INIT_TOKEN_POLL_INTERVAL_MS = 100;
10379
10627
  var DB_INIT_TOKEN_TIMEOUT_MS = 15e3;
10380
10628
  var LIFECYCLE_HINT_DEBOUNCE_MS = 250;
10629
+ function shouldRecoverConnections(hints) {
10630
+ return hints.has("network-restored") || hints.has("app-resumed");
10631
+ }
10381
10632
  function resolveGetToken(options) {
10382
10633
  if ("getToken" in options && options.getToken) {
10383
10634
  return options.getToken;
@@ -10427,7 +10678,7 @@ function createDvinaClient(options) {
10427
10678
  const getToken = resolveGetToken(options);
10428
10679
  const getLanguage = resolveLanguage(options.language);
10429
10680
  const getUserTimezone = resolveUserTimezone();
10430
- const httpTransport = chunkY4OD5SDF_cjs.createHttpTransport({
10681
+ const httpTransport = chunkVDPZQ5F3_cjs.createHttpTransport({
10431
10682
  url: httpUrl,
10432
10683
  getToken,
10433
10684
  getLanguage,
@@ -10486,19 +10737,29 @@ function createDvinaClient(options) {
10486
10737
  const billingBase = hasProtocol ? billingOverride.replace(/\/+$/, "") : `${httpProtocol}://${billingOverride ?? baseUrl.replace(/^api\./, "billing.")}`;
10487
10738
  const billingHttpUrl = `${billingBase}/graphql`;
10488
10739
  const billingSseUrl = `${billingBase}/subscriptions/stream`;
10489
- const billing = new chunkY4OD5SDF_cjs.BillingClient({ billingHttpUrl, billingSseUrl, getToken, onError: options.onError });
10740
+ const billing = new chunkVDPZQ5F3_cjs.BillingClient({ billingHttpUrl, billingSseUrl, getToken, onError: options.onError });
10490
10741
  let lifecycleHintTimer;
10742
+ const pendingLifecycleHints = /* @__PURE__ */ new Set();
10743
+ const recoverConnections = () => {
10744
+ recoverableSyncEngine.reconnectActiveSync();
10745
+ chatStream.reconnectAll();
10746
+ wsTransport?.terminate();
10747
+ billing.reconnectAll();
10748
+ };
10491
10749
  const lifecycle = {
10492
- hint(_reason) {
10750
+ hint(reason) {
10751
+ pendingLifecycleHints.add(reason);
10493
10752
  if (lifecycleHintTimer) {
10494
10753
  return;
10495
10754
  }
10496
10755
  lifecycleHintTimer = setTimeout(() => {
10497
10756
  lifecycleHintTimer = void 0;
10498
- recoverableSyncEngine.reconnectActiveSync();
10499
- chatStream.reconnectAll();
10500
- wsTransport?.terminate();
10501
- billing.reconnectAll();
10757
+ const hints = new Set(pendingLifecycleHints);
10758
+ pendingLifecycleHints.clear();
10759
+ if (!shouldRecoverConnections(hints)) {
10760
+ return;
10761
+ }
10762
+ recoverConnections();
10502
10763
  }, LIFECYCLE_HINT_DEBOUNCE_MS);
10503
10764
  }
10504
10765
  };
@@ -10819,7 +11080,7 @@ function buildSmartQuery(baseDocument, rootFieldName, includes, baseVariables, i
10819
11080
  }
10820
11081
  const doc = cloneDocument(baseDocument);
10821
11082
  const mergedVariables = { ...baseVariables };
10822
- const opDef = doc.definitions.find((d) => d.kind === chunkY4OD5SDF_cjs.Kind.OPERATION_DEFINITION);
11083
+ const opDef = doc.definitions.find((d) => d.kind === chunkVDPZQ5F3_cjs.Kind.OPERATION_DEFINITION);
10823
11084
  if (!opDef) {
10824
11085
  return { document: baseDocument, variables: baseVariables };
10825
11086
  }
@@ -10829,7 +11090,7 @@ function buildSmartQuery(baseDocument, rootFieldName, includes, baseVariables, i
10829
11090
  }
10830
11091
  const existingFragments = /* @__PURE__ */ new Set();
10831
11092
  for (const def of doc.definitions) {
10832
- if (def.kind === chunkY4OD5SDF_cjs.Kind.FRAGMENT_DEFINITION) {
11093
+ if (def.kind === chunkVDPZQ5F3_cjs.Kind.FRAGMENT_DEFINITION) {
10833
11094
  existingFragments.add(def.name.value);
10834
11095
  }
10835
11096
  }
@@ -10853,10 +11114,10 @@ function buildSmartQuery(baseDocument, rootFieldName, includes, baseVariables, i
10853
11114
  }
10854
11115
  if (isConnection && connectionIncludeFields.length > 0) {
10855
11116
  const nodesWrapper = {
10856
- kind: chunkY4OD5SDF_cjs.Kind.FIELD,
10857
- name: { kind: chunkY4OD5SDF_cjs.Kind.NAME, value: "nodes" },
11117
+ kind: chunkVDPZQ5F3_cjs.Kind.FIELD,
11118
+ name: { kind: chunkVDPZQ5F3_cjs.Kind.NAME, value: "nodes" },
10858
11119
  selectionSet: {
10859
- kind: chunkY4OD5SDF_cjs.Kind.SELECTION_SET,
11120
+ kind: chunkVDPZQ5F3_cjs.Kind.SELECTION_SET,
10860
11121
  selections: connectionIncludeFields
10861
11122
  }
10862
11123
  };
@@ -10870,14 +11131,14 @@ function buildSmartQuery(baseDocument, rootFieldName, includes, baseVariables, i
10870
11131
  function processIncludeDirective(include, prefix, opDef, mergedVariables, existingFragments, newDefinitions) {
10871
11132
  const fieldArgs = buildPrefixedArguments(include.fieldArguments ?? [], prefix);
10872
11133
  const fragmentDefs = include.fragmentDoc.definitions.filter(
10873
- (d) => d.kind === chunkY4OD5SDF_cjs.Kind.FRAGMENT_DEFINITION
11134
+ (d) => d.kind === chunkVDPZQ5F3_cjs.Kind.FRAGMENT_DEFINITION
10874
11135
  );
10875
11136
  const mainFragment = fragmentDefs[0];
10876
11137
  if (!mainFragment) return void 0;
10877
11138
  const selections = [
10878
11139
  {
10879
- kind: chunkY4OD5SDF_cjs.Kind.FRAGMENT_SPREAD,
10880
- name: { kind: chunkY4OD5SDF_cjs.Kind.NAME, value: mainFragment.name.value }
11140
+ kind: chunkVDPZQ5F3_cjs.Kind.FRAGMENT_SPREAD,
11141
+ name: { kind: chunkVDPZQ5F3_cjs.Kind.NAME, value: mainFragment.name.value }
10881
11142
  }
10882
11143
  ];
10883
11144
  if (include.children && include.children.length > 0) {
@@ -10899,10 +11160,10 @@ function processIncludeDirective(include, prefix, opDef, mergedVariables, existi
10899
11160
  if (childFields.length > 0) {
10900
11161
  if (include.isConnection) {
10901
11162
  const nodesWrapper = {
10902
- kind: chunkY4OD5SDF_cjs.Kind.FIELD,
10903
- name: { kind: chunkY4OD5SDF_cjs.Kind.NAME, value: "nodes" },
11163
+ kind: chunkVDPZQ5F3_cjs.Kind.FIELD,
11164
+ name: { kind: chunkVDPZQ5F3_cjs.Kind.NAME, value: "nodes" },
10904
11165
  selectionSet: {
10905
- kind: chunkY4OD5SDF_cjs.Kind.SELECTION_SET,
11166
+ kind: chunkVDPZQ5F3_cjs.Kind.SELECTION_SET,
10906
11167
  selections: childFields
10907
11168
  }
10908
11169
  };
@@ -10913,11 +11174,11 @@ function processIncludeDirective(include, prefix, opDef, mergedVariables, existi
10913
11174
  }
10914
11175
  }
10915
11176
  const includeField = {
10916
- kind: chunkY4OD5SDF_cjs.Kind.FIELD,
10917
- name: { kind: chunkY4OD5SDF_cjs.Kind.NAME, value: include.fieldName },
11177
+ kind: chunkVDPZQ5F3_cjs.Kind.FIELD,
11178
+ name: { kind: chunkVDPZQ5F3_cjs.Kind.NAME, value: include.fieldName },
10918
11179
  arguments: fieldArgs.length > 0 ? fieldArgs : void 0,
10919
11180
  selectionSet: {
10920
- kind: chunkY4OD5SDF_cjs.Kind.SELECTION_SET,
11181
+ kind: chunkVDPZQ5F3_cjs.Kind.SELECTION_SET,
10921
11182
  selections
10922
11183
  }
10923
11184
  };
@@ -10944,7 +11205,7 @@ function processIncludeDirective(include, prefix, opDef, mergedVariables, existi
10944
11205
  }
10945
11206
  function findFieldInSelectionSet(selectionSet, fieldName) {
10946
11207
  for (const selection of selectionSet.selections) {
10947
- if (selection.kind === chunkY4OD5SDF_cjs.Kind.FIELD && selection.name.value === fieldName) {
11208
+ if (selection.kind === chunkVDPZQ5F3_cjs.Kind.FIELD && selection.name.value === fieldName) {
10948
11209
  return selection;
10949
11210
  }
10950
11211
  }
@@ -10958,7 +11219,7 @@ function buildPrefixedArguments(args, prefix) {
10958
11219
  });
10959
11220
  }
10960
11221
  function prefixVariableReferences(node, prefix) {
10961
- if (node["kind"] === chunkY4OD5SDF_cjs.Kind.VARIABLE && typeof node["name"]?.["value"] === "string") {
11222
+ if (node["kind"] === chunkVDPZQ5F3_cjs.Kind.VARIABLE && typeof node["name"]?.["value"] === "string") {
10962
11223
  node["name"]["value"] = `${prefix}${node["name"]["value"]}`;
10963
11224
  return;
10964
11225
  }
@@ -10983,7 +11244,7 @@ function buildPrefixedVariableDefinitions(varDefs, prefix) {
10983
11244
  }
10984
11245
  function extractIncludeInfo(nestedDocument, nestedFieldName, parentVarNames) {
10985
11246
  const opDef = nestedDocument.definitions.find(
10986
- (d) => d.kind === chunkY4OD5SDF_cjs.Kind.OPERATION_DEFINITION
11247
+ (d) => d.kind === chunkVDPZQ5F3_cjs.Kind.OPERATION_DEFINITION
10987
11248
  );
10988
11249
  if (!opDef) {
10989
11250
  return { variableDefinitions: [], fieldArguments: [] };
@@ -10995,7 +11256,7 @@ function extractIncludeInfo(nestedDocument, nestedFieldName, parentVarNames) {
10995
11256
  let fieldArguments = [];
10996
11257
  function findNestedField(selectionSet) {
10997
11258
  for (const sel of selectionSet.selections) {
10998
- if (sel.kind === chunkY4OD5SDF_cjs.Kind.FIELD) {
11259
+ if (sel.kind === chunkVDPZQ5F3_cjs.Kind.FIELD) {
10999
11260
  if (sel.name.value === nestedFieldName && sel.arguments) {
11000
11261
  fieldArguments = sel.arguments;
11001
11262
  return;
@@ -23060,5 +23321,5 @@ exports.getOrCreateDatabase = getOrCreateDatabase;
23060
23321
  exports.reconstructConnectionNodes = reconstructConnectionNodes;
23061
23322
  exports.reconstructEntity = reconstructEntity;
23062
23323
  exports.uploadFile = uploadFile;
23063
- //# sourceMappingURL=chunk-XK5PW7IX.cjs.map
23064
- //# sourceMappingURL=chunk-XK5PW7IX.cjs.map
23324
+ //# sourceMappingURL=chunk-CGJTK2BE.cjs.map
23325
+ //# sourceMappingURL=chunk-CGJTK2BE.cjs.map