@timardex/cluemart-shared 1.7.0 → 1.7.1

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 (145) hide show
  1. package/dist/ad-BUYzE6zx.d.ts +181 -0
  2. package/dist/ad-BhLoEul3.d.mts +181 -0
  3. package/dist/affiliate-BbtjeUP4.d.mts +73 -0
  4. package/dist/affiliate-C51nzKsw.d.ts +73 -0
  5. package/dist/apollo/index.cjs +1383 -0
  6. package/dist/apollo/index.cjs.map +1 -0
  7. package/dist/apollo/index.d.mts +323 -0
  8. package/dist/apollo/index.d.ts +323 -0
  9. package/dist/apollo/index.mjs +1295 -0
  10. package/dist/apollo/index.mjs.map +1 -0
  11. package/dist/auth/index.cjs +1727 -0
  12. package/dist/auth/index.cjs.map +1 -0
  13. package/dist/auth/index.d.mts +166 -0
  14. package/dist/auth/index.d.ts +166 -0
  15. package/dist/auth/index.mjs +380 -0
  16. package/dist/auth/index.mjs.map +1 -0
  17. package/dist/chunk-32MKHJTX.mjs +1207 -0
  18. package/dist/chunk-32MKHJTX.mjs.map +1 -0
  19. package/dist/{chunk-RKIRWZCH.mjs → chunk-AYO3E4DM.mjs} +39 -183
  20. package/dist/chunk-AYO3E4DM.mjs.map +1 -0
  21. package/dist/{chunk-ZZJSCYJK.mjs → chunk-BIJ5NDXW.mjs} +46 -42
  22. package/dist/chunk-BIJ5NDXW.mjs.map +1 -0
  23. package/dist/chunk-DQ7ZHIXW.mjs +26 -0
  24. package/dist/chunk-DQ7ZHIXW.mjs.map +1 -0
  25. package/dist/{chunk-MVQ3CFQR.mjs → chunk-ILILH7E2.mjs} +12 -23
  26. package/dist/chunk-ILILH7E2.mjs.map +1 -0
  27. package/dist/{chunk-TAECMXM4.mjs → chunk-LBEJECG3.mjs} +249 -219
  28. package/dist/{chunk-TAECMXM4.mjs.map → chunk-LBEJECG3.mjs.map} +1 -1
  29. package/dist/{chunk-HZMP7GXC.mjs → chunk-R6PCFOYO.mjs} +949 -2629
  30. package/dist/chunk-R6PCFOYO.mjs.map +1 -0
  31. package/dist/chunk-RAYUJODN.mjs +45 -0
  32. package/dist/chunk-RAYUJODN.mjs.map +1 -0
  33. package/dist/chunk-SD42WIMV.mjs +297 -0
  34. package/dist/chunk-SD42WIMV.mjs.map +1 -0
  35. package/dist/chunk-VPANTTZI.mjs +262 -0
  36. package/dist/chunk-VPANTTZI.mjs.map +1 -0
  37. package/dist/{chunk-KZTOISPA.mjs → chunk-X3OLM35T.mjs} +14 -8
  38. package/dist/chunk-X3OLM35T.mjs.map +1 -0
  39. package/dist/{contactUs-H7799pWe.d.ts → contactUs--NoohZBu.d.ts} +1 -1
  40. package/dist/{contactUs-DGrDzJaM.d.mts → contactUs-CBWzefUS.d.mts} +1 -1
  41. package/dist/enums/index.cjs +13 -7
  42. package/dist/enums/index.cjs.map +1 -1
  43. package/dist/enums/index.d.mts +15 -9
  44. package/dist/enums/index.d.ts +15 -9
  45. package/dist/enums/index.mjs +1 -1
  46. package/dist/formFields/index.cjs +136 -73
  47. package/dist/formFields/index.cjs.map +1 -1
  48. package/dist/formFields/index.d.mts +3 -2
  49. package/dist/formFields/index.d.ts +3 -2
  50. package/dist/formFields/index.mjs +9 -4
  51. package/dist/{global-fKbMmluy.d.ts → global-CUYYxpy2.d.ts} +12 -11
  52. package/dist/{global-BUUfmCo7.d.mts → global-DePDtOFt.d.mts} +12 -11
  53. package/dist/graphql/index.cjs +694 -1251
  54. package/dist/graphql/index.cjs.map +1 -1
  55. package/dist/graphql/index.d.mts +423 -173
  56. package/dist/graphql/index.d.ts +423 -173
  57. package/dist/graphql/index.mjs +33 -21
  58. package/dist/hooks/index.cjs +937 -307
  59. package/dist/hooks/index.cjs.map +1 -1
  60. package/dist/hooks/index.d.mts +10 -4
  61. package/dist/hooks/index.d.ts +10 -4
  62. package/dist/hooks/index.mjs +170 -58
  63. package/dist/hooks/index.mjs.map +1 -1
  64. package/dist/images/apple-maps-icon.webp.d.ts +8 -1
  65. package/dist/images/banner-horizontal.webp.d.ts +8 -1
  66. package/dist/images/banner-vertical.webp.d.ts +8 -1
  67. package/dist/images/cluiTui.webp.d.ts +8 -1
  68. package/dist/images/corporate.webp.d.ts +8 -1
  69. package/dist/images/facebook.webp.d.ts +8 -1
  70. package/dist/images/gazebo-top.webp.d.ts +8 -1
  71. package/dist/images/google-maps-icon.webp.d.ts +8 -1
  72. package/dist/images/googleMaps-logo-dark.webp.d.ts +8 -1
  73. package/dist/images/googleMaps-logo-light.webp.d.ts +8 -1
  74. package/dist/images/instagram.webp.d.ts +8 -1
  75. package/dist/images/logo-atr.webp.d.ts +8 -1
  76. package/dist/images/logo-dark.webp.d.ts +8 -1
  77. package/dist/images/logo.webp.d.ts +8 -1
  78. package/dist/images/meet.webp.d.ts +8 -1
  79. package/dist/images/mini-market1.webp.d.ts +8 -1
  80. package/dist/images/mini-market2.webp.d.ts +8 -1
  81. package/dist/images/mini-market3.webp.d.ts +8 -1
  82. package/dist/images/mini-market4.webp.d.ts +8 -1
  83. package/dist/images/mini-market5.webp.d.ts +8 -1
  84. package/dist/images/poll.webp.d.ts +8 -1
  85. package/dist/images/poster1.webp.d.ts +8 -1
  86. package/dist/images/poster2.webp.d.ts +8 -1
  87. package/dist/images/poster3.webp.d.ts +8 -1
  88. package/dist/images/poster4.webp.d.ts +8 -1
  89. package/dist/images/private.webp.d.ts +8 -1
  90. package/dist/images/qr-code.webp.d.ts +8 -1
  91. package/dist/images/school.webp.d.ts +8 -1
  92. package/dist/images/sima.webp.d.ts +8 -1
  93. package/dist/images/store-android.webp.d.ts +8 -1
  94. package/dist/images/store-ios.webp.d.ts +8 -1
  95. package/dist/images/tablas.webp.d.ts +8 -1
  96. package/dist/images/telefonos.webp.d.ts +8 -1
  97. package/dist/images/tiktok.webp.d.ts +8 -1
  98. package/dist/images/tip.webp.d.ts +8 -1
  99. package/dist/images/ugralos.webp.d.ts +8 -1
  100. package/dist/images/waze-maps-icon.webp.d.ts +8 -1
  101. package/dist/images/website.webp.d.ts +8 -1
  102. package/dist/images/youtube.webp.d.ts +8 -1
  103. package/dist/index.cjs +1655 -1705
  104. package/dist/index.cjs.map +1 -1
  105. package/dist/index.d.mts +654 -240
  106. package/dist/index.d.ts +654 -240
  107. package/dist/index.mjs +1617 -1704
  108. package/dist/index.mjs.map +1 -1
  109. package/dist/map/index.cjs +14 -9
  110. package/dist/map/index.cjs.map +1 -1
  111. package/dist/map/index.d.mts +16 -13
  112. package/dist/map/index.d.ts +16 -13
  113. package/dist/map/index.mjs +14 -9
  114. package/dist/map/index.mjs.map +1 -1
  115. package/dist/{resourceActivities-BL_12IAo.d.ts → resourceActivities-CMUcn2P7.d.ts} +9 -4
  116. package/dist/{resourceActivities-zczOntNk.d.mts → resourceActivities-CwbJFGIp.d.mts} +9 -4
  117. package/dist/sharing/index.cjs +39 -1252
  118. package/dist/sharing/index.cjs.map +1 -1
  119. package/dist/sharing/index.d.mts +17 -5
  120. package/dist/sharing/index.d.ts +17 -5
  121. package/dist/sharing/index.mjs +34 -30
  122. package/dist/subscription-BU8GvH2K.d.ts +12 -0
  123. package/dist/subscription-bmAdrnfi.d.mts +12 -0
  124. package/dist/types/index.cjs +15 -2
  125. package/dist/types/index.cjs.map +1 -1
  126. package/dist/types/index.d.mts +10 -23
  127. package/dist/types/index.d.ts +10 -23
  128. package/dist/types/index.mjs +9 -5
  129. package/dist/user-D47MLFyH.d.ts +134 -0
  130. package/dist/user-DE8edl3u.d.mts +134 -0
  131. package/dist/utils/index.cjs +355 -136
  132. package/dist/utils/index.cjs.map +1 -1
  133. package/dist/utils/index.d.mts +87 -35
  134. package/dist/utils/index.d.ts +87 -35
  135. package/dist/utils/index.mjs +42 -15
  136. package/package.json +31 -10
  137. package/dist/ad-CVkVX_z5.d.ts +0 -296
  138. package/dist/ad-DA9ECAhK.d.mts +0 -296
  139. package/dist/affiliate-1RtkLnLP.d.ts +0 -35
  140. package/dist/affiliate-Cos2Syz5.d.mts +0 -35
  141. package/dist/chunk-HZMP7GXC.mjs.map +0 -1
  142. package/dist/chunk-KZTOISPA.mjs.map +0 -1
  143. package/dist/chunk-MVQ3CFQR.mjs.map +0 -1
  144. package/dist/chunk-RKIRWZCH.mjs.map +0 -1
  145. package/dist/chunk-ZZJSCYJK.mjs.map +0 -1
