@ovineko/spa-guard 0.0.2-alpha-1 → 0.0.4
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/README.md +22 -173
- package/dist/ForceRetryError-BWLv3UVK.d.mts +6 -0
- package/dist/_internal.d.ts +149 -20
- package/dist/_internal.js +113 -170
- package/dist/chunk-CfYAbeIz.mjs +13 -0
- package/dist/common/index.d.ts +29 -9
- package/dist/common/index.js +47 -83
- package/dist/errorDispatchers-Cl_pa0DT.mjs +105 -0
- package/dist/i18n/index.d.ts +2 -21
- package/dist/i18n/index.js +344 -341
- package/dist/index-DL8CfPXg.d.mts +26 -0
- package/dist/index-rPxPv6iu.d.mts +16 -0
- package/dist/logger-Cp1Eyk6S.mjs +534 -0
- package/dist/retryOrchestrator-DNGIHV2M.mjs +758 -0
- package/dist/retryOrchestrator-mn9XcIVu.d.mts +257 -0
- package/dist/runtime/debug/index.d.ts +6 -4
- package/dist/runtime/debug/index.js +218 -238
- package/dist/runtime/index.d.ts +66 -8
- package/dist/runtime/index.js +279 -367
- package/dist/schema/index.d.ts +2 -13
- package/dist/schema/index.js +1 -0
- package/dist/schema/parse.d.ts +6 -2
- package/dist/schema/parse.js +29 -44
- package/dist/spinner-BbZVKZ-6.mjs +60 -0
- package/dist/spinner-X23gI09z.d.mts +37 -0
- package/dist/state-I20jENMD.mjs +93 -0
- package/dist/types-DrN8pgyc.d.mts +107 -0
- package/package.json +1 -4
- package/dist/chunk-3UJ67DPX.js +0 -98
- package/dist/chunk-GE63YJOT.js +0 -865
- package/dist/chunk-MLKGABMK.js +0 -9
- package/dist/chunk-PERG4557.js +0 -74
- package/dist/chunk-VZ2DLGXX.js +0 -111
- package/dist/chunk-XIFXSNSD.js +0 -678
- package/dist/common/checkVersion.d.ts +0 -5
- package/dist/common/constants.d.ts +0 -14
- package/dist/common/errors/BeaconError.d.ts +0 -12
- package/dist/common/errors/ForceRetryError.d.ts +0 -5
- package/dist/common/events/index.d.ts +0 -2
- package/dist/common/events/internal.d.ts +0 -13
- package/dist/common/events/types.d.ts +0 -104
- package/dist/common/fallbackRendering.d.ts +0 -23
- package/dist/common/fallbackState.d.ts +0 -3
- package/dist/common/handleErrorWithSpaGuard.d.ts +0 -18
- package/dist/common/html.generated.d.ts +0 -3
- package/dist/common/i18n.d.ts +0 -23
- package/dist/common/isChunkError.d.ts +0 -1
- package/dist/common/isStaticAssetError.d.ts +0 -3
- package/dist/common/lastReloadTime.d.ts +0 -17
- package/dist/common/listen/index.d.ts +0 -1
- package/dist/common/listen/internal.d.ts +0 -2
- package/dist/common/log.d.ts +0 -1
- package/dist/common/logger.d.ts +0 -30
- package/dist/common/options.d.ts +0 -182
- package/dist/common/parseVersion.d.ts +0 -9
- package/dist/common/retryImport.d.ts +0 -43
- package/dist/common/retryOrchestrator.d.ts +0 -35
- package/dist/common/retryState.d.ts +0 -11
- package/dist/common/sendBeacon.d.ts +0 -2
- package/dist/common/serializeError.d.ts +0 -1
- package/dist/common/shouldIgnore.d.ts +0 -13
- package/dist/common/spinner.d.ts +0 -8
- package/dist/common/staticAssetRecovery.d.ts +0 -2
- package/dist/i18n/translations.d.ts +0 -2
- package/dist/runtime/debug/errorDispatchers.d.ts +0 -63
- package/dist/runtime/recommendedSetup.d.ts +0 -36
- package/dist/runtime/state.d.ts +0 -20
package/dist/chunk-GE63YJOT.js
DELETED
|
@@ -1,865 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
__export
|
|
3
|
-
} from "./chunk-MLKGABMK.js";
|
|
4
|
-
|
|
5
|
-
// package.json
|
|
6
|
-
var name = "@ovineko/spa-guard";
|
|
7
|
-
|
|
8
|
-
// src/common/constants.ts
|
|
9
|
-
var optionsWindowKey = "__SPA_GUARD_OPTIONS__";
|
|
10
|
-
var eventSubscribersWindowKey = /* @__PURE__ */ Symbol.for(`${name}:event-subscribers`);
|
|
11
|
-
var internalConfigWindowKey = /* @__PURE__ */ Symbol.for(`${name}:internal-config`);
|
|
12
|
-
var initializedKey = /* @__PURE__ */ Symbol.for(`${name}:initialized`);
|
|
13
|
-
var loggerWindowKey = /* @__PURE__ */ Symbol.for(`${name}:logger`);
|
|
14
|
-
var RETRY_ID_PARAM = "spaGuardRetryId";
|
|
15
|
-
var RETRY_ATTEMPT_PARAM = "spaGuardRetryAttempt";
|
|
16
|
-
var CACHE_BUST_PARAM = "spaGuardCacheBust";
|
|
17
|
-
var versionCheckStateWindowKey = /* @__PURE__ */ Symbol.for(`${name}:version-check-state`);
|
|
18
|
-
var inMemoryLastReloadKey = /* @__PURE__ */ Symbol.for(`${name}:in-memory-last-reload`);
|
|
19
|
-
var staticAssetRecoveryKey = /* @__PURE__ */ Symbol.for(`${name}:static-asset-recovery`);
|
|
20
|
-
var debugSyncErrorEventType = "spa-guard:debug-sync-error";
|
|
21
|
-
var spinnerStateWindowKey = /* @__PURE__ */ Symbol.for(`${name}:spinner-state`);
|
|
22
|
-
var fallbackModeKey = /* @__PURE__ */ Symbol.for(`${name}:fallback-mode`);
|
|
23
|
-
|
|
24
|
-
// src/common/events/internal.ts
|
|
25
|
-
if (globalThis.window && !globalThis.window[eventSubscribersWindowKey]) {
|
|
26
|
-
globalThis.window[eventSubscribersWindowKey] = /* @__PURE__ */ new Set();
|
|
27
|
-
}
|
|
28
|
-
if (globalThis.window && !globalThis.window[internalConfigWindowKey]) {
|
|
29
|
-
globalThis.window[internalConfigWindowKey] = {
|
|
30
|
-
defaultRetryEnabled: true,
|
|
31
|
-
initialized: false
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
var subscribers = globalThis.window?.[eventSubscribersWindowKey] ?? /* @__PURE__ */ new Set();
|
|
35
|
-
var internalConfig = globalThis.window?.[internalConfigWindowKey] ?? {
|
|
36
|
-
defaultRetryEnabled: true,
|
|
37
|
-
initialized: false
|
|
38
|
-
};
|
|
39
|
-
var setLogger = (logger) => {
|
|
40
|
-
if (globalThis.window !== void 0) {
|
|
41
|
-
globalThis.window[loggerWindowKey] = logger;
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
var getLogger = () => {
|
|
45
|
-
return globalThis.window?.[loggerWindowKey];
|
|
46
|
-
};
|
|
47
|
-
var emitEvent = (event, options) => {
|
|
48
|
-
if (!options?.silent) {
|
|
49
|
-
getLogger()?.logEvent(event);
|
|
50
|
-
}
|
|
51
|
-
subscribers.forEach((cb) => {
|
|
52
|
-
try {
|
|
53
|
-
cb(event);
|
|
54
|
-
} catch {
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
};
|
|
58
|
-
var subscribe = (cb) => {
|
|
59
|
-
subscribers.add(cb);
|
|
60
|
-
return () => subscribers.delete(cb);
|
|
61
|
-
};
|
|
62
|
-
var isInitialized = () => {
|
|
63
|
-
return internalConfig.initialized;
|
|
64
|
-
};
|
|
65
|
-
var markInitialized = () => {
|
|
66
|
-
internalConfig.initialized = true;
|
|
67
|
-
if (globalThis.window !== void 0) {
|
|
68
|
-
globalThis.window[initializedKey] = true;
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
var disableDefaultRetry = () => {
|
|
72
|
-
internalConfig.defaultRetryEnabled = false;
|
|
73
|
-
};
|
|
74
|
-
var enableDefaultRetry = () => {
|
|
75
|
-
internalConfig.defaultRetryEnabled = true;
|
|
76
|
-
};
|
|
77
|
-
var isDefaultRetryEnabled = () => {
|
|
78
|
-
return internalConfig.defaultRetryEnabled;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// src/common/i18n.ts
|
|
82
|
-
function applyI18n(container, t) {
|
|
83
|
-
const contentEls = container.querySelectorAll("[data-spa-guard-content]");
|
|
84
|
-
for (const el of contentEls) {
|
|
85
|
-
const key = el.dataset.spaGuardContent;
|
|
86
|
-
if (key && key in t) {
|
|
87
|
-
const value = t[key];
|
|
88
|
-
if (typeof value === "string") {
|
|
89
|
-
el.textContent = value;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
const actionEls = container.querySelectorAll("[data-spa-guard-action]");
|
|
94
|
-
for (const el of actionEls) {
|
|
95
|
-
const action = el.dataset.spaGuardAction;
|
|
96
|
-
const tKey = action === "try-again" ? "tryAgain" : action;
|
|
97
|
-
if (tKey && tKey in t) {
|
|
98
|
-
const value = t[tKey];
|
|
99
|
-
if (typeof value === "string") {
|
|
100
|
-
el.textContent = value;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (t.rtl) {
|
|
105
|
-
for (const child of container.children) {
|
|
106
|
-
if (child instanceof HTMLElement && child.tagName !== "STYLE") {
|
|
107
|
-
child.style.direction = "rtl";
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
function getI18n() {
|
|
113
|
-
try {
|
|
114
|
-
const el = document.querySelector('meta[name="spa-guard-i18n"]');
|
|
115
|
-
if (!el) {
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
const content = el.getAttribute("content");
|
|
119
|
-
if (!content) {
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
return JSON.parse(content);
|
|
123
|
-
} catch {
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
function setTranslations(translations) {
|
|
128
|
-
let el = document.querySelector('meta[name="spa-guard-i18n"]');
|
|
129
|
-
if (!el) {
|
|
130
|
-
el = document.createElement("meta");
|
|
131
|
-
el.setAttribute("name", "spa-guard-i18n");
|
|
132
|
-
document.head.append(el);
|
|
133
|
-
}
|
|
134
|
-
el.setAttribute("content", JSON.stringify(translations));
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// src/common/html.generated.ts
|
|
138
|
-
var defaultErrorFallbackHtml = `<style>.spa-guard-error-id:has(.spa-guard-retry-id:empty){display:none}.spa-guard-error-id{font-family:ui-monospace,SFMono-Regular,Consolas,"Liberation Mono",Menlo,monospace}.spa-guard-fallback-root{display:flex;align-items:center;justify-content:center;min-height:100vh;padding:2rem;font-family:system-ui,sans-serif;background:#fff;color:#1a1a1a;color-scheme:light dark}.spa-guard-fallback-icon{stroke:#b0b0b0}.spa-guard-fallback-message{color:#666}.spa-guard-fallback-muted{color:#999}.spa-guard-btn-secondary{border:1px solid #d0d0d0;background:#fff;color:#333}.spa-guard-btn-primary{border:1px solid transparent;background:#111;color:#fff}@media (prefers-color-scheme:dark){.spa-guard-fallback-root{background:#111318;color:#e7eaf0}.spa-guard-fallback-icon{stroke:#8b95a7}.spa-guard-fallback-message{color:#b8bfca}.spa-guard-fallback-muted{color:#8b95a7}.spa-guard-btn-secondary{border-color:#3b4351;background:#1a1f28;color:#d8deea}.spa-guard-btn-primary{background:#e7eaf0;color:#151922}}</style><div class="spa-guard-fallback-root"><div style="text-align:center;max-width:480px"><div style="margin-bottom:1.5rem"><svg class="spa-guard-fallback-icon" xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg></div><h1 data-spa-guard-content="heading" style="font-size:1.375rem;font-weight:600;margin:0 0 .5rem;line-height:1.3">Something went wrong</h1><p data-spa-guard-content="message" class="spa-guard-fallback-message" style="max-width:600px;margin:0 auto 1.5rem;font-size:.9375rem;line-height:1.5">Please refresh the page to continue.</p><div style="display:flex;gap:.5rem;justify-content:center;flex-wrap:wrap"><button data-spa-guard-action="try-again" type="button" class="spa-guard-btn-secondary" style="display:none;padding:.5rem 1.25rem;font-size:.875rem;font-family:inherit;border-radius:6px;cursor:pointer;line-height:1.5">Try again</button> <button data-spa-guard-action="reload" type="button" class="spa-guard-btn-primary" style="padding:.5rem 1.25rem;font-size:.875rem;font-family:inherit;border-radius:6px;cursor:pointer;line-height:1.5">Reload page</button></div><p class="spa-guard-error-id spa-guard-fallback-muted" style="margin-top:1.5rem;font-size:.6875rem">Error ID: <span class="spa-guard-retry-id"></span></p></div></div>`;
|
|
139
|
-
var defaultLoadingFallbackHtml = `<style>.spa-guard-loading-root{display:flex;align-items:center;justify-content:center;min-height:100vh;padding:2rem;font-family:system-ui,sans-serif;background:#fff;color:#1a1a1a;color-scheme:light dark}.spa-guard-loading-muted{color:#999}@media (prefers-color-scheme:dark){.spa-guard-loading-root{background:#111318;color:#e7eaf0}.spa-guard-loading-muted{color:#8b95a7}}</style><div class="spa-guard-loading-root"><div style="text-align:center"><div data-spa-guard-spinner style="margin-bottom:1.25rem"></div><h2 data-spa-guard-content="loading" style="font-size:1.125rem;font-weight:600;margin:0 0 .25rem">Loading...</h2><p data-spa-guard-section="retrying" class="spa-guard-loading-muted" style="display:none;font-size:.8125rem;margin:.5rem 0 0"><span data-spa-guard-content="retrying">Retry attempt</span> <span data-spa-guard-content="attempt"></span></p></div></div>`;
|
|
140
|
-
var defaultSpinnerHtml = `<svg width="40" height="40" viewBox="0 0 40 40" style="animation:spa-guard-spin .8s linear infinite"><circle cx="20" cy="20" r="16" fill="none" stroke="#e8e8e8" stroke-width="3"/><circle cx="20" cy="20" r="16" fill="none" stroke="#666" stroke-width="3" stroke-dasharray="80" stroke-dashoffset="60" stroke-linecap="round"/></svg><style>@keyframes spa-guard-spin{to{transform:rotate(360deg)}}</style>`;
|
|
141
|
-
|
|
142
|
-
// src/common/options.ts
|
|
143
|
-
var options_exports = {};
|
|
144
|
-
__export(options_exports, {
|
|
145
|
-
getOptions: () => getOptions,
|
|
146
|
-
optionsWindowKey: () => optionsWindowKey
|
|
147
|
-
});
|
|
148
|
-
var defaultOptions = {
|
|
149
|
-
checkVersion: {
|
|
150
|
-
cache: "no-store",
|
|
151
|
-
interval: 3e5,
|
|
152
|
-
mode: "html",
|
|
153
|
-
onUpdate: "reload"
|
|
154
|
-
},
|
|
155
|
-
enableRetryReset: true,
|
|
156
|
-
errors: {
|
|
157
|
-
forceRetry: [],
|
|
158
|
-
ignore: []
|
|
159
|
-
},
|
|
160
|
-
handleUnhandledRejections: {
|
|
161
|
-
retry: true,
|
|
162
|
-
sendBeacon: true
|
|
163
|
-
},
|
|
164
|
-
html: {
|
|
165
|
-
fallback: {
|
|
166
|
-
content: defaultErrorFallbackHtml,
|
|
167
|
-
selector: "body"
|
|
168
|
-
},
|
|
169
|
-
loading: {
|
|
170
|
-
content: defaultLoadingFallbackHtml
|
|
171
|
-
},
|
|
172
|
-
spinner: {
|
|
173
|
-
background: "#fff",
|
|
174
|
-
disabled: false
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
lazyRetry: {
|
|
178
|
-
callReloadOnFailure: true,
|
|
179
|
-
retryDelays: [1e3, 2e3]
|
|
180
|
-
},
|
|
181
|
-
minTimeBetweenResets: 5e3,
|
|
182
|
-
reloadDelays: [1e3, 2e3, 5e3],
|
|
183
|
-
staticAssets: {
|
|
184
|
-
autoRecover: true,
|
|
185
|
-
recoveryDelay: 500
|
|
186
|
-
},
|
|
187
|
-
useRetryId: true
|
|
188
|
-
};
|
|
189
|
-
var getOptions = () => {
|
|
190
|
-
const windowOptions = globalThis.window?.[optionsWindowKey];
|
|
191
|
-
return {
|
|
192
|
-
...defaultOptions,
|
|
193
|
-
...windowOptions,
|
|
194
|
-
checkVersion: {
|
|
195
|
-
...defaultOptions.checkVersion,
|
|
196
|
-
...windowOptions?.checkVersion
|
|
197
|
-
},
|
|
198
|
-
errors: {
|
|
199
|
-
...defaultOptions.errors,
|
|
200
|
-
...windowOptions?.errors
|
|
201
|
-
},
|
|
202
|
-
handleUnhandledRejections: {
|
|
203
|
-
...defaultOptions.handleUnhandledRejections,
|
|
204
|
-
...windowOptions?.handleUnhandledRejections
|
|
205
|
-
},
|
|
206
|
-
html: {
|
|
207
|
-
fallback: {
|
|
208
|
-
...defaultOptions.html?.fallback,
|
|
209
|
-
...windowOptions?.html?.fallback
|
|
210
|
-
},
|
|
211
|
-
loading: {
|
|
212
|
-
...defaultOptions.html?.loading,
|
|
213
|
-
...windowOptions?.html?.loading
|
|
214
|
-
},
|
|
215
|
-
spinner: {
|
|
216
|
-
...defaultOptions.html?.spinner,
|
|
217
|
-
...windowOptions?.html?.spinner
|
|
218
|
-
}
|
|
219
|
-
},
|
|
220
|
-
lazyRetry: {
|
|
221
|
-
...defaultOptions.lazyRetry,
|
|
222
|
-
...windowOptions?.lazyRetry
|
|
223
|
-
},
|
|
224
|
-
reportBeacon: {
|
|
225
|
-
...defaultOptions.reportBeacon,
|
|
226
|
-
...windowOptions?.reportBeacon
|
|
227
|
-
},
|
|
228
|
-
staticAssets: {
|
|
229
|
-
...defaultOptions.staticAssets,
|
|
230
|
-
...windowOptions?.staticAssets
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
// src/common/fallbackState.ts
|
|
236
|
-
var isInFallbackMode = () => {
|
|
237
|
-
if (globalThis.window === void 0) {
|
|
238
|
-
return false;
|
|
239
|
-
}
|
|
240
|
-
return globalThis.window[fallbackModeKey] === true;
|
|
241
|
-
};
|
|
242
|
-
var setFallbackMode = () => {
|
|
243
|
-
if (globalThis.window === void 0) {
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
globalThis.window[fallbackModeKey] = true;
|
|
247
|
-
};
|
|
248
|
-
var resetFallbackMode = () => {
|
|
249
|
-
if (globalThis.window === void 0) {
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
globalThis.window[fallbackModeKey] = false;
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
// src/common/errors/ForceRetryError.ts
|
|
256
|
-
var FORCE_RETRY_MAGIC = "__SPA_GUARD_FORCE_RETRY__";
|
|
257
|
-
var ForceRetryError = class extends Error {
|
|
258
|
-
constructor(message, options) {
|
|
259
|
-
super(`${FORCE_RETRY_MAGIC}${message ?? ""}`, options);
|
|
260
|
-
this.name = "ForceRetryError";
|
|
261
|
-
}
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
// src/common/retryState.ts
|
|
265
|
-
var getRetryStateFromUrl = () => {
|
|
266
|
-
try {
|
|
267
|
-
const params = new URLSearchParams(globalThis.window.location.search);
|
|
268
|
-
const retryId = params.get(RETRY_ID_PARAM);
|
|
269
|
-
const retryAttempt = params.get(RETRY_ATTEMPT_PARAM);
|
|
270
|
-
if (retryId && retryAttempt) {
|
|
271
|
-
if (!/^\d+$/.test(retryAttempt)) {
|
|
272
|
-
return null;
|
|
273
|
-
}
|
|
274
|
-
const parsed = parseInt(retryAttempt, 10);
|
|
275
|
-
if (Number.isNaN(parsed) || !Number.isFinite(parsed) || parsed < 0) {
|
|
276
|
-
return null;
|
|
277
|
-
}
|
|
278
|
-
return {
|
|
279
|
-
retryAttempt: parsed,
|
|
280
|
-
retryId
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
return null;
|
|
284
|
-
} catch {
|
|
285
|
-
return null;
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
var generateRetryId = () => {
|
|
289
|
-
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
290
|
-
return crypto.randomUUID();
|
|
291
|
-
}
|
|
292
|
-
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
293
|
-
const array = new Uint32Array(2);
|
|
294
|
-
crypto.getRandomValues(array);
|
|
295
|
-
return `${Date.now()}-${array[0].toString(36)}-${array[1].toString(36)}`;
|
|
296
|
-
}
|
|
297
|
-
return `${Date.now()}-${Math.random().toString(36).slice(2, 15)}`;
|
|
298
|
-
};
|
|
299
|
-
var getRetryAttemptFromUrl = () => {
|
|
300
|
-
try {
|
|
301
|
-
const params = new URLSearchParams(globalThis.window.location.search);
|
|
302
|
-
const retryAttempt = params.get(RETRY_ATTEMPT_PARAM);
|
|
303
|
-
if (retryAttempt) {
|
|
304
|
-
if (!/^\d+$/.test(retryAttempt)) {
|
|
305
|
-
return null;
|
|
306
|
-
}
|
|
307
|
-
const parsed = parseInt(retryAttempt, 10);
|
|
308
|
-
if (Number.isNaN(parsed) || !Number.isFinite(parsed) || parsed < 0) {
|
|
309
|
-
return null;
|
|
310
|
-
}
|
|
311
|
-
return parsed;
|
|
312
|
-
}
|
|
313
|
-
return null;
|
|
314
|
-
} catch {
|
|
315
|
-
return null;
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
var getRetryInfoForBeacon = () => {
|
|
319
|
-
const retryState = getRetryStateFromUrl();
|
|
320
|
-
if (!retryState) {
|
|
321
|
-
return {};
|
|
322
|
-
}
|
|
323
|
-
return {
|
|
324
|
-
retryAttempt: retryState.retryAttempt,
|
|
325
|
-
retryId: retryState.retryId
|
|
326
|
-
};
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
// src/common/fallbackRendering.ts
|
|
330
|
-
var showLoadingUI = (attempt) => {
|
|
331
|
-
const options = getOptions();
|
|
332
|
-
const loadingHtml = options.html?.loading?.content;
|
|
333
|
-
if (!loadingHtml) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
const selector = options.html?.fallback?.selector ?? "body";
|
|
337
|
-
try {
|
|
338
|
-
const targetElement = document.querySelector(selector);
|
|
339
|
-
if (!targetElement) {
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
const container = document.createElement("div");
|
|
343
|
-
container.innerHTML = loadingHtml;
|
|
344
|
-
const t = getI18n();
|
|
345
|
-
if (t) {
|
|
346
|
-
applyI18n(container, t);
|
|
347
|
-
}
|
|
348
|
-
targetElement.innerHTML = container.innerHTML;
|
|
349
|
-
const retrySection = targetElement.querySelector('[data-spa-guard-section="retrying"]');
|
|
350
|
-
if (retrySection) {
|
|
351
|
-
const retrySectionEl = retrySection;
|
|
352
|
-
retrySectionEl.style.display = "";
|
|
353
|
-
retrySectionEl.style.visibility = "visible";
|
|
354
|
-
}
|
|
355
|
-
const attemptElements = targetElement.querySelectorAll('[data-spa-guard-content="attempt"]');
|
|
356
|
-
for (const el of attemptElements) {
|
|
357
|
-
el.textContent = String(attempt);
|
|
358
|
-
}
|
|
359
|
-
const spinnerEl = targetElement.querySelector("[data-spa-guard-spinner]");
|
|
360
|
-
if (spinnerEl) {
|
|
361
|
-
const spinnerOptions = options.html?.spinner;
|
|
362
|
-
if (spinnerOptions?.disabled) {
|
|
363
|
-
spinnerEl.style.display = "none";
|
|
364
|
-
} else if (spinnerOptions?.content) {
|
|
365
|
-
spinnerEl.innerHTML = spinnerOptions.content;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
} catch {
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
var showFallbackUI = (override) => {
|
|
372
|
-
const options = getOptions();
|
|
373
|
-
const fallbackHtml = options.html?.fallback?.content;
|
|
374
|
-
const selector = options.html?.fallback?.selector ?? "body";
|
|
375
|
-
if (!fallbackHtml) {
|
|
376
|
-
getLogger()?.noFallbackConfigured();
|
|
377
|
-
emitEvent({ name: "fallback-ui-not-rendered", reason: "no-html-configured" });
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
try {
|
|
381
|
-
const targetElement = document.querySelector(selector);
|
|
382
|
-
if (!targetElement) {
|
|
383
|
-
getLogger()?.fallbackTargetNotFound(selector);
|
|
384
|
-
emitEvent({ name: "fallback-ui-not-rendered", reason: "target-not-found", selector });
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
const container = document.createElement("div");
|
|
388
|
-
container.innerHTML = fallbackHtml;
|
|
389
|
-
const t = getI18n();
|
|
390
|
-
if (t) {
|
|
391
|
-
applyI18n(container, t);
|
|
392
|
-
}
|
|
393
|
-
targetElement.innerHTML = container.innerHTML;
|
|
394
|
-
const reloadBtn = targetElement.querySelector('[data-spa-guard-action="reload"]');
|
|
395
|
-
if (reloadBtn) {
|
|
396
|
-
reloadBtn.addEventListener("click", () => globalThis.window.location.reload());
|
|
397
|
-
}
|
|
398
|
-
const retryId = override?.retryId ?? getRetryStateFromUrl()?.retryId;
|
|
399
|
-
if (retryId) {
|
|
400
|
-
const retryIdElements = document.getElementsByClassName("spa-guard-retry-id");
|
|
401
|
-
for (const element of retryIdElements) {
|
|
402
|
-
element.textContent = retryId;
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
emitEvent({
|
|
406
|
-
name: "fallback-ui-shown"
|
|
407
|
-
});
|
|
408
|
-
} catch (error) {
|
|
409
|
-
getLogger()?.fallbackInjectFailed(error);
|
|
410
|
-
}
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
// src/common/lastReloadTime.ts
|
|
414
|
-
var STORAGE_KEY = "__spa_guard_last_reload_timestamp__";
|
|
415
|
-
var RESET_INFO_KEY = "__spa_guard_last_retry_reset__";
|
|
416
|
-
if (globalThis.window && !globalThis.window[inMemoryLastReloadKey]) {
|
|
417
|
-
globalThis.window[inMemoryLastReloadKey] = {
|
|
418
|
-
resetInfo: null,
|
|
419
|
-
storage: null
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
var getInMemoryState = () => {
|
|
423
|
-
const w = globalThis.window;
|
|
424
|
-
if (!w) {
|
|
425
|
-
return { resetInfo: null, storage: null };
|
|
426
|
-
}
|
|
427
|
-
return w[inMemoryLastReloadKey] ?? (w[inMemoryLastReloadKey] = { resetInfo: null, storage: null });
|
|
428
|
-
};
|
|
429
|
-
var hasSessionStorage = () => {
|
|
430
|
-
try {
|
|
431
|
-
return globalThis.window !== void 0 && typeof sessionStorage !== "undefined";
|
|
432
|
-
} catch {
|
|
433
|
-
return false;
|
|
434
|
-
}
|
|
435
|
-
};
|
|
436
|
-
var setLastReloadTime = (retryId, attemptNumber) => {
|
|
437
|
-
const data = {
|
|
438
|
-
attemptNumber,
|
|
439
|
-
retryId,
|
|
440
|
-
timestamp: Date.now()
|
|
441
|
-
};
|
|
442
|
-
if (hasSessionStorage()) {
|
|
443
|
-
try {
|
|
444
|
-
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(data));
|
|
445
|
-
} catch {
|
|
446
|
-
getInMemoryState().storage = data;
|
|
447
|
-
}
|
|
448
|
-
} else {
|
|
449
|
-
getInMemoryState().storage = data;
|
|
450
|
-
}
|
|
451
|
-
};
|
|
452
|
-
var getLastReloadTime = () => {
|
|
453
|
-
if (hasSessionStorage()) {
|
|
454
|
-
try {
|
|
455
|
-
const stored = sessionStorage.getItem(STORAGE_KEY);
|
|
456
|
-
if (stored) {
|
|
457
|
-
return JSON.parse(stored);
|
|
458
|
-
}
|
|
459
|
-
} catch {
|
|
460
|
-
try {
|
|
461
|
-
sessionStorage.removeItem(STORAGE_KEY);
|
|
462
|
-
} catch {
|
|
463
|
-
}
|
|
464
|
-
return getInMemoryState().storage;
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
return getInMemoryState().storage;
|
|
468
|
-
};
|
|
469
|
-
var clearLastReloadTime = () => {
|
|
470
|
-
if (hasSessionStorage()) {
|
|
471
|
-
try {
|
|
472
|
-
sessionStorage.removeItem(STORAGE_KEY);
|
|
473
|
-
} catch {
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
getInMemoryState().storage = null;
|
|
477
|
-
};
|
|
478
|
-
var shouldResetRetryCycle = (retryState, reloadDelays, minTimeBetweenResets = 5e3) => {
|
|
479
|
-
if (retryState.retryAttempt === 0) {
|
|
480
|
-
return false;
|
|
481
|
-
}
|
|
482
|
-
const lastReload = getLastReloadTime();
|
|
483
|
-
if (!lastReload) {
|
|
484
|
-
return false;
|
|
485
|
-
}
|
|
486
|
-
if (lastReload.retryId !== retryState.retryId) {
|
|
487
|
-
return false;
|
|
488
|
-
}
|
|
489
|
-
const lastReset = getLastRetryResetInfo();
|
|
490
|
-
if (lastReset) {
|
|
491
|
-
const timeSinceLastReset = Date.now() - lastReset.timestamp;
|
|
492
|
-
if (timeSinceLastReset < minTimeBetweenResets) {
|
|
493
|
-
return false;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
const timeSinceReload = Date.now() - lastReload.timestamp;
|
|
497
|
-
const previousDelayIndex = lastReload.attemptNumber - 1;
|
|
498
|
-
const previousDelay = reloadDelays[previousDelayIndex] ?? 1e3;
|
|
499
|
-
const PAGE_LOAD_BUFFER_MS = 3e4;
|
|
500
|
-
return timeSinceReload > previousDelay + PAGE_LOAD_BUFFER_MS;
|
|
501
|
-
};
|
|
502
|
-
var setLastRetryResetInfo = (previousRetryId) => {
|
|
503
|
-
const data = {
|
|
504
|
-
previousRetryId,
|
|
505
|
-
timestamp: Date.now()
|
|
506
|
-
};
|
|
507
|
-
if (hasSessionStorage()) {
|
|
508
|
-
try {
|
|
509
|
-
sessionStorage.setItem(RESET_INFO_KEY, JSON.stringify(data));
|
|
510
|
-
} catch {
|
|
511
|
-
getInMemoryState().resetInfo = data;
|
|
512
|
-
}
|
|
513
|
-
} else {
|
|
514
|
-
getInMemoryState().resetInfo = data;
|
|
515
|
-
}
|
|
516
|
-
};
|
|
517
|
-
var getLastRetryResetInfo = () => {
|
|
518
|
-
if (hasSessionStorage()) {
|
|
519
|
-
try {
|
|
520
|
-
const stored = sessionStorage.getItem(RESET_INFO_KEY);
|
|
521
|
-
if (stored) {
|
|
522
|
-
return JSON.parse(stored);
|
|
523
|
-
}
|
|
524
|
-
} catch {
|
|
525
|
-
try {
|
|
526
|
-
sessionStorage.removeItem(RESET_INFO_KEY);
|
|
527
|
-
} catch {
|
|
528
|
-
}
|
|
529
|
-
return getInMemoryState().resetInfo;
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
return getInMemoryState().resetInfo;
|
|
533
|
-
};
|
|
534
|
-
var clearLastRetryResetInfo = () => {
|
|
535
|
-
if (hasSessionStorage()) {
|
|
536
|
-
try {
|
|
537
|
-
sessionStorage.removeItem(RESET_INFO_KEY);
|
|
538
|
-
} catch {
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
getInMemoryState().resetInfo = null;
|
|
542
|
-
};
|
|
543
|
-
|
|
544
|
-
// src/common/shouldIgnore.ts
|
|
545
|
-
var shouldIgnoreMessages = (messages) => {
|
|
546
|
-
const options = getOptions();
|
|
547
|
-
const ignorePatterns = (options.errors?.ignore ?? []).filter((p) => p !== "");
|
|
548
|
-
if (ignorePatterns.length === 0) {
|
|
549
|
-
return false;
|
|
550
|
-
}
|
|
551
|
-
const validMessages = messages.filter((msg) => typeof msg === "string");
|
|
552
|
-
return validMessages.some(
|
|
553
|
-
(message) => ignorePatterns.some((pattern) => message.includes(pattern))
|
|
554
|
-
);
|
|
555
|
-
};
|
|
556
|
-
var shouldForceRetry = (messages) => {
|
|
557
|
-
const options = getOptions();
|
|
558
|
-
const forceRetryPatterns = [...options.errors?.forceRetry ?? [], FORCE_RETRY_MAGIC].filter(
|
|
559
|
-
(p) => p !== ""
|
|
560
|
-
);
|
|
561
|
-
const validMessages = messages.filter((msg) => typeof msg === "string");
|
|
562
|
-
return validMessages.some(
|
|
563
|
-
(message) => forceRetryPatterns.some((pattern) => message.includes(pattern))
|
|
564
|
-
);
|
|
565
|
-
};
|
|
566
|
-
var shouldIgnoreBeacon = (beacon) => {
|
|
567
|
-
return shouldIgnoreMessages([beacon.errorMessage, beacon.eventMessage]);
|
|
568
|
-
};
|
|
569
|
-
|
|
570
|
-
// src/common/sendBeacon.ts
|
|
571
|
-
var sendBeacon = (beacon) => {
|
|
572
|
-
if (shouldIgnoreBeacon(beacon)) {
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
|
-
const options = getOptions();
|
|
576
|
-
if (!options.reportBeacon?.endpoint) {
|
|
577
|
-
getLogger()?.noBeaconEndpoint();
|
|
578
|
-
return;
|
|
579
|
-
}
|
|
580
|
-
const enrichedBeacon = options.appName ? { ...beacon, appName: options.appName } : beacon;
|
|
581
|
-
const body = JSON.stringify(enrichedBeacon);
|
|
582
|
-
const isSendBeaconAvailable = typeof globalThis.window?.navigator?.sendBeacon === "function";
|
|
583
|
-
const isSentBeacon = isSendBeaconAvailable && globalThis.window.navigator.sendBeacon(options.reportBeacon.endpoint, body);
|
|
584
|
-
if (!isSentBeacon && typeof fetch === "function") {
|
|
585
|
-
fetch(options.reportBeacon.endpoint, { body, keepalive: true, method: "POST" }).catch(
|
|
586
|
-
(error) => {
|
|
587
|
-
getLogger()?.beaconSendFailed(error);
|
|
588
|
-
}
|
|
589
|
-
);
|
|
590
|
-
}
|
|
591
|
-
};
|
|
592
|
-
|
|
593
|
-
// src/common/retryOrchestrator.ts
|
|
594
|
-
var retryOrchestratorKey = /* @__PURE__ */ Symbol.for(`${name}:retry-orchestrator`);
|
|
595
|
-
var createFreshState = () => ({
|
|
596
|
-
attempt: 0,
|
|
597
|
-
lastSource: void 0,
|
|
598
|
-
lastTriggerTime: void 0,
|
|
599
|
-
phase: "idle",
|
|
600
|
-
retryId: null,
|
|
601
|
-
timer: null
|
|
602
|
-
});
|
|
603
|
-
var getState = () => {
|
|
604
|
-
if (globalThis.window === void 0) {
|
|
605
|
-
return createFreshState();
|
|
606
|
-
}
|
|
607
|
-
const w = globalThis.window;
|
|
608
|
-
if (!w[retryOrchestratorKey]) {
|
|
609
|
-
w[retryOrchestratorKey] = createFreshState();
|
|
610
|
-
}
|
|
611
|
-
return w[retryOrchestratorKey];
|
|
612
|
-
};
|
|
613
|
-
var setState = (updates) => {
|
|
614
|
-
if (globalThis.window === void 0) {
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
const w = globalThis.window;
|
|
618
|
-
if (!w[retryOrchestratorKey]) {
|
|
619
|
-
w[retryOrchestratorKey] = createFreshState();
|
|
620
|
-
}
|
|
621
|
-
Object.assign(w[retryOrchestratorKey], updates);
|
|
622
|
-
};
|
|
623
|
-
var buildReloadUrl = (retryId, attempt, cacheBust, includeRetryId = true) => {
|
|
624
|
-
const url = new URL(globalThis.window.location.href);
|
|
625
|
-
if (includeRetryId) {
|
|
626
|
-
url.searchParams.set(RETRY_ID_PARAM, retryId);
|
|
627
|
-
}
|
|
628
|
-
url.searchParams.set(RETRY_ATTEMPT_PARAM, String(attempt));
|
|
629
|
-
if (cacheBust) {
|
|
630
|
-
url.searchParams.set(CACHE_BUST_PARAM, String(Date.now()));
|
|
631
|
-
}
|
|
632
|
-
return url.toString();
|
|
633
|
-
};
|
|
634
|
-
var parseAttemptFromUrl = () => {
|
|
635
|
-
try {
|
|
636
|
-
const params = new URLSearchParams(globalThis.window.location.search);
|
|
637
|
-
const raw = params.get(RETRY_ATTEMPT_PARAM);
|
|
638
|
-
if (!raw) {
|
|
639
|
-
return null;
|
|
640
|
-
}
|
|
641
|
-
if (!/^\d+$/.test(raw)) {
|
|
642
|
-
return null;
|
|
643
|
-
}
|
|
644
|
-
const parsed = parseInt(raw, 10);
|
|
645
|
-
if (Number.isNaN(parsed) || !Number.isFinite(parsed) || parsed < 0) {
|
|
646
|
-
return null;
|
|
647
|
-
}
|
|
648
|
-
return parsed;
|
|
649
|
-
} catch {
|
|
650
|
-
return null;
|
|
651
|
-
}
|
|
652
|
-
};
|
|
653
|
-
var parseRetryIdFromUrl = () => {
|
|
654
|
-
try {
|
|
655
|
-
const params = new URLSearchParams(globalThis.window.location.search);
|
|
656
|
-
return params.get(RETRY_ID_PARAM);
|
|
657
|
-
} catch {
|
|
658
|
-
return null;
|
|
659
|
-
}
|
|
660
|
-
};
|
|
661
|
-
var clearRetryFromUrl = () => {
|
|
662
|
-
try {
|
|
663
|
-
const url = new URL(globalThis.window.location.href);
|
|
664
|
-
url.searchParams.delete(RETRY_ID_PARAM);
|
|
665
|
-
url.searchParams.delete(RETRY_ATTEMPT_PARAM);
|
|
666
|
-
url.searchParams.delete(CACHE_BUST_PARAM);
|
|
667
|
-
globalThis.window.history.replaceState(null, "", url.toString());
|
|
668
|
-
} catch (error) {
|
|
669
|
-
getLogger()?.error("clearRetryFromUrl failed", error);
|
|
670
|
-
}
|
|
671
|
-
};
|
|
672
|
-
var triggerRetry = (input = {}) => {
|
|
673
|
-
const state = getState();
|
|
674
|
-
if (state.phase === "fallback" || isInFallbackMode()) {
|
|
675
|
-
getLogger()?.fallbackAlreadyShown(input.error);
|
|
676
|
-
return { status: "fallback" };
|
|
677
|
-
}
|
|
678
|
-
if (state.phase === "scheduled") {
|
|
679
|
-
getLogger()?.reloadAlreadyScheduled(input.error);
|
|
680
|
-
return { reason: "already-scheduled", status: "deduped" };
|
|
681
|
-
}
|
|
682
|
-
if (!isDefaultRetryEnabled()) {
|
|
683
|
-
return { status: "retry-disabled" };
|
|
684
|
-
}
|
|
685
|
-
setState({ lastSource: input.source, lastTriggerTime: Date.now(), phase: "scheduled" });
|
|
686
|
-
try {
|
|
687
|
-
const options = getOptions();
|
|
688
|
-
const reloadDelays = options.reloadDelays ?? [1e3, 2e3, 5e3];
|
|
689
|
-
const useRetryId = options.useRetryId ?? true;
|
|
690
|
-
const enableRetryReset = options.enableRetryReset ?? true;
|
|
691
|
-
const minTimeBetweenResets = options.minTimeBetweenResets ?? 5e3;
|
|
692
|
-
const urlAttempt = parseAttemptFromUrl();
|
|
693
|
-
const urlRetryId = parseRetryIdFromUrl();
|
|
694
|
-
let currentAttempt = urlAttempt ?? 0;
|
|
695
|
-
let retryId = useRetryId && urlRetryId ? urlRetryId : generateRetryId();
|
|
696
|
-
getLogger()?.retryCycleStarting(retryId, currentAttempt);
|
|
697
|
-
if (enableRetryReset && urlRetryId && urlAttempt !== null && urlAttempt > 0) {
|
|
698
|
-
const retryStateForReset = { retryAttempt: urlAttempt, retryId: urlRetryId };
|
|
699
|
-
if (shouldResetRetryCycle(retryStateForReset, reloadDelays, minTimeBetweenResets)) {
|
|
700
|
-
const lastReload = getLastReloadTime();
|
|
701
|
-
const timeSinceReload = lastReload ? Date.now() - lastReload.timestamp : 0;
|
|
702
|
-
clearRetryFromUrl();
|
|
703
|
-
clearLastReloadTime();
|
|
704
|
-
setLastRetryResetInfo(urlRetryId);
|
|
705
|
-
const errorMsg2 = String(input.error);
|
|
706
|
-
emitEvent(
|
|
707
|
-
{
|
|
708
|
-
name: "retry-reset",
|
|
709
|
-
previousAttempt: urlAttempt,
|
|
710
|
-
previousRetryId: urlRetryId,
|
|
711
|
-
timeSinceReload
|
|
712
|
-
},
|
|
713
|
-
{ silent: shouldIgnoreMessages([errorMsg2]) }
|
|
714
|
-
);
|
|
715
|
-
currentAttempt = 0;
|
|
716
|
-
retryId = generateRetryId();
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
emitEvent({
|
|
720
|
-
error: input.error,
|
|
721
|
-
isRetrying: currentAttempt < reloadDelays.length,
|
|
722
|
-
name: "chunk-error"
|
|
723
|
-
});
|
|
724
|
-
if (currentAttempt >= reloadDelays.length) {
|
|
725
|
-
const errorMsg2 = String(input.error);
|
|
726
|
-
emitEvent(
|
|
727
|
-
{
|
|
728
|
-
finalAttempt: currentAttempt,
|
|
729
|
-
name: "retry-exhausted",
|
|
730
|
-
retryId
|
|
731
|
-
},
|
|
732
|
-
{ silent: shouldIgnoreMessages([errorMsg2]) }
|
|
733
|
-
);
|
|
734
|
-
sendBeacon({
|
|
735
|
-
errorMessage: "Exceeded maximum reload attempts",
|
|
736
|
-
eventName: "chunk_error_max_reloads",
|
|
737
|
-
retryAttempt: currentAttempt,
|
|
738
|
-
retryId,
|
|
739
|
-
serialized: JSON.stringify({
|
|
740
|
-
error: String(input.error),
|
|
741
|
-
retryAttempt: currentAttempt,
|
|
742
|
-
retryId
|
|
743
|
-
})
|
|
744
|
-
});
|
|
745
|
-
setState({ attempt: currentAttempt, phase: "fallback", retryId });
|
|
746
|
-
setFallbackMode();
|
|
747
|
-
clearRetryFromUrl();
|
|
748
|
-
showFallbackUI({ retryId });
|
|
749
|
-
return { status: "fallback" };
|
|
750
|
-
}
|
|
751
|
-
const nextAttempt = currentAttempt + 1;
|
|
752
|
-
const delay = reloadDelays[currentAttempt] ?? 1e3;
|
|
753
|
-
const errorMsg = String(input.error);
|
|
754
|
-
emitEvent(
|
|
755
|
-
{
|
|
756
|
-
attempt: nextAttempt,
|
|
757
|
-
delay,
|
|
758
|
-
name: "retry-attempt",
|
|
759
|
-
retryId
|
|
760
|
-
},
|
|
761
|
-
{ silent: shouldIgnoreMessages([errorMsg]) }
|
|
762
|
-
);
|
|
763
|
-
getLogger()?.retrySchedulingReload(retryId, nextAttempt, delay);
|
|
764
|
-
setState({ attempt: nextAttempt, retryId });
|
|
765
|
-
showLoadingUI(nextAttempt);
|
|
766
|
-
const timer = setTimeout(() => {
|
|
767
|
-
try {
|
|
768
|
-
if (useRetryId && enableRetryReset) {
|
|
769
|
-
setLastReloadTime(retryId, nextAttempt);
|
|
770
|
-
}
|
|
771
|
-
const reloadUrl = buildReloadUrl(retryId, nextAttempt, input.cacheBust, useRetryId);
|
|
772
|
-
globalThis.window.location.href = reloadUrl;
|
|
773
|
-
} catch (navError) {
|
|
774
|
-
getLogger()?.error("triggerRetry navigation failed", navError);
|
|
775
|
-
setState({ phase: "idle", timer: null });
|
|
776
|
-
}
|
|
777
|
-
}, delay);
|
|
778
|
-
setState({ timer });
|
|
779
|
-
return { status: "accepted" };
|
|
780
|
-
} catch (error) {
|
|
781
|
-
getLogger()?.error("triggerRetry internal error", error);
|
|
782
|
-
setState({ lastSource: void 0, lastTriggerTime: void 0, phase: "idle" });
|
|
783
|
-
return { status: "internal-error" };
|
|
784
|
-
}
|
|
785
|
-
};
|
|
786
|
-
var markRetryHealthyBoot = () => {
|
|
787
|
-
const state = getState();
|
|
788
|
-
if (state.timer !== null) {
|
|
789
|
-
clearTimeout(state.timer);
|
|
790
|
-
}
|
|
791
|
-
clearRetryFromUrl();
|
|
792
|
-
clearLastReloadTime();
|
|
793
|
-
clearLastRetryResetInfo();
|
|
794
|
-
setState(createFreshState());
|
|
795
|
-
resetFallbackMode();
|
|
796
|
-
};
|
|
797
|
-
var getRetrySnapshot = () => {
|
|
798
|
-
const state = getState();
|
|
799
|
-
return {
|
|
800
|
-
attempt: state.attempt,
|
|
801
|
-
lastSource: state.lastSource,
|
|
802
|
-
lastTriggerTime: state.lastTriggerTime,
|
|
803
|
-
phase: state.phase,
|
|
804
|
-
retryId: state.retryId
|
|
805
|
-
};
|
|
806
|
-
};
|
|
807
|
-
var setFallbackStateForDebug = () => {
|
|
808
|
-
const state = getState();
|
|
809
|
-
if (state.timer !== null) {
|
|
810
|
-
clearTimeout(state.timer);
|
|
811
|
-
}
|
|
812
|
-
setState({ phase: "fallback", timer: null });
|
|
813
|
-
setFallbackMode();
|
|
814
|
-
showFallbackUI({ retryId: state.retryId ?? void 0 });
|
|
815
|
-
};
|
|
816
|
-
var resetRetryOrchestratorForTests = () => {
|
|
817
|
-
const state = getState();
|
|
818
|
-
if (state.timer !== null) {
|
|
819
|
-
clearTimeout(state.timer);
|
|
820
|
-
}
|
|
821
|
-
if (globalThis.window !== void 0) {
|
|
822
|
-
globalThis.window[retryOrchestratorKey] = createFreshState();
|
|
823
|
-
}
|
|
824
|
-
resetFallbackMode();
|
|
825
|
-
};
|
|
826
|
-
|
|
827
|
-
export {
|
|
828
|
-
optionsWindowKey,
|
|
829
|
-
versionCheckStateWindowKey,
|
|
830
|
-
staticAssetRecoveryKey,
|
|
831
|
-
debugSyncErrorEventType,
|
|
832
|
-
spinnerStateWindowKey,
|
|
833
|
-
setLogger,
|
|
834
|
-
getLogger,
|
|
835
|
-
emitEvent,
|
|
836
|
-
subscribe,
|
|
837
|
-
isInitialized,
|
|
838
|
-
markInitialized,
|
|
839
|
-
disableDefaultRetry,
|
|
840
|
-
enableDefaultRetry,
|
|
841
|
-
isDefaultRetryEnabled,
|
|
842
|
-
applyI18n,
|
|
843
|
-
getI18n,
|
|
844
|
-
setTranslations,
|
|
845
|
-
defaultErrorFallbackHtml,
|
|
846
|
-
defaultLoadingFallbackHtml,
|
|
847
|
-
defaultSpinnerHtml,
|
|
848
|
-
getOptions,
|
|
849
|
-
options_exports,
|
|
850
|
-
getRetryStateFromUrl,
|
|
851
|
-
getRetryAttemptFromUrl,
|
|
852
|
-
getRetryInfoForBeacon,
|
|
853
|
-
isInFallbackMode,
|
|
854
|
-
resetFallbackMode,
|
|
855
|
-
getLastRetryResetInfo,
|
|
856
|
-
ForceRetryError,
|
|
857
|
-
shouldIgnoreMessages,
|
|
858
|
-
shouldForceRetry,
|
|
859
|
-
sendBeacon,
|
|
860
|
-
triggerRetry,
|
|
861
|
-
markRetryHealthyBoot,
|
|
862
|
-
getRetrySnapshot,
|
|
863
|
-
setFallbackStateForDebug,
|
|
864
|
-
resetRetryOrchestratorForTests
|
|
865
|
-
};
|