@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/README.md
CHANGED
|
@@ -7,198 +7,47 @@ Core runtime for spa-guard — chunk load error handling, version checking, spin
|
|
|
7
7
|
|
|
8
8
|
## Install
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
npm install @ovineko/spa-guard
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Usage
|
|
15
|
-
|
|
16
|
-
Call `recommendedSetup` once when your app boots. It dismisses the loading spinner, starts version checking, and returns a cleanup function.
|
|
10
|
+
**pnpm** (recommended):
|
|
17
11
|
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const cleanup = recommendedSetup();
|
|
22
|
-
// optionally call cleanup() to stop background checks
|
|
12
|
+
```bash
|
|
13
|
+
pnpm add @ovineko/spa-guard
|
|
23
14
|
```
|
|
24
15
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
By default, `recommendedSetup` uses `healthyBoot: "auto"`:
|
|
28
|
-
|
|
29
|
-
- if retry params exist in the URL, it waits a dynamic grace period and calls `markRetryHealthyBoot()` only when the orchestrator phase is still `idle`.
|
|
30
|
-
- if no retry params exist, it does nothing.
|
|
31
|
-
|
|
32
|
-
Auto grace period formula:
|
|
33
|
-
|
|
34
|
-
- `max(5000, max(reloadDelays)+1000, sum(lazyRetry.retryDelays)+1000)`
|
|
35
|
-
|
|
36
|
-
If you want strict control, switch to manual healthy-boot mode and call `markRetryHealthyBoot()` yourself.
|
|
37
|
-
|
|
38
|
-
```ts
|
|
39
|
-
import { markRetryHealthyBoot } from "@ovineko/spa-guard";
|
|
40
|
-
import { recommendedSetup } from "@ovineko/spa-guard/runtime";
|
|
16
|
+
**npm**:
|
|
41
17
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
await Promise.all([import("./routes/Home"), import("./routes/Checkout")]);
|
|
45
|
-
|
|
46
|
-
markRetryHealthyBoot();
|
|
18
|
+
```bash
|
|
19
|
+
npm install @ovineko/spa-guard
|
|
47
20
|
```
|
|
48
21
|
|
|
49
|
-
|
|
22
|
+
**yarn**:
|
|
50
23
|
|
|
51
|
-
```
|
|
52
|
-
|
|
24
|
+
```bash
|
|
25
|
+
yarn add @ovineko/spa-guard
|
|
53
26
|
```
|
|
54
27
|
|
|
55
|
-
|
|
28
|
+
**bun**:
|
|
56
29
|
|
|
57
|
-
```
|
|
58
|
-
|
|
30
|
+
```bash
|
|
31
|
+
bun add @ovineko/spa-guard
|
|
59
32
|
```
|
|
60
33
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
spa-guard uses a single retry orchestrator (`retryOrchestrator.ts`) as the sole owner of retry lifecycle. All reload scheduling, deduplication, and fallback transitions run through `triggerRetry()`.
|
|
64
|
-
|
|
65
|
-
### Retry state machine
|
|
66
|
-
|
|
67
|
-
The orchestrator maintains an explicit phase:
|
|
68
|
-
|
|
69
|
-
- `idle` — no retry in progress
|
|
70
|
-
- `scheduled` — a reload has been scheduled (timer running); concurrent triggers are deduplicated
|
|
71
|
-
- `fallback` — retries exhausted, fallback UI is shown; further triggers are ignored
|
|
72
|
-
|
|
73
|
-
### Retry progression
|
|
74
|
-
|
|
75
|
-
When a recoverable error occurs (chunk load error, unhandled rejection, `vite:preloadError`, or static asset 404):
|
|
76
|
-
|
|
77
|
-
1. Event listener classifies the event and calls `triggerRetry({ source, error })`.
|
|
78
|
-
2. Orchestrator checks phase — if already `scheduled` or `fallback`, returns immediately without scheduling another reload.
|
|
79
|
-
3. On first trigger: reads `RETRY_ATTEMPT_PARAM` from URL to restore attempt count after a reload.
|
|
80
|
-
4. If attempts remain: increments attempt, calls `showLoadingUI(nextAttempt)` to render the loading UI immediately (before the timer fires), sets a timer for `reloadDelays[currentAttempt]`, encodes `retryId` and attempt count into the reload URL, then navigates. Requires `options.html.loading.content` to be configured; if absent, `showLoadingUI` returns silently and the retry still proceeds.
|
|
81
|
-
5. If attempts are exhausted: transitions to `fallback`, calls `setFallbackMode()`, sends a beacon, and renders fallback UI.
|
|
82
|
-
|
|
83
|
-
### URL params
|
|
84
|
-
|
|
85
|
-
The orchestrator serializes state into URL params for cross-reload continuity:
|
|
86
|
-
|
|
87
|
-
- `RETRY_ATTEMPT_PARAM` — current attempt count (strict non-negative integer; malformed values are ignored)
|
|
88
|
-
- `RETRY_ID_PARAM` — unique ID for this retry session
|
|
89
|
-
- `CACHE_BUST_PARAM` — timestamp for cache busting (set when `cacheBust: true` is passed, e.g. for static asset errors)
|
|
90
|
-
|
|
91
|
-
### Loading UI during retry delay
|
|
34
|
+
**deno**:
|
|
92
35
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
Default fallback/loading templates are theme-aware: they set `color-scheme: light dark` and apply neutral dark colors automatically via `@media (prefers-color-scheme: dark)`.
|
|
96
|
-
|
|
97
|
-
### Unhandledrejection serialization
|
|
98
|
-
|
|
99
|
-
`serializeError` handles `PromiseRejectionEvent` with strict redaction guardrails. For HTTP-like errors it extracts only safe metadata: `status`, `statusText`, `url`, `method`, `response.type`, and `X-Request-ID` from response headers when present. Response body, request/response payload, and the full headers object are **never** included in serialized output. For request wrappers (`reason.request` / `reason.config`) only `method`, `url`, and `baseURL` are extracted. Deep object traversal is bounded by `MAX_DEPTH=4`, `MAX_KEYS=20`, and `MAX_STRING_LEN=500` to prevent oversized beacons. Circular references are handled via a `WeakSet` visited tracker. The output also includes `isTrusted`, `timeStamp` from the event, and runtime context (`pageUrl`, `constructorName`).
|
|
100
|
-
This HTTP-like extraction also applies to `Error` subclasses that carry a `response` field (for example `ResponseError`), not only to plain objects.
|
|
101
|
-
|
|
102
|
-
### Retry reset
|
|
103
|
-
|
|
104
|
-
If enough time has passed since the last reload (configurable via `minTimeBetweenResets`, default 5000 ms), the orchestrator resets the attempt counter and starts a fresh retry cycle instead of continuing to fallback. This prevents stale URL params from triggering fallback on a clean page load.
|
|
105
|
-
|
|
106
|
-
### Healthy boot
|
|
107
|
-
|
|
108
|
-
After a successful app boot following a retry reload, `markRetryHealthyBoot()` clears retry URL params, cancels any pending timer, and resets orchestrator state.
|
|
109
|
-
|
|
110
|
-
Default behavior in `recommendedSetup`: auto healthy-boot after a grace period (`healthyBoot: "auto"`).
|
|
111
|
-
Manual override: set `healthyBoot: "manual"` and call `markRetryHealthyBoot()` yourself once critical boot is confirmed.
|
|
112
|
-
|
|
113
|
-
### Avoid false retry loops from app errors
|
|
114
|
-
|
|
115
|
-
By default, regular `unhandledrejection` events also trigger `triggerRetry()` (`handleUnhandledRejections.retry: true`). If your app has non-chunk unhandled rejections, this can look like retry looping even though chunks are healthy. In that case, disable reload-on-unhandled-rejection:
|
|
116
|
-
|
|
117
|
-
```ts
|
|
118
|
-
window.__SPA_GUARD_OPTIONS__ = {
|
|
119
|
-
handleUnhandledRejections: {
|
|
120
|
-
retry: false,
|
|
121
|
-
sendBeacon: true,
|
|
122
|
-
},
|
|
123
|
-
};
|
|
36
|
+
```bash
|
|
37
|
+
deno add npm:@ovineko/spa-guard
|
|
124
38
|
```
|
|
125
39
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
Multiple 404'd asset errors within a short window (default 500 ms) are coalesced into a single `triggerRetry({ cacheBust: true, source: "static-asset-error" })`. The orchestrator's deduplication ensures only one reload is scheduled.
|
|
129
|
-
|
|
130
|
-
### Retry ownership rule
|
|
131
|
-
|
|
132
|
-
Only `retryOrchestrator.ts` may schedule reloads, advance retry state, or transition to fallback. Listeners, renderers, and other modules must not schedule their own retry timers or set fallback state directly.
|
|
133
|
-
|
|
134
|
-
## API
|
|
135
|
-
|
|
136
|
-
### `@ovineko/spa-guard` (common)
|
|
137
|
-
|
|
138
|
-
- `listen` — subscribe to spa-guard events
|
|
139
|
-
- `events` — event type constants
|
|
140
|
-
- `options` — runtime options helpers
|
|
141
|
-
- `disableDefaultRetry` / `enableDefaultRetry` / `isDefaultRetryEnabled` — control default retry behaviour
|
|
142
|
-
- `isInFallbackMode` — returns `true` when fallback UI is active (retries exhausted)
|
|
143
|
-
- `resetFallbackMode` — clears the fallback flag; use in tests or programmatic recovery flows
|
|
144
|
-
- `BeaconError` — error class for beacon failures
|
|
145
|
-
- `ForceRetryError` — error class to force a retry
|
|
146
|
-
|
|
147
|
-
**Retry orchestrator (single owner of retry lifecycle):**
|
|
148
|
-
|
|
149
|
-
- `triggerRetry(input?)` — trigger a retry from any source; returns `TriggerResult`:
|
|
150
|
-
- `{ status: "accepted" }` — reload scheduled
|
|
151
|
-
- `{ status: "deduped", reason: string }` — ignored because another retry is already scheduled or an internal error occurred
|
|
152
|
-
- `{ status: "fallback" }` — already in fallback mode; no retry scheduled
|
|
153
|
-
- `{ status: "retry-disabled" }` — retry is disabled via `disableDefaultRetry()`
|
|
154
|
-
- `markRetryHealthyBoot()` — call after a successful boot following a retry reload; clears URL params, cancels timers, resets orchestrator state and fallback flag
|
|
155
|
-
- `getRetrySnapshot()` — returns current orchestrator state: `{ phase, attempt, retryId, lastSource, lastTriggerTime }`
|
|
156
|
-
- `resetRetryOrchestratorForTests()` — resets all orchestrator state including fallback flag; use in test teardown
|
|
157
|
-
|
|
158
|
-
### `@ovineko/spa-guard/runtime`
|
|
159
|
-
|
|
160
|
-
- `recommendedSetup(options?)` — enable recommended runtime features; idempotent and returns cleanup function
|
|
161
|
-
- `RecommendedSetupOptions` — `{ versionCheck?: boolean; healthyBoot?: "auto" | "manual" | "off" | false | { mode?: "auto"; graceMs?: number } }`
|
|
162
|
-
- `healthyBoot.graceMs` acts as a lower bound override for auto mode (`max(computedGraceMs, graceMs)`)
|
|
163
|
-
- `startVersionCheck` / `stopVersionCheck` — manual version check control
|
|
164
|
-
- `getState` / `subscribeToState` — runtime state access
|
|
165
|
-
- `SpaGuardState` — state type
|
|
166
|
-
- `showSpinner` / `dismissSpinner` / `getSpinnerHtml` — spinner helpers
|
|
167
|
-
- `setTranslations` — override i18n strings
|
|
168
|
-
- `ForceRetryError`
|
|
169
|
-
|
|
170
|
-
### `@ovineko/spa-guard/schema`
|
|
171
|
-
|
|
172
|
-
Schemas for spa-guard configuration.
|
|
173
|
-
|
|
174
|
-
### `@ovineko/spa-guard/i18n`
|
|
175
|
-
|
|
176
|
-
Built-in translation strings.
|
|
177
|
-
|
|
178
|
-
### `@ovineko/spa-guard/runtime/debug`
|
|
179
|
-
|
|
180
|
-
Debug helpers for testing error scenarios. Use `createDebugger()` to mount an in-page panel with buttons for each scenario.
|
|
40
|
+
## Usage
|
|
181
41
|
|
|
182
|
-
|
|
42
|
+
```ts
|
|
43
|
+
import { recommendedSetup } from "@ovineko/spa-guard/runtime";
|
|
183
44
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
- `dispatchSyncRuntimeError` — sync error thrown during React render
|
|
187
|
-
- `dispatchAsyncRuntimeError` — uncaught error via setTimeout
|
|
188
|
-
- `dispatchFinallyError` — unhandled rejection from Promise.finally
|
|
189
|
-
- `dispatchForceRetryError` — ForceRetryError to exercise the force-retry path
|
|
190
|
-
- `dispatchUnhandledRejection` — generic unhandled promise rejection
|
|
191
|
-
- `dispatchRetryExhausted` — renders fallback UI directly (bypasses orchestrator; orchestrator phase remains `idle`)
|
|
192
|
-
- `dispatchStaticAsset404` — appends a hashed `<script>` that 404s, exercising the Resource Timing API-based static asset detection path
|
|
45
|
+
const cleanup = recommendedSetup();
|
|
46
|
+
```
|
|
193
47
|
|
|
194
|
-
##
|
|
48
|
+
## Documentation
|
|
195
49
|
|
|
196
|
-
|
|
197
|
-
- [@ovineko/spa-guard-react-router](../react-router/README.md) — React Router error boundary
|
|
198
|
-
- [@ovineko/spa-guard-vite](../vite/README.md) — Vite plugin (injects runtime script)
|
|
199
|
-
- [@ovineko/spa-guard-node](../node/README.md) — Node.js cache and builder API
|
|
200
|
-
- [@ovineko/spa-guard-fastify](../fastify/README.md) — Fastify plugin
|
|
201
|
-
- [@ovineko/spa-guard-eslint](../eslint/README.md) — ESLint rules
|
|
50
|
+
Full documentation: [ovineko.com/docs/spa-guard/core](https://ovineko.com/docs/spa-guard/core)
|
|
202
51
|
|
|
203
52
|
## License
|
|
204
53
|
|
package/dist/_internal.d.ts
CHANGED
|
@@ -1,20 +1,149 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
import { _ as Logger, a as getRetrySnapshot, b as optionsWindowKey, c as triggerRetry, f as disableDefaultRetry, g as subscribe, h as isDefaultRetryEnabled, i as TriggerResult, l as Options, m as enableDefaultRetry, n as RetrySnapshot, o as markRetryHealthyBoot, p as emitEvent, r as TriggerInput, s as resetRetryOrchestratorForTests, t as RetryPhase, u as getOptions, v as createLogger, y as debugSyncErrorEventType } from "./retryOrchestrator-mn9XcIVu.mjs";
|
|
2
|
+
import { g as UnsubscribeFn, i as SPAGuardEventChunkError, r as SPAGuardEvent } from "./types-DrN8pgyc.mjs";
|
|
3
|
+
import { a as sanitizeCssValue, c as getI18n, n as defaultSpinnerSvg, s as applyI18n, t as SPINNER_ID } from "./spinner-X23gI09z.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/common/handleErrorWithSpaGuard.d.ts
|
|
6
|
+
/** Minimal subset of React.ErrorInfo used for beacon serialization. */
|
|
7
|
+
interface ErrorInfoLike {
|
|
8
|
+
componentStack?: null | string;
|
|
9
|
+
digest?: string;
|
|
10
|
+
}
|
|
11
|
+
interface HandleErrorOptions {
|
|
12
|
+
autoRetryChunkErrors?: boolean;
|
|
13
|
+
errorInfo?: ErrorInfoLike;
|
|
14
|
+
eventName: string;
|
|
15
|
+
onError?: (error: unknown) => void;
|
|
16
|
+
sendBeaconOnError?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Shared error handling logic with spa-guard integration.
|
|
20
|
+
*
|
|
21
|
+
* Detects chunk errors and automatically retries, or sends beacon for non-chunk errors.
|
|
22
|
+
*/
|
|
23
|
+
declare const handleErrorWithSpaGuard: (error: unknown, options: HandleErrorOptions) => void;
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/common/html.generated.d.ts
|
|
26
|
+
declare const 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>";
|
|
27
|
+
declare const 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>";
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/common/isChunkError.d.ts
|
|
30
|
+
declare const isChunkError: (error: unknown) => boolean;
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/common/listen/internal.d.ts
|
|
33
|
+
declare const listenInternal: (serializeError: (error: unknown) => string, logger?: Logger) => void;
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/common/log.d.ts
|
|
36
|
+
declare const logMessage: (msg: string) => string;
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/common/parseVersion.d.ts
|
|
39
|
+
/**
|
|
40
|
+
* Extract the SPA Guard version string from an HTML document.
|
|
41
|
+
*
|
|
42
|
+
* Tries the new `__SPA_GUARD_VERSION__` format first, then falls back
|
|
43
|
+
* to the legacy `__SPA_GUARD_OPTIONS__` object with a `version` key.
|
|
44
|
+
*
|
|
45
|
+
* Returns `null` when neither marker is found.
|
|
46
|
+
*/
|
|
47
|
+
declare function extractVersionFromHtml(html: string): null | string;
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/common/retryImport.d.ts
|
|
50
|
+
/**
|
|
51
|
+
* Options for configuring the retry behaviour of {@link retryImport}.
|
|
52
|
+
*/
|
|
53
|
+
interface RetryImportOptions {
|
|
54
|
+
/**
|
|
55
|
+
* If true and all retries fail with a chunk error, triggers a page reload via the orchestrator before rethrowing.
|
|
56
|
+
* @default true (when used via lazyWithRetry)
|
|
57
|
+
*/
|
|
58
|
+
callReloadOnFailure?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Optional callback invoked before each retry attempt.
|
|
61
|
+
* Useful for logging or analytics.
|
|
62
|
+
*
|
|
63
|
+
* @param attempt - The 1-based attempt number (1 = first retry)
|
|
64
|
+
* @param delay - The delay in milliseconds before this retry attempt
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* onRetry: (attempt, delay) => console.log(`Retry ${attempt} after ${delay}ms`)
|
|
68
|
+
*/
|
|
69
|
+
onRetry?: (attempt: number, delay: number) => void;
|
|
70
|
+
/**
|
|
71
|
+
* AbortSignal to cancel pending retries and clear timers.
|
|
72
|
+
* When aborted, any in-progress wait is cancelled immediately (preventing memory leaks),
|
|
73
|
+
* and the retryImport promise rejects with an AbortError.
|
|
74
|
+
* Useful when the caller no longer needs the import result (e.g. component unmounted).
|
|
75
|
+
*/
|
|
76
|
+
signal?: AbortSignal;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Retries an import function with configurable delays between attempts.
|
|
80
|
+
*
|
|
81
|
+
* @param importFn - The function that performs the dynamic import
|
|
82
|
+
* @param delays - Array of delays in milliseconds. Each entry represents one retry attempt.
|
|
83
|
+
* @param options - Optional configuration for retry behaviour
|
|
84
|
+
* @returns Promise that resolves with the import result or rejects after all attempts are exhausted
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* retryImport(() => import('./MyModule'), [1000, 2000])
|
|
88
|
+
* retryImport(() => import('./MyModule'), [500, 1500], {
|
|
89
|
+
* onRetry: (attempt, delayMs) => console.log(`Retry ${attempt} after ${delayMs}ms`),
|
|
90
|
+
* })
|
|
91
|
+
*/
|
|
92
|
+
declare const retryImport: <T>(importFn: () => Promise<T>, delays: number[], options?: RetryImportOptions) => Promise<T>;
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/common/serializeError.d.ts
|
|
95
|
+
declare const serializeError: (error: unknown) => string;
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/runtime/debug/errorDispatchers.d.ts
|
|
98
|
+
/**
|
|
99
|
+
* Error dispatchers for the debug panel.
|
|
100
|
+
*
|
|
101
|
+
* Unlike the old errorSimulators (which returned promises that callers could catch),
|
|
102
|
+
* these functions return void. Errors are "fire and forget" — they escape to
|
|
103
|
+
* window event listeners (window.error, window.unhandledrejection) where
|
|
104
|
+
* spa-guard's listenInternal() picks them up.
|
|
105
|
+
*/
|
|
106
|
+
/**
|
|
107
|
+
* Dispatches an async runtime error via setTimeout.
|
|
108
|
+
* Triggers the window "error" event because the throw happens outside
|
|
109
|
+
* any call stack that could catch it.
|
|
110
|
+
*/
|
|
111
|
+
declare function dispatchAsyncRuntimeError(): void;
|
|
112
|
+
/**
|
|
113
|
+
* Dispatches an unhandled chunk load error via void Promise.reject().
|
|
114
|
+
* Triggers window "unhandledrejection" with an error matching spa-guard's
|
|
115
|
+
* chunk error detection patterns.
|
|
116
|
+
*/
|
|
117
|
+
declare function dispatchChunkLoadError(): void;
|
|
118
|
+
/**
|
|
119
|
+
* Dispatches an unhandled chunk error via Promise.finally().
|
|
120
|
+
* The throw inside .finally() with no surrounding catch produces
|
|
121
|
+
* a window "unhandledrejection" event.
|
|
122
|
+
*/
|
|
123
|
+
declare function dispatchFinallyError(): void;
|
|
124
|
+
/**
|
|
125
|
+
* Dispatches a ForceRetryError via void Promise.reject().
|
|
126
|
+
* Triggers window "unhandledrejection" with a ForceRetryError whose message
|
|
127
|
+
* contains the FORCE_RETRY_MAGIC prefix, exercising the forceRetry path.
|
|
128
|
+
*/
|
|
129
|
+
declare function dispatchForceRetryError(): void;
|
|
130
|
+
/**
|
|
131
|
+
* Dispatches an unhandled network timeout error after a delay.
|
|
132
|
+
* Uses setTimeout + void Promise.reject() to trigger window "unhandledrejection".
|
|
133
|
+
*/
|
|
134
|
+
declare function dispatchNetworkTimeout(delayMs?: number): void;
|
|
135
|
+
/**
|
|
136
|
+
* Dispatches a sync runtime error via CustomEvent.
|
|
137
|
+
* DebugSyncErrorTrigger (a React component) listens for this event,
|
|
138
|
+
* stores the error in state, and throws it during render so that
|
|
139
|
+
* React Error Boundary can catch it.
|
|
140
|
+
*/
|
|
141
|
+
declare function dispatchSyncRuntimeError(): void;
|
|
142
|
+
/**
|
|
143
|
+
* Dispatches a plain unhandled promise rejection via void Promise.reject().
|
|
144
|
+
* This is NOT a chunk error and NOT a ForceRetry — it exercises the
|
|
145
|
+
* handleUnhandledRejections config path for generic rejections.
|
|
146
|
+
*/
|
|
147
|
+
declare function dispatchUnhandledRejection(): void;
|
|
148
|
+
//#endregion
|
|
149
|
+
export { type ErrorInfoLike, type HandleErrorOptions, type Options, type RetryPhase, type RetrySnapshot, type SPAGuardEvent, type SPAGuardEventChunkError, SPINNER_ID, type TriggerInput, type TriggerResult, type UnsubscribeFn, applyI18n, createLogger, debugSyncErrorEventType, defaultErrorFallbackHtml, defaultLoadingFallbackHtml, defaultSpinnerSvg, disableDefaultRetry, dispatchAsyncRuntimeError, dispatchChunkLoadError, dispatchFinallyError, dispatchForceRetryError, dispatchNetworkTimeout, dispatchSyncRuntimeError, dispatchUnhandledRejection, emitEvent, enableDefaultRetry, extractVersionFromHtml, getI18n, getOptions, getRetrySnapshot, handleErrorWithSpaGuard, isChunkError, isDefaultRetryEnabled, listenInternal, logMessage, markRetryHealthyBoot, optionsWindowKey, resetRetryOrchestratorForTests, retryImport, sanitizeCssValue, serializeError, subscribe, triggerRetry };
|