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