@timardex/cluemart-shared 1.7.0 → 1.7.2
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.
- package/dist/ad-BUYzE6zx.d.ts +181 -0
- package/dist/ad-BhLoEul3.d.mts +181 -0
- package/dist/affiliate-BbtjeUP4.d.mts +73 -0
- package/dist/affiliate-C51nzKsw.d.ts +73 -0
- package/dist/apollo/index.cjs +1383 -0
- package/dist/apollo/index.cjs.map +1 -0
- package/dist/apollo/index.d.mts +323 -0
- package/dist/apollo/index.d.ts +323 -0
- package/dist/apollo/index.mjs +1295 -0
- package/dist/apollo/index.mjs.map +1 -0
- package/dist/auth/index.cjs +1727 -0
- package/dist/auth/index.cjs.map +1 -0
- package/dist/auth/index.d.mts +166 -0
- package/dist/auth/index.d.ts +166 -0
- package/dist/auth/index.mjs +380 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/chunk-32MKHJTX.mjs +1207 -0
- package/dist/chunk-32MKHJTX.mjs.map +1 -0
- package/dist/{chunk-HZMP7GXC.mjs → chunk-447EYKHL.mjs} +1010 -2671
- package/dist/chunk-447EYKHL.mjs.map +1 -0
- package/dist/{chunk-RKIRWZCH.mjs → chunk-AYO3E4DM.mjs} +39 -183
- package/dist/chunk-AYO3E4DM.mjs.map +1 -0
- package/dist/{chunk-ZZJSCYJK.mjs → chunk-BIJ5NDXW.mjs} +46 -42
- package/dist/chunk-BIJ5NDXW.mjs.map +1 -0
- package/dist/chunk-DQ7ZHIXW.mjs +26 -0
- package/dist/chunk-DQ7ZHIXW.mjs.map +1 -0
- package/dist/{chunk-MVQ3CFQR.mjs → chunk-ILILH7E2.mjs} +12 -23
- package/dist/chunk-ILILH7E2.mjs.map +1 -0
- package/dist/{chunk-TAECMXM4.mjs → chunk-LBEJECG3.mjs} +249 -219
- package/dist/{chunk-TAECMXM4.mjs.map → chunk-LBEJECG3.mjs.map} +1 -1
- package/dist/chunk-RAYUJODN.mjs +45 -0
- package/dist/chunk-RAYUJODN.mjs.map +1 -0
- package/dist/chunk-SD42WIMV.mjs +297 -0
- package/dist/chunk-SD42WIMV.mjs.map +1 -0
- package/dist/chunk-VPANTTZI.mjs +262 -0
- package/dist/chunk-VPANTTZI.mjs.map +1 -0
- package/dist/{chunk-KZTOISPA.mjs → chunk-X3OLM35T.mjs} +14 -8
- package/dist/chunk-X3OLM35T.mjs.map +1 -0
- package/dist/{contactUs-H7799pWe.d.ts → contactUs--NoohZBu.d.ts} +1 -1
- package/dist/{contactUs-DGrDzJaM.d.mts → contactUs-CBWzefUS.d.mts} +1 -1
- package/dist/enums/index.cjs +13 -7
- package/dist/enums/index.cjs.map +1 -1
- package/dist/enums/index.d.mts +15 -9
- package/dist/enums/index.d.ts +15 -9
- package/dist/enums/index.mjs +1 -1
- package/dist/formFields/index.cjs +136 -73
- package/dist/formFields/index.cjs.map +1 -1
- package/dist/formFields/index.d.mts +3 -2
- package/dist/formFields/index.d.ts +3 -2
- package/dist/formFields/index.mjs +9 -4
- package/dist/{global-fKbMmluy.d.ts → global-CUYYxpy2.d.ts} +12 -11
- package/dist/{global-BUUfmCo7.d.mts → global-DePDtOFt.d.mts} +12 -11
- package/dist/graphql/index.cjs +734 -1271
- package/dist/graphql/index.cjs.map +1 -1
- package/dist/graphql/index.d.mts +434 -176
- package/dist/graphql/index.d.ts +434 -176
- package/dist/graphql/index.mjs +37 -23
- package/dist/hooks/index.cjs +947 -309
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.mts +10 -4
- package/dist/hooks/index.d.ts +10 -4
- package/dist/hooks/index.mjs +170 -58
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/images/apple-maps-icon.webp.d.ts +8 -1
- package/dist/images/banner-horizontal.webp.d.ts +8 -1
- package/dist/images/banner-vertical.webp.d.ts +8 -1
- package/dist/images/cluiTui.webp.d.ts +8 -1
- package/dist/images/corporate.webp.d.ts +8 -1
- package/dist/images/facebook.webp.d.ts +8 -1
- package/dist/images/gazebo-top.webp.d.ts +8 -1
- package/dist/images/google-maps-icon.webp.d.ts +8 -1
- package/dist/images/googleMaps-logo-dark.webp.d.ts +8 -1
- package/dist/images/googleMaps-logo-light.webp.d.ts +8 -1
- package/dist/images/instagram.webp.d.ts +8 -1
- package/dist/images/logo-atr.webp.d.ts +8 -1
- package/dist/images/logo-dark.webp.d.ts +8 -1
- package/dist/images/logo.webp.d.ts +8 -1
- package/dist/images/meet.webp.d.ts +8 -1
- package/dist/images/mini-market1.webp.d.ts +8 -1
- package/dist/images/mini-market2.webp.d.ts +8 -1
- package/dist/images/mini-market3.webp.d.ts +8 -1
- package/dist/images/mini-market4.webp.d.ts +8 -1
- package/dist/images/mini-market5.webp.d.ts +8 -1
- package/dist/images/poll.webp.d.ts +8 -1
- package/dist/images/poster1.webp.d.ts +8 -1
- package/dist/images/poster2.webp.d.ts +8 -1
- package/dist/images/poster3.webp.d.ts +8 -1
- package/dist/images/poster4.webp.d.ts +8 -1
- package/dist/images/private.webp.d.ts +8 -1
- package/dist/images/qr-code.webp.d.ts +8 -1
- package/dist/images/school.webp.d.ts +8 -1
- package/dist/images/sima.webp.d.ts +8 -1
- package/dist/images/store-android.webp.d.ts +8 -1
- package/dist/images/store-ios.webp.d.ts +8 -1
- package/dist/images/tablas.webp.d.ts +8 -1
- package/dist/images/telefonos.webp.d.ts +8 -1
- package/dist/images/tiktok.webp.d.ts +8 -1
- package/dist/images/tip.webp.d.ts +8 -1
- package/dist/images/ugralos.webp.d.ts +8 -1
- package/dist/images/waze-maps-icon.webp.d.ts +8 -1
- package/dist/images/website.webp.d.ts +8 -1
- package/dist/images/youtube.webp.d.ts +8 -1
- package/dist/index.cjs +1751 -1781
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +665 -243
- package/dist/index.d.ts +665 -243
- package/dist/index.mjs +1711 -1779
- package/dist/index.mjs.map +1 -1
- package/dist/map/index.cjs +14 -9
- package/dist/map/index.cjs.map +1 -1
- package/dist/map/index.d.mts +16 -13
- package/dist/map/index.d.ts +16 -13
- package/dist/map/index.mjs +14 -9
- package/dist/map/index.mjs.map +1 -1
- package/dist/{resourceActivities-BL_12IAo.d.ts → resourceActivities-CMUcn2P7.d.ts} +9 -4
- package/dist/{resourceActivities-zczOntNk.d.mts → resourceActivities-CwbJFGIp.d.mts} +9 -4
- package/dist/sharing/index.cjs +39 -1252
- package/dist/sharing/index.cjs.map +1 -1
- package/dist/sharing/index.d.mts +17 -5
- package/dist/sharing/index.d.ts +17 -5
- package/dist/sharing/index.mjs +34 -30
- package/dist/subscription-BU8GvH2K.d.ts +12 -0
- package/dist/subscription-bmAdrnfi.d.mts +12 -0
- package/dist/types/index.cjs +15 -2
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.mts +10 -23
- package/dist/types/index.d.ts +10 -23
- package/dist/types/index.mjs +9 -5
- package/dist/user-D47MLFyH.d.ts +134 -0
- package/dist/user-DE8edl3u.d.mts +134 -0
- package/dist/utils/index.cjs +355 -136
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.mts +87 -35
- package/dist/utils/index.d.ts +87 -35
- package/dist/utils/index.mjs +42 -15
- package/package.json +31 -10
- package/dist/ad-CVkVX_z5.d.ts +0 -296
- package/dist/ad-DA9ECAhK.d.mts +0 -296
- package/dist/affiliate-1RtkLnLP.d.ts +0 -35
- package/dist/affiliate-Cos2Syz5.d.mts +0 -35
- package/dist/chunk-HZMP7GXC.mjs.map +0 -1
- package/dist/chunk-KZTOISPA.mjs.map +0 -1
- package/dist/chunk-MVQ3CFQR.mjs.map +0 -1
- package/dist/chunk-RKIRWZCH.mjs.map +0 -1
- 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
|