@@ -0,0 +1,1295 @@
1
+ import {
2
+ isTransientNetworkError
3
+ } from "../chunk-RAYUJODN.mjs";
4
+
5
+ // src/apollo/createApolloManager.ts
6
+ function createApolloManager(adapters = {}) {
7
+ const { onAuthRecoveryEvent } = adapters;
8
+ let resetClientFn = null;
9
+ let pendingReset = false;
10
+ return {
11
+ resetClient() {
12
+ if (!resetClientFn) {
13
+ pendingReset = true;
14
+ return;
15
+ }
16
+ pendingReset = false;
17
+ onAuthRecoveryEvent?.({ type: "reset_client" });
18
+ resetClientFn();
19
+ },
20
+ setResetClient(fn) {
21
+ resetClientFn = fn;
22
+ if (fn && pendingReset) {
23
+ pendingReset = false;
24
+ onAuthRecoveryEvent?.({ type: "reset_client" });
25
+ fn();
26
+ }
27
+ }
28
+ };
29
+ }
30
+
31
+ // src/apollo/createAuthLink.ts
32
+ import { ApolloLink, Observable } from "@apollo/client";
33
+ function maskedTokenInfo(token) {
34
+ const len = token.length;
35
+ const start = token.slice(0, 4);
36
+ const end = token.slice(-4);
37
+ return { end, len, start };
38
+ }
39
+ function createAuthLink(adapters) {
40
+ const { awaitReady, getAccessToken, onError: onError3, onDebug } = adapters;
41
+ return new ApolloLink((operation, forward) => {
42
+ return new Observable((observer) => {
43
+ let innerSub = null;
44
+ let closed = false;
45
+ const teardown = () => {
46
+ closed = true;
47
+ innerSub?.unsubscribe();
48
+ innerSub = null;
49
+ };
50
+ void (async () => {
51
+ if (awaitReady) {
52
+ try {
53
+ await awaitReady();
54
+ } catch (err) {
55
+ onError3?.(err, { action: "awaitReady" });
56
+ }
57
+ }
58
+ if (closed) return;
59
+ const token = await getAccessToken();
60
+ if (token) {
61
+ operation.setContext(({ headers = {} }) => {
62
+ const hasAuthHeader = Object.hasOwn(headers, "Authorization") || Object.hasOwn(headers, "authorization");
63
+ if (hasAuthHeader) {
64
+ onDebug?.("Preserving existing Authorization header", {
65
+ operationName: operation.operationName
66
+ });
67
+ return { headers };
68
+ }
69
+ return {
70
+ headers: {
71
+ ...headers,
72
+ Authorization: `Bearer ${token}`
73
+ }
74
+ };
75
+ });
76
+ onDebug?.("Attached Authorization header", {
77
+ operationName: operation.operationName,
78
+ token: maskedTokenInfo(token)
79
+ });
80
+ } else {
81
+ onDebug?.("Proceeding without Authorization header", {
82
+ operationName: operation.operationName
83
+ });
84
+ }
85
+ if (closed) return;
86
+ try {
87
+ innerSub = forward(operation).subscribe({
88
+ complete: () => {
89
+ if (!closed) observer.complete();
90
+ },
91
+ error: (error) => {
92
+ if (!closed) observer.error(error);
93
+ },
94
+ next: (result) => {
95
+ if (!closed) observer.next(result);
96
+ }
97
+ });
98
+ } catch (err) {
99
+ if (closed) return;
100
+ onError3?.(err, { action: "forward" });
101
+ observer.error(err);
102
+ }
103
+ })();
104
+ return teardown;
105
+ });
106
+ });
107
+ }
108
+
109
+ // src/apollo/createErrorLink.ts
110
+ import { Observable as Observable2 } from "@apollo/client";
111
+ import { onError } from "@apollo/client/link/error";
112
+
113
+ // src/apollo/readErrorResponseFields.ts
114
+ function readErrorResponseFields(errorResponse) {
115
+ const record = errorResponse;
116
+ return {
117
+ graphQLErrors: record["graphQLErrors"],
118
+ networkError: record["networkError"],
119
+ response: record["response"]
120
+ };
121
+ }
122
+
123
+ // src/apollo/unauthHelpers.ts
124
+ function getStatusCode(networkError) {
125
+ const anyErr = networkError;
126
+ const status = anyErr?.["statusCode"] ?? anyErr?.["status"] ?? anyErr?.["response"]?.status;
127
+ return typeof status === "number" ? status : null;
128
+ }
129
+ function isUnauthenticatedGraphQLError(graphQLErrors) {
130
+ return Boolean(
131
+ graphQLErrors?.some(
132
+ (err) => err.extensions?.code === "UNAUTHENTICATED" || err.message?.includes("You must be logged in.")
133
+ )
134
+ );
135
+ }
136
+ function isUnauthenticatedError(input) {
137
+ const statusCode = input.networkError ? getStatusCode(input.networkError) : null;
138
+ return isUnauthenticatedGraphQLError(input.graphQLErrors) || statusCode === 401 || statusCode === 403;
139
+ }
140
+ var NON_RETRYABLE_REFRESH_AUTH_CODES = /* @__PURE__ */ new Set(["FORBIDDEN", "TOKEN_EXPIRED", "UNAUTHENTICATED"]);
141
+ var REFRESH_AUTH_FAILURE_MESSAGE_PATTERNS = [
142
+ /invalid.*refresh token/i,
143
+ /jwt expired/i,
144
+ /jwt malformed/i,
145
+ /invalid signature/i
146
+ ];
147
+ function isRefreshAuthFailureMessage(message) {
148
+ if (!message) return false;
149
+ return REFRESH_AUTH_FAILURE_MESSAGE_PATTERNS.some(
150
+ (pattern) => pattern.test(message)
151
+ );
152
+ }
153
+ function getRefreshErrorCode(errors) {
154
+ for (const err of errors) {
155
+ const code = err.extensions?.code;
156
+ if (typeof code === "string") return code;
157
+ }
158
+ return void 0;
159
+ }
160
+ function isExpectedRefreshAuthFailure(errors, errorCode) {
161
+ if (errorCode != null && NON_RETRYABLE_REFRESH_AUTH_CODES.has(errorCode)) {
162
+ return true;
163
+ }
164
+ return errors.some((err) => isRefreshAuthFailureMessage(err.message));
165
+ }
166
+ function refreshGraphqlErrorsWarrantRetry(errors) {
167
+ if (errors.some(
168
+ (e) => e.extensions != null && e.extensions.retryable === true
169
+ )) {
170
+ return true;
171
+ }
172
+ for (const err of errors) {
173
+ if (isRefreshAuthFailureMessage(err.message)) {
174
+ return false;
175
+ }
176
+ const code = err.extensions?.code;
177
+ if (typeof code === "string" && NON_RETRYABLE_REFRESH_AUTH_CODES.has(code)) {
178
+ return false;
179
+ }
180
+ }
181
+ return true;
182
+ }
183
+ function decideRefreshNextStep(result) {
184
+ if (!result.token && !result.retryable) {
185
+ if (result.hadRefreshToken === false) return { kind: "complete" };
186
+ return { kind: "logout" };
187
+ }
188
+ if (!result.token) return { kind: "complete" };
189
+ return { kind: "retry", token: result.token };
190
+ }
191
+
192
+ // src/apollo/createErrorLink.ts
193
+ function handleRetryableRefreshFailure(observer) {
194
+ if (!observer.isClosed()) observer.complete();
195
+ }
196
+ function retryOperationWithToken(operation, forward, token, observer, setInnerSubscriber) {
197
+ operation.setContext(({ headers = {} }) => ({
198
+ __authRetryAttempted: true,
199
+ headers: {
200
+ ...headers,
201
+ Authorization: `Bearer ${token}`
202
+ }
203
+ }));
204
+ if (observer.isClosed()) return;
205
+ setInnerSubscriber(
206
+ forward(operation).subscribe({
207
+ complete: () => {
208
+ if (!observer.isClosed()) observer.complete();
209
+ },
210
+ error: (error) => {
211
+ if (!observer.isClosed()) observer.error(error);
212
+ },
213
+ next: (value) => {
214
+ if (!observer.isClosed()) observer.next(value);
215
+ }
216
+ })
217
+ );
218
+ }
219
+ function createErrorLink(adapters) {
220
+ const {
221
+ refreshAccessToken,
222
+ clearAccessToken,
223
+ logout,
224
+ onError: reportError,
225
+ onDebug,
226
+ onAuthRecoveryEvent
227
+ } = adapters;
228
+ function scheduleSessionLogout(reason) {
229
+ onAuthRecoveryEvent?.({ reason, type: "logout_scheduled" });
230
+ setTimeout(() => {
231
+ void logout();
232
+ }, 0);
233
+ }
234
+ async function handleTerminalRefreshFailure(observer) {
235
+ clearAccessToken?.("refresh_failed");
236
+ if (!observer.isClosed()) observer.complete();
237
+ scheduleSessionLogout("refresh_failed");
238
+ }
239
+ async function handleRefreshResult(result, operation, forward, observer, setInnerSubscriber) {
240
+ const decision = decideRefreshNextStep(result);
241
+ if (decision.kind === "logout") {
242
+ await handleTerminalRefreshFailure(observer);
243
+ return;
244
+ }
245
+ if (decision.kind === "complete") {
246
+ handleRetryableRefreshFailure(observer);
247
+ return;
248
+ }
249
+ retryOperationWithToken(
250
+ operation,
251
+ forward,
252
+ decision.token,
253
+ observer,
254
+ setInnerSubscriber
255
+ );
256
+ }
257
+ async function recoverFromAuthError(operation, forward, authContext, observer, setInnerSubscriber) {
258
+ const ctx = operation.getContext();
259
+ if (ctx.__authRetryAttempted) {
260
+ onDebug?.("Auth retry suppressed (already retried)", {
261
+ operationName: operation.operationName,
262
+ statusCode: authContext.statusCode
263
+ });
264
+ if (!observer.isClosed()) {
265
+ observer.error(
266
+ new Error(
267
+ `Auth failed after retry (status ${authContext.statusCode ?? "unknown"})`
268
+ )
269
+ );
270
+ }
271
+ return;
272
+ }
273
+ onDebug?.("Auth error detected; attempting refresh", {
274
+ operationName: operation.operationName,
275
+ statusCode: authContext.statusCode
276
+ });
277
+ const result = await refreshAccessToken();
278
+ if (observer.isClosed()) return;
279
+ await handleRefreshResult(
280
+ result,
281
+ operation,
282
+ forward,
283
+ observer,
284
+ setInnerSubscriber
285
+ );
286
+ }
287
+ async function handleAuthRecoveryError(err, observer) {
288
+ reportError?.(err, { action: "tokenRefresh" });
289
+ console.error("Token refresh failed", err);
290
+ clearAccessToken?.("refresh_exception");
291
+ if (!observer.isClosed()) observer.complete();
292
+ scheduleSessionLogout("refresh_exception");
293
+ }
294
+ return onError((errorResponse) => {
295
+ const { operation, forward } = errorResponse;
296
+ const { graphQLErrors, networkError } = readErrorResponseFields(errorResponse);
297
+ if (!isUnauthenticatedError({
298
+ graphQLErrors,
299
+ networkError
300
+ })) {
301
+ return;
302
+ }
303
+ const statusCode = networkError ? getStatusCode(networkError) : null;
304
+ const authContext = {
305
+ graphQLErrors,
306
+ networkError,
307
+ statusCode
308
+ };
309
+ return new Observable2((observer) => {
310
+ let innerSubscriber = null;
311
+ let closed = false;
312
+ const recoveryObserver = {
313
+ complete: () => {
314
+ if (!closed) observer.complete();
315
+ },
316
+ error: (error) => {
317
+ if (!closed) observer.error(error);
318
+ },
319
+ isClosed: () => closed,
320
+ next: (value) => {
321
+ if (!closed) observer.next(value);
322
+ }
323
+ };
324
+ const teardown = () => {
325
+ closed = true;
326
+ innerSubscriber?.unsubscribe();
327
+ innerSubscriber = null;
328
+ };
329
+ void recoverFromAuthError(
330
+ operation,
331
+ forward,
332
+ authContext,
333
+ recoveryObserver,
334
+ (subscriber) => {
335
+ innerSubscriber = subscriber;
336
+ }
337
+ ).catch((err) => handleAuthRecoveryError(err, recoveryObserver));
338
+ return teardown;
339
+ });
340
+ });
341
+ }
342
+
343
+ // src/apollo/createRefreshAccessToken.ts
344
+ var REFRESH_TOKEN_QUERY = `
345
+ mutation refreshToken($input: RefreshTokenInputType!) {
346
+ refreshToken(input: $input) {
347
+ data {
348
+ token
349
+ refreshToken
350
+ }
351
+ message
352
+ }
353
+ }
354
+ `;
355
+ var RETRY_DELAY_MS = 1500;
356
+ var MAX_REFRESH_ATTEMPTS = 5;
357
+ var wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
358
+ function createRefreshAccessToken(adapters) {
359
+ const {
360
+ apiUrl,
361
+ storage,
362
+ onTokensUpdated,
363
+ onTokensCleared,
364
+ onError: onError3,
365
+ onDebug,
366
+ onAuthRecoveryEvent,
367
+ refreshCoordination
368
+ } = adapters;
369
+ let inFlightRefresh = null;
370
+ async function clearRefreshCredentials(reason) {
371
+ await storage.clearTokens();
372
+ onTokensCleared?.(reason);
373
+ }
374
+ async function clearOrAdoptNewerAccessToken(reason, accessTokenAtStart, errorCode) {
375
+ const currentAccess = await storage.getAccessToken();
376
+ if (currentAccess != null && currentAccess !== accessTokenAtStart) {
377
+ onAuthRecoveryEvent?.({ reason, type: "stale_clear_skipped" });
378
+ return { hadRefreshToken: true, token: currentAccess };
379
+ }
380
+ await clearRefreshCredentials(reason);
381
+ onAuthRecoveryEvent?.({
382
+ errorCode,
383
+ reason,
384
+ type: "refresh_failed"
385
+ });
386
+ return {
387
+ hadRefreshToken: true,
388
+ token: null
389
+ };
390
+ }
391
+ async function abortAfterRefreshGraphqlErrors(errors, errorCode, accessTokenAtStart) {
392
+ const sanitizedErrors = errors.map((error) => ({
393
+ message: error?.message
394
+ }));
395
+ if (isExpectedRefreshAuthFailure(errors, errorCode)) {
396
+ console.warn(
397
+ "[refreshAccessToken] Refresh rejected:",
398
+ errorCode ?? sanitizedErrors.map((e) => e.message).join(", ")
399
+ );
400
+ } else {
401
+ console.error("[refreshAccessToken] GraphQL errors:", sanitizedErrors);
402
+ onError3?.(new Error("GraphQL errors during refresh"), {
403
+ action: "refresh_graphql_error",
404
+ errorCode,
405
+ errors: sanitizedErrors
406
+ });
407
+ }
408
+ const outcome = await clearOrAdoptNewerAccessToken(
409
+ "refresh_graphql_error",
410
+ accessTokenAtStart,
411
+ errorCode
412
+ );
413
+ return {
414
+ ...outcome,
415
+ errorCode
416
+ };
417
+ }
418
+ async function runRefreshAttempt(refreshToken, attempt) {
419
+ const res = await fetch(`${apiUrl}/graphql`, {
420
+ body: JSON.stringify({
421
+ query: REFRESH_TOKEN_QUERY,
422
+ variables: { input: { refreshToken } }
423
+ }),
424
+ headers: { "Content-Type": "application/json" },
425
+ method: "POST"
426
+ });
427
+ const json = await res.json();
428
+ if (json.errors?.length) {
429
+ const errors = json.errors;
430
+ const errorCode = getRefreshErrorCode(errors);
431
+ const warrantRetry = refreshGraphqlErrorsWarrantRetry(errors) && attempt < MAX_REFRESH_ATTEMPTS;
432
+ if (warrantRetry) {
433
+ onDebug?.(
434
+ `GraphQL errors (attempt ${attempt}/${MAX_REFRESH_ATTEMPTS}), retrying`,
435
+ { errorCode }
436
+ );
437
+ return { kind: "retry" };
438
+ }
439
+ return { errorCode, errors, kind: "terminal_graphql" };
440
+ }
441
+ const newToken = json?.data?.refreshToken?.data?.token;
442
+ const newRefreshToken = json?.data?.refreshToken?.data?.refreshToken;
443
+ if (newToken && newRefreshToken) {
444
+ await storage.setTokens(newToken, newRefreshToken);
445
+ onTokensUpdated?.(newToken);
446
+ return { kind: "success", token: newToken };
447
+ }
448
+ if (attempt < MAX_REFRESH_ATTEMPTS) {
449
+ onDebug?.(
450
+ `Invalid refresh response (attempt ${attempt}/${MAX_REFRESH_ATTEMPTS}), retrying`
451
+ );
452
+ return { kind: "retry" };
453
+ }
454
+ return { kind: "terminal_invalid" };
455
+ }
456
+ async function refreshAccessTokenInternal() {
457
+ const accessTokenAtStart = await storage.getAccessToken();
458
+ for (let attempt = 1; attempt <= MAX_REFRESH_ATTEMPTS; attempt += 1) {
459
+ const refreshToken = await storage.getRefreshToken();
460
+ if (!refreshToken) return { hadRefreshToken: false, token: null };
461
+ try {
462
+ const result = await runRefreshAttempt(refreshToken, attempt);
463
+ if (result.kind === "success") {
464
+ onAuthRecoveryEvent?.({ type: "refresh_succeeded" });
465
+ return { hadRefreshToken: true, token: result.token };
466
+ }
467
+ if (result.kind === "retry") {
468
+ await wait(RETRY_DELAY_MS);
469
+ continue;
470
+ }
471
+ if (result.kind === "terminal_graphql") {
472
+ return abortAfterRefreshGraphqlErrors(
473
+ result.errors,
474
+ result.errorCode,
475
+ accessTokenAtStart
476
+ );
477
+ }
478
+ return clearOrAdoptNewerAccessToken(
479
+ "refresh_invalid_response",
480
+ accessTokenAtStart
481
+ );
482
+ } catch (err) {
483
+ if (attempt < MAX_REFRESH_ATTEMPTS) {
484
+ await wait(RETRY_DELAY_MS);
485
+ continue;
486
+ }
487
+ onError3?.(err, {
488
+ action: "refreshAccessToken",
489
+ attempt,
490
+ maxAttempts: MAX_REFRESH_ATTEMPTS
491
+ });
492
+ console.error("Token refresh failed:", err);
493
+ onAuthRecoveryEvent?.({
494
+ reason: "refresh_network_exhausted",
495
+ retryable: true,
496
+ type: "refresh_failed"
497
+ });
498
+ return { hadRefreshToken: true, retryable: true, token: null };
499
+ }
500
+ }
501
+ throw new Error("refreshAccessToken: unreachable");
502
+ }
503
+ return function refreshAccessToken() {
504
+ if (inFlightRefresh !== null) {
505
+ return inFlightRefresh;
506
+ }
507
+ const startCoalesced = () => {
508
+ inFlightRefresh ??= refreshAccessTokenInternal().finally(() => {
509
+ inFlightRefresh = null;
510
+ });
511
+ return inFlightRefresh;
512
+ };
513
+ if (refreshCoordination) {
514
+ return refreshCoordination.withLock(async () => {
515
+ if (inFlightRefresh !== null) {
516
+ return inFlightRefresh;
517
+ }
518
+ return startCoalesced();
519
+ });
520
+ }
521
+ return startCoalesced();
522
+ };
523
+ }
524
+
525
+ // src/apollo/createApolloErrorLoggingLink.ts
526
+ import { onError as onError2 } from "@apollo/client/link/error";
527
+
528
+ // src/apollo/toStructuredError.ts
529
+ function safeJsonStringify(value) {
530
+ const seen = /* @__PURE__ */ new WeakSet();
531
+ const json = JSON.stringify(
532
+ value,
533
+ (_key, v) => {
534
+ if (typeof v === "bigint") return v.toString();
535
+ if (typeof v === "function") return `[Function ${v.name || "anonymous"}]`;
536
+ if (v && typeof v === "object") {
537
+ if (seen.has(v)) return "[Circular]";
538
+ seen.add(v);
539
+ }
540
+ if (v instanceof Error) {
541
+ return {
542
+ message: v.message,
543
+ name: v.name,
544
+ stack: v.stack,
545
+ ...v
546
+ };
547
+ }
548
+ return v;
549
+ },
550
+ 2
551
+ );
552
+ return json ?? "null";
553
+ }
554
+ function coerceJson(value) {
555
+ if (value === void 0) return void 0;
556
+ if (value === null) return null;
557
+ if (typeof value === "boolean" || typeof value === "number" || typeof value === "string") {
558
+ return value;
559
+ }
560
+ if (typeof value === "bigint") return value.toString();
561
+ if (typeof value === "symbol") return value.toString();
562
+ if (typeof value === "function") {
563
+ return `[Function ${value.name || "anonymous"}]`;
564
+ }
565
+ return value;
566
+ }
567
+ function pickKnownFields(src, dst) {
568
+ const keys = [
569
+ "message",
570
+ "code",
571
+ "reason",
572
+ "type",
573
+ "name",
574
+ "stack",
575
+ "status",
576
+ "statusCode",
577
+ "readyState",
578
+ "url",
579
+ "wasClean"
580
+ ];
581
+ for (const k of keys) {
582
+ if (k in src) {
583
+ const coerced = coerceJson(src[k]);
584
+ if (coerced !== void 0) dst[k] = coerced;
585
+ }
586
+ }
587
+ }
588
+ function objectToJson(anyErr) {
589
+ const out = {};
590
+ pickKnownFields(anyErr, out);
591
+ for (const [k, v] of Object.entries(anyErr)) {
592
+ if (k in out) continue;
593
+ const coerced = coerceJson(v);
594
+ if (coerced !== void 0) out[k] = coerced;
595
+ }
596
+ return out;
597
+ }
598
+ function toStructuredError(err) {
599
+ if (err == null) return null;
600
+ if (typeof err === "string") return { message: err };
601
+ if (typeof err === "number" || typeof err === "boolean")
602
+ return { value: err };
603
+ if (typeof err === "symbol") return { value: err.toString() };
604
+ if (err instanceof Error) {
605
+ const details = objectToJson(err);
606
+ if (details && typeof details === "object" && !Array.isArray(details)) {
607
+ return {
608
+ ...details,
609
+ message: err.message,
610
+ name: err.name,
611
+ stack: err.stack ?? null
612
+ };
613
+ }
614
+ return {
615
+ message: err.message,
616
+ name: err.name,
617
+ stack: err.stack ?? null
618
+ };
619
+ }
620
+ if (typeof err === "object") return objectToJson(err);
621
+ return { value: safeJsonStringify({ value: err }) };
622
+ }
623
+
624
+ // src/apollo/createApolloErrorLoggingLink.ts
625
+ var SCOPE = "apollo";
626
+ var REDACTED = "[REDACTED]";
627
+ var MAX_DEPTH = 4;
628
+ var MAX_ARRAY_ITEMS = 20;
629
+ var SENSITIVE_KEY_RE = /(pass(word)?|token|secret|auth(orization)?|cookie|session|otp|pin|email|phone|ssn|credit|card|cvv|iban|refresh)/i;
630
+ var GRAPHQL_EXTENSION_ALLOWLIST = /* @__PURE__ */ new Set(["category", "code", "httpStatus"]);
631
+ function resolveIsDev(isDev) {
632
+ return typeof isDev === "function" ? isDev() : isDev;
633
+ }
634
+ function isSensitiveKey(key) {
635
+ return SENSITIVE_KEY_RE.test(key);
636
+ }
637
+ function isSensitiveExtensionKey(key) {
638
+ return isSensitiveKey(key) || /stack|trace|debug|exception|internals|snippet|query|variables|body/i.test(
639
+ key
640
+ );
641
+ }
642
+ function redactValue(value, depth = 0) {
643
+ if (value == null) return value;
644
+ if (depth >= MAX_DEPTH) return "[Truncated]";
645
+ if (Array.isArray(value)) {
646
+ return value.slice(0, MAX_ARRAY_ITEMS).map((item) => redactValue(item, depth + 1));
647
+ }
648
+ if (typeof value === "object") {
649
+ const input = value;
650
+ const out = {};
651
+ for (const [key, nested] of Object.entries(input)) {
652
+ out[key] = isSensitiveKey(key) ? REDACTED : redactValue(nested, depth + 1);
653
+ }
654
+ return out;
655
+ }
656
+ return value;
657
+ }
658
+ function pickAllowlistedExtensions(ext) {
659
+ const out = {};
660
+ for (const key of GRAPHQL_EXTENSION_ALLOWLIST) {
661
+ if (key in ext && ext[key] !== void 0) {
662
+ out[key] = ext[key];
663
+ }
664
+ }
665
+ return Object.keys(out).length > 0 ? out : void 0;
666
+ }
667
+ function redactGraphQLExtensionsForDev(ext) {
668
+ const out = {};
669
+ for (const [key, value] of Object.entries(ext)) {
670
+ if (GRAPHQL_EXTENSION_ALLOWLIST.has(key)) {
671
+ out[key] = value != null && typeof value === "object" ? redactValue(value) : value;
672
+ continue;
673
+ }
674
+ if (isSensitiveExtensionKey(key)) {
675
+ out[key] = REDACTED;
676
+ continue;
677
+ }
678
+ out[key] = redactValue(value);
679
+ }
680
+ return Object.keys(out).length > 0 ? out : void 0;
681
+ }
682
+ function safeExtensionsForLogs(extensions, isDev) {
683
+ if (extensions == null) return void 0;
684
+ if (typeof extensions !== "object" || Array.isArray(extensions)) {
685
+ return "[NonObjectExtensions]";
686
+ }
687
+ const ext = extensions;
688
+ if (!isDev) {
689
+ return pickAllowlistedExtensions(ext);
690
+ }
691
+ return redactGraphQLExtensionsForDev(ext);
692
+ }
693
+ function serializeGraphQLError(err, isDev) {
694
+ return {
695
+ extensions: safeExtensionsForLogs(err.extensions, isDev),
696
+ locations: err.locations,
697
+ message: err.message,
698
+ path: err.path
699
+ };
700
+ }
701
+ function safeVariablesForLogs(variables, isDev) {
702
+ if (!variables) return void 0;
703
+ if (!isDev) {
704
+ return {
705
+ keys: Object.keys(variables),
706
+ present: true
707
+ };
708
+ }
709
+ return redactValue(variables);
710
+ }
711
+ function safeResponseForLogs(response, isDev) {
712
+ if (!response) return null;
713
+ if (!isDev) return { present: true };
714
+ return redactValue(toStructuredError(response));
715
+ }
716
+ function createApolloErrorLoggingLink(adapters) {
717
+ const { isDev, onLog } = adapters;
718
+ return onError2((errorHandler) => {
719
+ const { operation } = errorHandler;
720
+ const { graphQLErrors, networkError, response } = readErrorResponseFields(errorHandler);
721
+ const dev = resolveIsDev(isDev);
722
+ if (graphQLErrors?.length) {
723
+ onLog("error", SCOPE, "GraphQL error(s)", {
724
+ graphQLErrors: graphQLErrors.map(
725
+ (err) => serializeGraphQLError(err, dev)
726
+ ),
727
+ operationName: operation.operationName,
728
+ variables: safeVariablesForLogs(operation.variables, dev)
729
+ });
730
+ }
731
+ if (networkError) {
732
+ onLog("error", SCOPE, "Network error", {
733
+ networkError: toStructuredError(networkError),
734
+ operationName: operation.operationName,
735
+ response: safeResponseForLogs(response, dev),
736
+ variables: safeVariablesForLogs(operation.variables, dev)
737
+ });
738
+ }
739
+ return void 0;
740
+ });
741
+ }
742
+
743
+ // src/apollo/createNetworkRecoveryLink.ts
744
+ import { ApolloLink as ApolloLink2, Observable as Observable3 } from "@apollo/client";
745
+ import { getMainDefinition } from "@apollo/client/utilities";
746
+ var MAX_RETRIES = 4;
747
+ var BACKOFF_MS = [500, 1500, 3e3, 4e3];
748
+ function emitNext(state, value) {
749
+ if (state.unsubscribed) return;
750
+ state.observer.next(value);
751
+ }
752
+ function emitComplete(state) {
753
+ if (state.unsubscribed) return;
754
+ state.observer.complete();
755
+ }
756
+ function emitError(state, err) {
757
+ if (state.unsubscribed) return;
758
+ state.observer.error(err);
759
+ }
760
+ function isQueryOperation(op) {
761
+ const def = getMainDefinition(op.query);
762
+ return def.kind === "OperationDefinition" && def.operation === "query";
763
+ }
764
+ function wait2(ms) {
765
+ return new Promise((resolve) => setTimeout(resolve, ms));
766
+ }
767
+ function isRetryableNetworkFailure(err) {
768
+ if (isTransientNetworkError(err)) return true;
769
+ const networkError = err && typeof err === "object" ? err.networkError : void 0;
770
+ if (!networkError) return false;
771
+ if (typeof networkError === "object" && networkError !== null && !(networkError instanceof Error) && Object.keys(networkError).length === 0) {
772
+ return false;
773
+ }
774
+ return isTransientNetworkError(networkError);
775
+ }
776
+ function waitForOnline(adapters, aborted) {
777
+ return new Promise((resolve) => {
778
+ if (aborted()) {
779
+ resolve();
780
+ return;
781
+ }
782
+ let intervalId = null;
783
+ const unsub = adapters.subscribeIsOnline((online) => {
784
+ if (aborted()) {
785
+ if (intervalId !== null) {
786
+ clearInterval(intervalId);
787
+ intervalId = null;
788
+ }
789
+ unsub();
790
+ resolve();
791
+ return;
792
+ }
793
+ if (online) {
794
+ if (intervalId !== null) {
795
+ clearInterval(intervalId);
796
+ intervalId = null;
797
+ }
798
+ unsub();
799
+ resolve();
800
+ }
801
+ });
802
+ intervalId = setInterval(() => {
803
+ if (aborted()) {
804
+ if (intervalId !== null) {
805
+ clearInterval(intervalId);
806
+ intervalId = null;
807
+ }
808
+ unsub();
809
+ resolve();
810
+ }
811
+ }, 500);
812
+ });
813
+ }
814
+ function cleanupRecoveryState(state) {
815
+ state.innerSub?.unsubscribe();
816
+ state.innerSub = null;
817
+ }
818
+ async function ensureOnlineOrWait(state) {
819
+ const online = await state.adapters.forceRefreshIsOnline();
820
+ if (online) return !state.unsubscribed;
821
+ await waitForOnline(state.adapters, () => state.unsubscribed);
822
+ return !state.unsubscribed;
823
+ }
824
+ async function handleQueryNetworkError(state, err, attempt) {
825
+ if (state.unsubscribed) return;
826
+ if (!isRetryableNetworkFailure(err)) {
827
+ emitError(state, err);
828
+ return;
829
+ }
830
+ const nowOnline = await state.adapters.forceRefreshIsOnline();
831
+ if (state.unsubscribed) return;
832
+ if (!nowOnline) {
833
+ await waitForOnline(state.adapters, () => state.unsubscribed);
834
+ if (state.unsubscribed) return;
835
+ cleanupRecoveryState(state);
836
+ void runQueryAttempt(state, attempt);
837
+ return;
838
+ }
839
+ if (attempt >= MAX_RETRIES) {
840
+ emitError(state, err);
841
+ return;
842
+ }
843
+ await wait2(BACKOFF_MS[attempt] ?? 4e3);
844
+ if (state.unsubscribed) return;
845
+ cleanupRecoveryState(state);
846
+ void runQueryAttempt(state, attempt + 1);
847
+ }
848
+ async function runQueryAttempt(state, attempt) {
849
+ if (state.unsubscribed) return;
850
+ const canContinue = await ensureOnlineOrWait(state);
851
+ if (!canContinue) return;
852
+ try {
853
+ state.innerSub = state.forward(state.operation).subscribe({
854
+ complete: () => emitComplete(state),
855
+ error: (err) => {
856
+ if (!isRetryableNetworkFailure(err)) {
857
+ emitError(state, err);
858
+ return;
859
+ }
860
+ void handleQueryNetworkError(state, err, attempt);
861
+ },
862
+ next: (value) => emitNext(state, value)
863
+ });
864
+ } catch (e) {
865
+ emitError(state, e);
866
+ }
867
+ }
868
+ function createNetworkRecoveryLink(adapters) {
869
+ return new ApolloLink2((operation, forward) => {
870
+ if (!forward) {
871
+ return null;
872
+ }
873
+ if (!isQueryOperation(operation)) {
874
+ return forward(operation);
875
+ }
876
+ return new Observable3((observer) => {
877
+ const state = {
878
+ adapters,
879
+ forward,
880
+ innerSub: null,
881
+ observer,
882
+ operation,
883
+ unsubscribed: false
884
+ };
885
+ void runQueryAttempt(state, 0);
886
+ return () => {
887
+ state.unsubscribed = true;
888
+ cleanupRecoveryState(state);
889
+ };
890
+ });
891
+ });
892
+ }
893
+
894
+ // src/apollo/createNetworkLog.ts
895
+ function resolveEnabled(enabled) {
896
+ return typeof enabled === "function" ? enabled() : enabled;
897
+ }
898
+ function createNetworkLog(adapters) {
899
+ const { enabled } = adapters;
900
+ return function networkLog(level, scope, message, details) {
901
+ if (!resolveEnabled(enabled)) return;
902
+ const payload = details ? safeJsonStringify(details) : "";
903
+ const prefix = `[${scope}] ${message}`;
904
+ let logger;
905
+ switch (level) {
906
+ case "debug":
907
+ logger = console.debug;
908
+ break;
909
+ case "info":
910
+ logger = console.info;
911
+ break;
912
+ case "warn":
913
+ logger = console.warn;
914
+ break;
915
+ case "error":
916
+ default:
917
+ logger = console.error;
918
+ break;
919
+ }
920
+ logger(payload ? `${prefix}
921
+ ${payload}` : prefix);
922
+ };
923
+ }
924
+
925
+ // src/apollo/createWsManager.ts
926
+ import { createClient } from "graphql-ws";
927
+ var WS_SCOPE = "ws";
928
+ var MIN_RECONNECT_MS = 1e3;
929
+ var MAX_RECONNECT_MS = 1e4;
930
+ var WS_CLIENT_RESTART_CODE = 4205;
931
+ var MAX_WS_RETRY_ATTEMPTS = 30;
932
+ var WS_READY_STATE_OPEN = 1;
933
+ var WS_READY_STATE_CONNECTING = 0;
934
+ function resolveIsDev2(isDev) {
935
+ if (isDev == null) return false;
936
+ return typeof isDev === "function" ? isDev() : isDev;
937
+ }
938
+ function maskedTokenInfo2(token) {
939
+ const len = token.length;
940
+ const start = token.slice(0, 4);
941
+ const end = token.slice(-4);
942
+ return { end, len, start };
943
+ }
944
+ function computeBackoffMs(attempt) {
945
+ const exp = Math.min(MIN_RECONNECT_MS * 2 ** attempt, MAX_RECONNECT_MS);
946
+ const jitter = (attempt * 37 + 17) % 250;
947
+ return Math.min(exp + jitter, MAX_RECONNECT_MS);
948
+ }
949
+ function wsCloseReason(reason) {
950
+ const trimmed = reason.trim().slice(0, 100);
951
+ return trimmed || "restart";
952
+ }
953
+ function createWsManager(adapters) {
954
+ const {
955
+ getWsUrl,
956
+ awaitReady,
957
+ getAccessToken,
958
+ isActive,
959
+ subscribeLifecycle,
960
+ onLog,
961
+ isDev
962
+ } = adapters;
963
+ const log = (level, message, details) => {
964
+ onLog?.(level, WS_SCOPE, message, details);
965
+ };
966
+ let client = null;
967
+ let activeSocket = null;
968
+ let unsubscribeLifecycle = null;
969
+ const ensureConnectedRef = {
970
+ current: () => void 0
971
+ };
972
+ const close = (reason) => {
973
+ activeSocket = null;
974
+ if (client) {
975
+ try {
976
+ log("debug", "Disposing WS client", { reason });
977
+ client.dispose();
978
+ } catch (e) {
979
+ log("warn", "Error while disposing WS client", {
980
+ error: toStructuredError(e),
981
+ reason
982
+ });
983
+ }
984
+ }
985
+ client = null;
986
+ };
987
+ const createNewClient = () => {
988
+ const url = getWsUrl();
989
+ return createClient({
990
+ connectionParams: async () => {
991
+ try {
992
+ await awaitReady();
993
+ } catch (e) {
994
+ log("error", "WS auth params: awaitReady failed", {
995
+ error: toStructuredError(e)
996
+ });
997
+ return {};
998
+ }
999
+ const token = getAccessToken();
1000
+ if (!token) {
1001
+ if (resolveIsDev2(isDev)) {
1002
+ log("warn", "WS auth params: missing token", {});
1003
+ }
1004
+ return {};
1005
+ }
1006
+ if (resolveIsDev2(isDev)) {
1007
+ log("debug", "WS connecting with token", {
1008
+ token: maskedTokenInfo2(token)
1009
+ });
1010
+ }
1011
+ const bearer = `Bearer ${token}`;
1012
+ return { Authorization: bearer, authorization: bearer };
1013
+ },
1014
+ keepAlive: 2e4,
1015
+ lazy: true,
1016
+ on: {
1017
+ closed: (ev) => {
1018
+ activeSocket = null;
1019
+ log("warn", "WS closed", {
1020
+ close: toStructuredError(ev),
1021
+ url
1022
+ });
1023
+ },
1024
+ connected: (socket) => {
1025
+ activeSocket = socket;
1026
+ log("info", "WS connected", { url });
1027
+ },
1028
+ connecting: () => {
1029
+ log("debug", "WS connecting", { url });
1030
+ },
1031
+ error: (err) => {
1032
+ const structuredError = toStructuredError(err);
1033
+ const hasStructuredDetails = structuredError != null && (typeof structuredError !== "object" || Array.isArray(structuredError) || Object.keys(structuredError).length > 0);
1034
+ const logLevel = hasStructuredDetails ? "error" : "warn";
1035
+ const logMessage = hasStructuredDetails ? "WS error" : "WS error (empty payload)";
1036
+ log(
1037
+ logLevel,
1038
+ logMessage,
1039
+ hasStructuredDetails ? { error: structuredError, url } : { url }
1040
+ );
1041
+ }
1042
+ },
1043
+ retryAttempts: MAX_WS_RETRY_ATTEMPTS,
1044
+ retryWait: async (retries) => {
1045
+ await new Promise(
1046
+ (resolve) => setTimeout(resolve, computeBackoffMs(retries))
1047
+ );
1048
+ },
1049
+ url
1050
+ });
1051
+ };
1052
+ const initLifecycleListener = () => {
1053
+ if (unsubscribeLifecycle) return;
1054
+ unsubscribeLifecycle = subscribeLifecycle({
1055
+ onActive: () => {
1056
+ log("debug", "Lifecycle active; allowing reconnect", {});
1057
+ ensureConnectedRef.current("lifecycle_active");
1058
+ },
1059
+ onInactive: () => {
1060
+ log("debug", "Lifecycle inactive; closing WS", {});
1061
+ close("lifecycle_inactive");
1062
+ }
1063
+ });
1064
+ };
1065
+ const getClient = () => {
1066
+ initLifecycleListener();
1067
+ if (!client) {
1068
+ client = createNewClient();
1069
+ }
1070
+ return client;
1071
+ };
1072
+ const nudgeSocketReconnect = (reason) => {
1073
+ if (!isActive()) return;
1074
+ const token = getAccessToken();
1075
+ if (!token) {
1076
+ if (resolveIsDev2(isDev)) {
1077
+ log("warn", "WS restart blocked (missing token)", { reason });
1078
+ }
1079
+ close(`blocked_missing_token:${reason}`);
1080
+ return;
1081
+ }
1082
+ if (client === null) {
1083
+ client = createNewClient();
1084
+ log("debug", "WS client created", { reason });
1085
+ return;
1086
+ }
1087
+ const socket = activeSocket;
1088
+ if (socket !== null) {
1089
+ const { readyState } = socket;
1090
+ if (readyState === WS_READY_STATE_OPEN || readyState === WS_READY_STATE_CONNECTING) {
1091
+ try {
1092
+ socket.close(WS_CLIENT_RESTART_CODE, wsCloseReason(reason));
1093
+ log("debug", "WS socket restart (same client)", { reason });
1094
+ } catch (e) {
1095
+ log("warn", "WS socket close failed", {
1096
+ error: toStructuredError(e),
1097
+ reason
1098
+ });
1099
+ }
1100
+ }
1101
+ return;
1102
+ }
1103
+ if (resolveIsDev2(isDev)) {
1104
+ log("debug", "WS nudge: no open socket (library retry)", { reason });
1105
+ }
1106
+ };
1107
+ const ensureConnected = (reason) => {
1108
+ initLifecycleListener();
1109
+ if (!isActive()) {
1110
+ log("debug", "Skip ensureConnected while inactive", { reason });
1111
+ return;
1112
+ }
1113
+ awaitReady().then(() => {
1114
+ const token = getAccessToken();
1115
+ if (!token) {
1116
+ if (resolveIsDev2(isDev)) {
1117
+ log("warn", "WS blocked (missing token)", { reason });
1118
+ }
1119
+ return;
1120
+ }
1121
+ getClient();
1122
+ }).catch((e) => {
1123
+ log("error", "WS ensureConnected failed", {
1124
+ error: toStructuredError(e),
1125
+ reason
1126
+ });
1127
+ });
1128
+ };
1129
+ ensureConnectedRef.current = ensureConnected;
1130
+ const onAuthTokenChanged = (reason) => {
1131
+ if (resolveIsDev2(isDev)) {
1132
+ log("debug", "Auth token changed; reconnecting WS", { reason });
1133
+ }
1134
+ nudgeSocketReconnect(`auth_token_changed:${reason}`);
1135
+ };
1136
+ const dispose = () => {
1137
+ close("dispose");
1138
+ if (unsubscribeLifecycle) {
1139
+ unsubscribeLifecycle();
1140
+ unsubscribeLifecycle = null;
1141
+ }
1142
+ };
1143
+ return {
1144
+ close,
1145
+ dispose,
1146
+ ensureConnected,
1147
+ getClient,
1148
+ initLifecycleListener,
1149
+ onAuthTokenChanged
1150
+ };
1151
+ }
1152
+
1153
+ // src/apollo/recoveryConstants.ts
1154
+ var MIN_BACKGROUND_MS = 3e4;
1155
+ var REFETCH_DELAY_MS = 500;
1156
+
1157
+ // src/apollo/createRecoveryCore.ts
1158
+ var DEFAULT_SHORT_BG_REASON = "short_background";
1159
+ var DEFAULT_RECOVER_REASON = "apollo_recover";
1160
+ function createRecoveryCore(adapters) {
1161
+ const {
1162
+ refreshSession,
1163
+ ensureWsConnected,
1164
+ disposeWs,
1165
+ refetchActiveQueries,
1166
+ isActive,
1167
+ isOnline,
1168
+ subscribeLifecycle,
1169
+ shortBackgroundWsReason = DEFAULT_SHORT_BG_REASON,
1170
+ recoverWsReason = DEFAULT_RECOVER_REASON,
1171
+ now = () => Date.now(),
1172
+ schedule = (fn, ms) => setTimeout(fn, ms),
1173
+ cancelSchedule = (id) => clearTimeout(id)
1174
+ } = adapters;
1175
+ let recovering = false;
1176
+ let resetGeneration = 0;
1177
+ let backgroundTime = null;
1178
+ let wsDisposeTimer = null;
1179
+ let refetchTimer = null;
1180
+ let unsubscribeLifecycle = null;
1181
+ const clearRefetchTimer = () => {
1182
+ if (refetchTimer !== null) {
1183
+ cancelSchedule(refetchTimer);
1184
+ refetchTimer = null;
1185
+ }
1186
+ };
1187
+ const clearWsDisposeTimer = () => {
1188
+ if (wsDisposeTimer !== null) {
1189
+ cancelSchedule(wsDisposeTimer);
1190
+ wsDisposeTimer = null;
1191
+ }
1192
+ };
1193
+ const canUseNetwork = () => isOnline?.() ?? true;
1194
+ const scheduleActiveQueryRefetch = (generationAtStart) => {
1195
+ clearRefetchTimer();
1196
+ refetchTimer = schedule(() => {
1197
+ refetchTimer = null;
1198
+ if (!isActive()) return;
1199
+ if (generationAtStart !== resetGeneration) return;
1200
+ if (!canUseNetwork()) return;
1201
+ refetchActiveQueries();
1202
+ }, REFETCH_DELAY_MS);
1203
+ };
1204
+ const handleMovedToBackground = () => {
1205
+ clearRefetchTimer();
1206
+ backgroundTime = now();
1207
+ clearWsDisposeTimer();
1208
+ wsDisposeTimer = schedule(() => {
1209
+ wsDisposeTimer = null;
1210
+ disposeWs();
1211
+ }, MIN_BACKGROUND_MS);
1212
+ };
1213
+ async function recoverApollo() {
1214
+ if (recovering) return;
1215
+ recovering = true;
1216
+ const generationAtStart = resetGeneration;
1217
+ try {
1218
+ const shouldRefetch = await refreshSession();
1219
+ if (generationAtStart !== resetGeneration) return;
1220
+ ensureWsConnected(recoverWsReason);
1221
+ if (!isActive()) return;
1222
+ if (shouldRefetch) {
1223
+ scheduleActiveQueryRefetch(generationAtStart);
1224
+ }
1225
+ } finally {
1226
+ if (generationAtStart === resetGeneration) {
1227
+ recovering = false;
1228
+ }
1229
+ }
1230
+ }
1231
+ const handleReturnedToForeground = () => {
1232
+ clearWsDisposeTimer();
1233
+ const bgTime = backgroundTime;
1234
+ const elapsed = bgTime != null ? now() - bgTime : MIN_BACKGROUND_MS;
1235
+ backgroundTime = null;
1236
+ if (elapsed >= MIN_BACKGROUND_MS) {
1237
+ void recoverApollo();
1238
+ return;
1239
+ }
1240
+ ensureWsConnected(shortBackgroundWsReason);
1241
+ };
1242
+ return {
1243
+ prepareClientReset() {
1244
+ clearRefetchTimer();
1245
+ clearWsDisposeTimer();
1246
+ backgroundTime = null;
1247
+ recovering = false;
1248
+ resetGeneration += 1;
1249
+ },
1250
+ recoverApollo,
1251
+ start() {
1252
+ if (unsubscribeLifecycle) return;
1253
+ unsubscribeLifecycle = subscribeLifecycle({
1254
+ onActive: handleReturnedToForeground,
1255
+ onInactive: handleMovedToBackground
1256
+ });
1257
+ },
1258
+ stop() {
1259
+ if (unsubscribeLifecycle) {
1260
+ unsubscribeLifecycle();
1261
+ unsubscribeLifecycle = null;
1262
+ }
1263
+ clearRefetchTimer();
1264
+ clearWsDisposeTimer();
1265
+ backgroundTime = null;
1266
+ recovering = false;
1267
+ }
1268
+ };
1269
+ }
1270
+ export {
1271
+ MIN_BACKGROUND_MS,
1272
+ NON_RETRYABLE_REFRESH_AUTH_CODES,
1273
+ REFETCH_DELAY_MS,
1274
+ createApolloErrorLoggingLink,
1275
+ createApolloManager,
1276
+ createAuthLink,
1277
+ createErrorLink,
1278
+ createNetworkLog,
1279
+ createNetworkRecoveryLink,
1280
+ createRecoveryCore,
1281
+ createRefreshAccessToken,
1282
+ createWsManager,
1283
+ decideRefreshNextStep,
1284
+ getRefreshErrorCode,
1285
+ getStatusCode,
1286
+ isExpectedRefreshAuthFailure,
1287
+ isRefreshAuthFailureMessage,
1288
+ isUnauthenticatedError,
1289
+ isUnauthenticatedGraphQLError,
1290
+ readErrorResponseFields,
1291
+ refreshGraphqlErrorsWarrantRetry,
1292
+ safeJsonStringify,
1293
+ toStructuredError
1294
+ };
1295
+ //# sourceMappingURL=index.mjs.map