@ovineko/spa-guard 0.0.2-alpha-0 → 0.0.3-alpha-0
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 +3 -0
- package/dist/_internal.js +4 -4
- package/dist/{chunk-T42DLOQP.js → chunk-3UJ67DPX.js} +1 -1
- package/dist/{chunk-LIKSIU75.js → chunk-GE63YJOT.js} +2 -2
- package/dist/{chunk-ORYUDYHU.js → chunk-PERG4557.js} +1 -1
- package/dist/{chunk-IZAXNDHZ.js → chunk-VZ2DLGXX.js} +1 -1
- package/dist/{chunk-4K3AQHLC.js → chunk-XIFXSNSD.js} +4 -4
- package/dist/common/html.generated.d.ts +2 -2
- package/dist/common/index.js +2 -2
- package/dist/runtime/debug/index.js +3 -3
- package/dist/runtime/index.js +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,9 +92,12 @@ The orchestrator serializes state into URL params for cross-reload continuity:
|
|
|
92
92
|
|
|
93
93
|
When `options.html.loading.content` is configured, `showLoadingUI(attempt)` is called before the reload timer fires. It injects the loading HTML into the target element (selector from `options.html.fallback.selector`, defaulting to `body`), reveals the `data-spa-guard-section="retrying"` element, fills attempt numbers into `[data-spa-guard-content="attempt"]` elements, applies i18n via `applyI18n`/`getI18n`, and optionally hides or replaces the spinner based on `options.html.spinner`. If loading content is not configured or the target element is not found, `showLoadingUI` returns silently — the retry still proceeds normally.
|
|
94
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
|
+
|
|
95
97
|
### Unhandledrejection serialization
|
|
96
98
|
|
|
97
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.
|
|
98
101
|
|
|
99
102
|
### Retry reset
|
|
100
103
|
|
package/dist/_internal.js
CHANGED
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
isChunkError,
|
|
4
4
|
listenInternal,
|
|
5
5
|
serializeError
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-XIFXSNSD.js";
|
|
7
7
|
import {
|
|
8
8
|
SPINNER_ID,
|
|
9
9
|
defaultSpinnerSvg,
|
|
10
10
|
extractVersionFromHtml,
|
|
11
11
|
sanitizeCssValue
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-3UJ67DPX.js";
|
|
13
13
|
import {
|
|
14
14
|
dispatchAsyncRuntimeError,
|
|
15
15
|
dispatchChunkLoadError,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
dispatchNetworkTimeout,
|
|
19
19
|
dispatchSyncRuntimeError,
|
|
20
20
|
dispatchUnhandledRejection
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-PERG4557.js";
|
|
22
22
|
import {
|
|
23
23
|
applyI18n,
|
|
24
24
|
debugSyncErrorEventType,
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
shouldIgnoreMessages,
|
|
41
41
|
subscribe,
|
|
42
42
|
triggerRetry
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-GE63YJOT.js";
|
|
44
44
|
import "./chunk-MLKGABMK.js";
|
|
45
45
|
|
|
46
46
|
// src/common/handleErrorWithSpaGuard.ts
|
|
@@ -135,8 +135,8 @@ function setTranslations(translations) {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
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}
|
|
139
|
-
var defaultLoadingFallbackHtml = `<
|
|
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
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
141
|
|
|
142
142
|
// src/common/options.ts
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
shouldIgnoreMessages,
|
|
12
12
|
staticAssetRecoveryKey,
|
|
13
13
|
triggerRetry
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-GE63YJOT.js";
|
|
15
15
|
|
|
16
16
|
// src/common/isChunkError.ts
|
|
17
17
|
var isChunkError = (error) => {
|
|
@@ -157,9 +157,6 @@ var serializeRejectionReason = (reason, visited, depth) => {
|
|
|
157
157
|
type: "Error"
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
|
-
if (reason instanceof Error) {
|
|
161
|
-
return serializeSafeError(reason, visited, depth);
|
|
162
|
-
}
|
|
163
160
|
const reasonObj = reason;
|
|
164
161
|
if (reasonObj.response != null) {
|
|
165
162
|
const response = reasonObj.response;
|
|
@@ -212,6 +209,9 @@ var serializeRejectionReason = (reason, visited, depth) => {
|
|
|
212
209
|
}
|
|
213
210
|
return result;
|
|
214
211
|
}
|
|
212
|
+
if (reason instanceof Error) {
|
|
213
|
+
return serializeSafeError(reason, visited, depth);
|
|
214
|
+
}
|
|
215
215
|
return {
|
|
216
216
|
type: "object",
|
|
217
217
|
value: extractBoundedObject(reasonObj, visited, depth)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export 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}
|
|
2
|
-
export declare const defaultLoadingFallbackHtml = "<
|
|
1
|
+
export 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>";
|
|
2
|
+
export 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>";
|
|
3
3
|
export declare const 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>";
|
package/dist/common/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
createLogger,
|
|
3
3
|
listenInternal,
|
|
4
4
|
serializeError
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-XIFXSNSD.js";
|
|
6
6
|
import {
|
|
7
7
|
ForceRetryError,
|
|
8
8
|
disableDefaultRetry,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
resetFallbackMode,
|
|
17
17
|
subscribe,
|
|
18
18
|
triggerRetry
|
|
19
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-GE63YJOT.js";
|
|
20
20
|
import {
|
|
21
21
|
__export
|
|
22
22
|
} from "../chunk-MLKGABMK.js";
|
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
dispatchStaticAsset404,
|
|
9
9
|
dispatchSyncRuntimeError,
|
|
10
10
|
dispatchUnhandledRejection
|
|
11
|
-
} from "../../chunk-
|
|
11
|
+
} from "../../chunk-PERG4557.js";
|
|
12
12
|
import {
|
|
13
13
|
subscribeToState
|
|
14
|
-
} from "../../chunk-
|
|
14
|
+
} from "../../chunk-VZ2DLGXX.js";
|
|
15
15
|
import {
|
|
16
16
|
subscribe
|
|
17
|
-
} from "../../chunk-
|
|
17
|
+
} from "../../chunk-GE63YJOT.js";
|
|
18
18
|
import "../../chunk-MLKGABMK.js";
|
|
19
19
|
|
|
20
20
|
// src/runtime/debug/index.ts
|
package/dist/runtime/index.js
CHANGED
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
extractVersionFromHtml,
|
|
4
4
|
getSpinnerHtml,
|
|
5
5
|
showSpinner
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-3UJ67DPX.js";
|
|
7
7
|
import {
|
|
8
8
|
getState,
|
|
9
9
|
subscribeToState
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-VZ2DLGXX.js";
|
|
11
11
|
import {
|
|
12
12
|
ForceRetryError,
|
|
13
13
|
getLogger,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
markRetryHealthyBoot,
|
|
18
18
|
setTranslations,
|
|
19
19
|
versionCheckStateWindowKey
|
|
20
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-GE63YJOT.js";
|
|
21
21
|
import "../chunk-MLKGABMK.js";
|
|
22
22
|
|
|
23
23
|
// src/common/checkVersion.ts
|