@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.
Files changed (67) hide show
  1. package/README.md +22 -173
  2. package/dist/ForceRetryError-BWLv3UVK.d.mts +6 -0
  3. package/dist/_internal.d.ts +149 -20
  4. package/dist/_internal.js +113 -170
  5. package/dist/chunk-CfYAbeIz.mjs +13 -0
  6. package/dist/common/index.d.ts +29 -9
  7. package/dist/common/index.js +47 -83
  8. package/dist/errorDispatchers-Cl_pa0DT.mjs +105 -0
  9. package/dist/i18n/index.d.ts +2 -21
  10. package/dist/i18n/index.js +344 -341
  11. package/dist/index-DL8CfPXg.d.mts +26 -0
  12. package/dist/index-rPxPv6iu.d.mts +16 -0
  13. package/dist/logger-Cp1Eyk6S.mjs +534 -0
  14. package/dist/retryOrchestrator-DNGIHV2M.mjs +758 -0
  15. package/dist/retryOrchestrator-mn9XcIVu.d.mts +257 -0
  16. package/dist/runtime/debug/index.d.ts +6 -4
  17. package/dist/runtime/debug/index.js +218 -238
  18. package/dist/runtime/index.d.ts +66 -8
  19. package/dist/runtime/index.js +279 -367
  20. package/dist/schema/index.d.ts +2 -13
  21. package/dist/schema/index.js +1 -0
  22. package/dist/schema/parse.d.ts +6 -2
  23. package/dist/schema/parse.js +29 -44
  24. package/dist/spinner-BbZVKZ-6.mjs +60 -0
  25. package/dist/spinner-X23gI09z.d.mts +37 -0
  26. package/dist/state-I20jENMD.mjs +93 -0
  27. package/dist/types-DrN8pgyc.d.mts +107 -0
  28. package/package.json +1 -4
  29. package/dist/chunk-3UJ67DPX.js +0 -98
  30. package/dist/chunk-GE63YJOT.js +0 -865
  31. package/dist/chunk-MLKGABMK.js +0 -9
  32. package/dist/chunk-PERG4557.js +0 -74
  33. package/dist/chunk-VZ2DLGXX.js +0 -111
  34. package/dist/chunk-XIFXSNSD.js +0 -678
  35. package/dist/common/checkVersion.d.ts +0 -5
  36. package/dist/common/constants.d.ts +0 -14
  37. package/dist/common/errors/BeaconError.d.ts +0 -12
  38. package/dist/common/errors/ForceRetryError.d.ts +0 -5
  39. package/dist/common/events/index.d.ts +0 -2
  40. package/dist/common/events/internal.d.ts +0 -13
  41. package/dist/common/events/types.d.ts +0 -104
  42. package/dist/common/fallbackRendering.d.ts +0 -23
  43. package/dist/common/fallbackState.d.ts +0 -3
  44. package/dist/common/handleErrorWithSpaGuard.d.ts +0 -18
  45. package/dist/common/html.generated.d.ts +0 -3
  46. package/dist/common/i18n.d.ts +0 -23
  47. package/dist/common/isChunkError.d.ts +0 -1
  48. package/dist/common/isStaticAssetError.d.ts +0 -3
  49. package/dist/common/lastReloadTime.d.ts +0 -17
  50. package/dist/common/listen/index.d.ts +0 -1
  51. package/dist/common/listen/internal.d.ts +0 -2
  52. package/dist/common/log.d.ts +0 -1
  53. package/dist/common/logger.d.ts +0 -30
  54. package/dist/common/options.d.ts +0 -182
  55. package/dist/common/parseVersion.d.ts +0 -9
  56. package/dist/common/retryImport.d.ts +0 -43
  57. package/dist/common/retryOrchestrator.d.ts +0 -35
  58. package/dist/common/retryState.d.ts +0 -11
  59. package/dist/common/sendBeacon.d.ts +0 -2
  60. package/dist/common/serializeError.d.ts +0 -1
  61. package/dist/common/shouldIgnore.d.ts +0 -13
  62. package/dist/common/spinner.d.ts +0 -8
  63. package/dist/common/staticAssetRecovery.d.ts +0 -2
  64. package/dist/i18n/translations.d.ts +0 -2
  65. package/dist/runtime/debug/errorDispatchers.d.ts +0 -63
  66. package/dist/runtime/recommendedSetup.d.ts +0 -36
  67. package/dist/runtime/state.d.ts +0 -20
@@ -1,5 +0,0 @@
1
- declare const FORCE_RETRY_MAGIC = "__SPA_GUARD_FORCE_RETRY__";
2
- export { FORCE_RETRY_MAGIC };
3
- export declare class ForceRetryError extends Error {
4
- constructor(message?: string, options?: ErrorOptions);
5
- }
@@ -1,2 +0,0 @@
1
- export { emitEvent, subscribe } from "./internal";
2
- export * from "./types";
@@ -1,13 +0,0 @@
1
- import type { Logger } from "../logger";
2
- import type { EmitOptions, InternalConfig, SPAGuardEvent, SubscribeFn, UnsubscribeFn } from "./types";
3
- export declare const subscribers: Set<SubscribeFn>;
4
- export declare const internalConfig: InternalConfig;
5
- export declare const setLogger: (logger?: Logger) => void;
6
- export declare const getLogger: () => Logger | undefined;
7
- export declare const emitEvent: (event: SPAGuardEvent, options?: EmitOptions) => void;
8
- export declare const subscribe: (cb: SubscribeFn) => UnsubscribeFn;
9
- export declare const isInitialized: () => boolean;
10
- export declare const markInitialized: () => void;
11
- export declare const disableDefaultRetry: () => void;
12
- export declare const enableDefaultRetry: () => void;
13
- export declare const isDefaultRetryEnabled: () => boolean;
@@ -1,104 +0,0 @@
1
- export interface EmitOptions {
2
- silent?: boolean;
3
- }
4
- export interface InternalConfig {
5
- defaultRetryEnabled: boolean;
6
- initialized: boolean;
7
- }
8
- export type SPAGuardEvent = (SPAGuardEventChunkError & {
9
- name: "chunk-error";
10
- }) | (SPAGuardEventFallbackUINotRendered & {
11
- name: "fallback-ui-not-rendered";
12
- }) | (SPAGuardEventFallbackUIShown & {
13
- name: "fallback-ui-shown";
14
- }) | (SPAGuardEventLazyRetryAttempt & {
15
- name: "lazy-retry-attempt";
16
- }) | (SPAGuardEventLazyRetryExhausted & {
17
- name: "lazy-retry-exhausted";
18
- }) | (SPAGuardEventLazyRetryStart & {
19
- name: "lazy-retry-start";
20
- }) | (SPAGuardEventLazyRetrySuccess & {
21
- name: "lazy-retry-success";
22
- }) | (SPAGuardEventRetryAttempt & {
23
- name: "retry-attempt";
24
- }) | (SPAGuardEventRetryExhausted & {
25
- name: "retry-exhausted";
26
- }) | (SPAGuardEventRetryReset & {
27
- name: "retry-reset";
28
- }) | (SPAGuardEventStaticAssetLoadFailed & {
29
- name: "static-asset-load-failed";
30
- });
31
- export interface SPAGuardEventChunkError {
32
- error: unknown;
33
- isRetrying: boolean;
34
- name: "chunk-error";
35
- }
36
- export interface SPAGuardEventFallbackUINotRendered {
37
- name: "fallback-ui-not-rendered";
38
- reason: "no-html-configured" | "target-not-found";
39
- selector?: string;
40
- }
41
- export interface SPAGuardEventFallbackUIShown {
42
- name: "fallback-ui-shown";
43
- }
44
- /** Emitted before each module-level retry attempt initiated by retryImport. */
45
- export interface SPAGuardEventLazyRetryAttempt {
46
- /** 1-based index of the current retry attempt. */
47
- attempt: number;
48
- /** Delay in milliseconds before this retry attempt. */
49
- delay: number;
50
- /** The error that caused the previous attempt to fail. */
51
- error?: unknown;
52
- name: "lazy-retry-attempt";
53
- /** Total number of attempts including the initial try (delays.length + 1). */
54
- totalAttempts: number;
55
- }
56
- /** Emitted when all module-level retry attempts are exhausted. */
57
- export interface SPAGuardEventLazyRetryExhausted {
58
- /** The final error after all attempts failed. */
59
- error: unknown;
60
- name: "lazy-retry-exhausted";
61
- /** Total number of attempts that were made (delays.length + 1). */
62
- totalAttempts: number;
63
- /** Whether triggerRetry() will be called after this event. */
64
- willReload: boolean;
65
- }
66
- /** Emitted once before the first import attempt, when retries are configured. */
67
- export interface SPAGuardEventLazyRetryStart {
68
- name: "lazy-retry-start";
69
- /** Total number of attempts that will be made (delays.length + 1). */
70
- totalAttempts: number;
71
- }
72
- /** Emitted when a module loads successfully after one or more retry attempts. */
73
- export interface SPAGuardEventLazyRetrySuccess {
74
- /** 1-based retry number on which the import succeeded (1 = first retry). */
75
- attempt: number;
76
- name: "lazy-retry-success";
77
- /** Total time in milliseconds from first attempt to success. */
78
- totalTime?: number;
79
- }
80
- export interface SPAGuardEventRetryAttempt {
81
- attempt: number;
82
- delay: number;
83
- name: "retry-attempt";
84
- retryId: string;
85
- }
86
- export interface SPAGuardEventRetryExhausted {
87
- finalAttempt: number;
88
- name: "retry-exhausted";
89
- retryId: string;
90
- }
91
- export interface SPAGuardEventRetryReset {
92
- name: "retry-reset";
93
- previousAttempt: number;
94
- previousRetryId: string;
95
- timeSinceReload: number;
96
- }
97
- /** Emitted when a hashed static asset (script/link) fails to load, likely due to a stale deployment. */
98
- export interface SPAGuardEventStaticAssetLoadFailed {
99
- name: "static-asset-load-failed";
100
- /** The URL of the asset that failed to load. */
101
- url: string;
102
- }
103
- export type SubscribeFn = (event: SPAGuardEvent) => void;
104
- export type UnsubscribeFn = () => void;
@@ -1,23 +0,0 @@
1
- /**
2
- * Renders the loading UI into the DOM during a retry delay before reload.
3
- *
4
- * Fail-safe: if loading content is not configured or the target element is not
5
- * found, returns silently with no log, no event, and no side effects.
6
- * All DOM access is wrapped in try/catch.
7
- */
8
- export declare const showLoadingUI: (attempt: number) => void;
9
- /**
10
- * Renders the fallback UI into the DOM.
11
- *
12
- * This is a pure rendering helper. It has no lifecycle side effects:
13
- * it does not set fallback mode, does not check whether fallback mode is
14
- * already active, and does not modify orchestrator state. The caller is
15
- * responsible for ensuring the lifecycle transition has already occurred
16
- * before invoking this function.
17
- *
18
- * Fails safely: if fallback HTML is not configured or the target element
19
- * is not found, logs a warning and returns without side effects or errors.
20
- */
21
- export declare const showFallbackUI: (override?: {
22
- retryId?: string;
23
- }) => void;
@@ -1,3 +0,0 @@
1
- export declare const isInFallbackMode: () => boolean;
2
- export declare const setFallbackMode: () => void;
3
- export declare const resetFallbackMode: () => void;
@@ -1,18 +0,0 @@
1
- /** Minimal subset of React.ErrorInfo used for beacon serialization. */
2
- export interface ErrorInfoLike {
3
- componentStack?: null | string;
4
- digest?: string;
5
- }
6
- export interface HandleErrorOptions {
7
- autoRetryChunkErrors?: boolean;
8
- errorInfo?: ErrorInfoLike;
9
- eventName: string;
10
- onError?: (error: unknown) => void;
11
- sendBeaconOnError?: boolean;
12
- }
13
- /**
14
- * Shared error handling logic with spa-guard integration.
15
- *
16
- * Detects chunk errors and automatically retries, or sends beacon for non-chunk errors.
17
- */
18
- export declare const handleErrorWithSpaGuard: (error: unknown, options: HandleErrorOptions) => void;
@@ -1,3 +0,0 @@
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
- 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>";
@@ -1,23 +0,0 @@
1
- import type { SpaGuardTranslations } from "../i18n";
2
- /**
3
- * Apply i18n translations to a virtual container's data-attributed elements.
4
- * Patches `[data-spa-guard-content]` and `[data-spa-guard-action]` elements,
5
- * and applies RTL direction if needed.
6
- *
7
- * Must be called on a virtual (detached) container BEFORE inserting into DOM
8
- * to avoid flash of untranslated content.
9
- */
10
- export declare function applyI18n(container: HTMLElement, t: SpaGuardTranslations): void;
11
- /**
12
- * Read i18n translations from the `<meta name="spa-guard-i18n">` tag.
13
- * Returns parsed translations or null if the tag is absent or malformed.
14
- */
15
- export declare function getI18n(): null | SpaGuardTranslations;
16
- /**
17
- * Write i18n translations to the `<meta name="spa-guard-i18n">` tag.
18
- * Creates the tag if it doesn't exist, or updates it if it does.
19
- *
20
- * Use this at runtime to dynamically patch the inline fallback/loading UI
21
- * translations without server-side rendering.
22
- */
23
- export declare function setTranslations(translations: SpaGuardTranslations): void;
@@ -1 +0,0 @@
1
- export declare const isChunkError: (error: unknown) => boolean;
@@ -1,3 +0,0 @@
1
- export declare const isStaticAssetError: (event: Event) => boolean;
2
- export declare const isLikely404: (url?: string, timeSinceNavMs?: number) => boolean;
3
- export declare const getAssetUrl: (event: Event) => string;
@@ -1,17 +0,0 @@
1
- import type { RetryState } from "./retryState";
2
- export interface LastReloadData {
3
- attemptNumber: number;
4
- retryId: string;
5
- timestamp: number;
6
- }
7
- export interface LastRetryResetInfo {
8
- previousRetryId: string;
9
- timestamp: number;
10
- }
11
- export declare const setLastReloadTime: (retryId: string, attemptNumber: number) => void;
12
- export declare const getLastReloadTime: () => LastReloadData | null;
13
- export declare const clearLastReloadTime: () => void;
14
- export declare const shouldResetRetryCycle: (retryState: RetryState, reloadDelays: number[], minTimeBetweenResets?: number) => boolean;
15
- export declare const setLastRetryResetInfo: (previousRetryId: string) => void;
16
- export declare const getLastRetryResetInfo: () => LastRetryResetInfo | null;
17
- export declare const clearLastRetryResetInfo: () => void;
@@ -1 +0,0 @@
1
- export declare const listen: () => void;
@@ -1,2 +0,0 @@
1
- import type { Logger } from "../logger";
2
- export declare const listenInternal: (serializeError: (error: unknown) => string, logger?: Logger) => void;
@@ -1 +0,0 @@
1
- export declare const logMessage: (msg: string) => string;
@@ -1,30 +0,0 @@
1
- import type { SPAGuardEvent } from "./events/types";
2
- export interface Logger {
3
- beaconSendFailed(error: unknown): void;
4
- capturedError(type: string, ...args: unknown[]): void;
5
- error(msg: string, ...args: unknown[]): void;
6
- fallbackAlreadyShown(error: unknown): void;
7
- fallbackInjectFailed(error: unknown): void;
8
- fallbackTargetNotFound(selector: string): void;
9
- log(msg: string, ...args: unknown[]): void;
10
- logEvent(event: SPAGuardEvent): void;
11
- noBeaconEndpoint(): void;
12
- noFallbackConfigured(): void;
13
- reloadAlreadyScheduled(error: unknown): void;
14
- retryCycleStarting(retryId: string, fromAttempt: number): void;
15
- retrySchedulingReload(retryId: string, attempt: number, delay: number): void;
16
- versionChangeDetected(oldVersion: null | string, latestVersion: string): void;
17
- versionCheckAlreadyRunning(): void;
18
- versionCheckDisabled(): void;
19
- versionCheckFailed(error: unknown): void;
20
- versionCheckHttpError(status: number): void;
21
- versionCheckParseError(): void;
22
- versionCheckPaused(): void;
23
- versionCheckRequiresEndpoint(): void;
24
- versionCheckResumed(): void;
25
- versionCheckResumedImmediate(): void;
26
- versionCheckStarted(mode: string, interval: number, version: string): void;
27
- versionCheckStopped(): void;
28
- warn(msg: string, ...args: unknown[]): void;
29
- }
30
- export declare const createLogger: () => Logger;
@@ -1,182 +0,0 @@
1
- export { optionsWindowKey } from "./constants";
2
- export interface Options {
3
- /**
4
- * Application name for beacon source identification.
5
- * Useful in monorepo setups to identify which app sent the beacon.
6
- */
7
- appName?: string;
8
- /**
9
- * Configuration for proactive version checking to detect new deployments.
10
- * When configured with a `version`, periodically polls to detect version changes
11
- * and dispatches a `spa-guard:version-change` CustomEvent on the window.
12
- */
13
- checkVersion?: {
14
- /**
15
- * Cache mode for the fetch request used to check the version.
16
- * - "no-store": Bypass the HTTP cache entirely (default).
17
- * - "no-cache": Revalidate with the server before using cached response.
18
- * @default "no-store"
19
- */
20
- cache?: "no-cache" | "no-store";
21
- /**
22
- * Endpoint URL for JSON mode version checking.
23
- * Required when mode is "json".
24
- */
25
- endpoint?: string;
26
- /**
27
- * Polling interval in milliseconds.
28
- * @default 300000
29
- */
30
- interval?: number;
31
- /**
32
- * Detection mode.
33
- * - "html": Re-fetches the current page and parses the injected version from the HTML.
34
- * - "json": Fetches a dedicated JSON endpoint.
35
- * @default "html"
36
- */
37
- mode?: "html" | "json";
38
- /**
39
- * Behavior when a version change is detected.
40
- * - "reload": Automatically calls location.reload() after dispatching the event.
41
- * - "event": Only dispatches the spa-guard:version-change CustomEvent (no reload).
42
- * @default "reload"
43
- */
44
- onUpdate?: "event" | "reload";
45
- };
46
- /**
47
- * Enable automatic retry cycle reset when enough time has passed
48
- * since the last reload. When true, if the user stays on a page longer
49
- * than the retry delay, the next error will start a fresh retry cycle.
50
- * @default true
51
- */
52
- enableRetryReset?: boolean;
53
- /**
54
- * Error filtering and retry configuration.
55
- */
56
- errors?: {
57
- /**
58
- * List of error message substrings that should trigger the retry/reload process,
59
- * same as chunk load errors. Useful for custom errors that indicate a stale deployment.
60
- * @default []
61
- */
62
- forceRetry?: string[];
63
- /**
64
- * List of error message substrings to ignore and not report.
65
- * If error message contains any of these strings, it will be filtered out.
66
- * @default []
67
- */
68
- ignore?: string[];
69
- };
70
- /**
71
- * Controls behavior for regular unhandled promise rejections
72
- * (those that are not chunk errors or ForceRetry errors).
73
- * @default { retry: true, sendBeacon: true }
74
- */
75
- handleUnhandledRejections?: {
76
- /**
77
- * Whether to attempt a page reload on unhandled rejections.
78
- * @default true
79
- */
80
- retry?: boolean;
81
- /**
82
- * Whether to send a beacon report on unhandled rejections.
83
- * @default true
84
- */
85
- sendBeacon?: boolean;
86
- };
87
- html?: {
88
- fallback?: {
89
- /** Custom HTML to display when all reload attempts are exhausted */
90
- content?: string;
91
- /** CSS selector where the fallback HTML should be injected @default "body" */
92
- selector?: string;
93
- };
94
- loading?: {
95
- /** Custom HTML to display during the loading/retrying state */
96
- content?: string;
97
- };
98
- /**
99
- * Spinner overlay configuration.
100
- * Controls the full-page loading spinner injected by the Vite plugin
101
- * and available via `showSpinner()`/`dismissSpinner()` at runtime.
102
- */
103
- spinner?: {
104
- /**
105
- * Overlay background color.
106
- * Used as CSS variable fallback: var(--spa-guard-spinner-bg, <this value>).
107
- * @default '#fff'
108
- */
109
- background?: string;
110
- /**
111
- * Custom spinner HTML (the spinner element only, no container/overlay).
112
- * If not provided, uses the default SVG spinner.
113
- */
114
- content?: string;
115
- /**
116
- * Disable spinner entirely.
117
- * No injection into body, showSpinner() is a no-op, Spinner returns null.
118
- * @default false
119
- */
120
- disabled?: boolean;
121
- };
122
- };
123
- /**
124
- * Options for the lazyWithRetry module-level retry logic.
125
- * Controls retry behaviour for dynamic imports before falling back to a full page reload.
126
- */
127
- lazyRetry?: {
128
- /**
129
- * Call triggerRetry() after all retry attempts for dynamic imports are exhausted.
130
- * If true, triggers page reload logic after all retryDelays fail.
131
- * If false, only throws the error to the error boundary without a reload.
132
- * @default true
133
- */
134
- callReloadOnFailure?: boolean;
135
- /**
136
- * Array of delays in milliseconds for dynamic import retry attempts.
137
- * Each element represents one retry attempt with the given delay.
138
- * The number of elements determines the total number of retry attempts.
139
- * @default [1000, 2000]
140
- * @example [500, 1500, 3000] // 3 attempts: 500ms, 1.5s, 3s
141
- */
142
- retryDelays?: number[];
143
- };
144
- /**
145
- * Minimum time in milliseconds between retry cycle resets.
146
- * Prevents infinite reset loops by ensuring a reset can only happen
147
- * if the previous reset was at least this many milliseconds ago.
148
- * @default 5000 (5 seconds)
149
- */
150
- minTimeBetweenResets?: number;
151
- /** @default [1000, 2000, 5000] */
152
- reloadDelays?: number[];
153
- reportBeacon?: {
154
- endpoint?: string;
155
- };
156
- /**
157
- * Configuration for automatic recovery from static asset 404 errors
158
- * caused by deployment version mismatches.
159
- */
160
- staticAssets?: {
161
- /**
162
- * Automatically trigger a cache-busting reload when a hashed static asset
163
- * fails to load and the page has been open long enough to suggest a stale deployment.
164
- * @default true
165
- */
166
- autoRecover?: boolean;
167
- /**
168
- * Milliseconds to wait after the first failed asset before triggering the reload.
169
- * Allows collecting multiple concurrent failures into a single reload.
170
- * @default 500
171
- */
172
- recoveryDelay?: number;
173
- };
174
- /** @default true */
175
- useRetryId?: boolean;
176
- /**
177
- * Current application version. Used by the version checker to detect new deployments.
178
- * Automatically generated by the Vite plugin using `crypto.randomUUID()` if not explicitly provided.
179
- */
180
- version?: string;
181
- }
182
- export declare const getOptions: () => Options;
@@ -1,9 +0,0 @@
1
- /**
2
- * Extract the SPA Guard version string from an HTML document.
3
- *
4
- * Tries the new `__SPA_GUARD_VERSION__` format first, then falls back
5
- * to the legacy `__SPA_GUARD_OPTIONS__` object with a `version` key.
6
- *
7
- * Returns `null` when neither marker is found.
8
- */
9
- export declare function extractVersionFromHtml(html: string): null | string;
@@ -1,43 +0,0 @@
1
- /**
2
- * Options for configuring the retry behaviour of {@link retryImport}.
3
- */
4
- export interface RetryImportOptions {
5
- /**
6
- * If true and all retries fail with a chunk error, triggers a page reload via the orchestrator before rethrowing.
7
- * @default true (when used via lazyWithRetry)
8
- */
9
- callReloadOnFailure?: boolean;
10
- /**
11
- * Optional callback invoked before each retry attempt.
12
- * Useful for logging or analytics.
13
- *
14
- * @param attempt - The 1-based attempt number (1 = first retry)
15
- * @param delay - The delay in milliseconds before this retry attempt
16
- *
17
- * @example
18
- * onRetry: (attempt, delay) => console.log(`Retry ${attempt} after ${delay}ms`)
19
- */
20
- onRetry?: (attempt: number, delay: number) => void;
21
- /**
22
- * AbortSignal to cancel pending retries and clear timers.
23
- * When aborted, any in-progress wait is cancelled immediately (preventing memory leaks),
24
- * and the retryImport promise rejects with an AbortError.
25
- * Useful when the caller no longer needs the import result (e.g. component unmounted).
26
- */
27
- signal?: AbortSignal;
28
- }
29
- /**
30
- * Retries an import function with configurable delays between attempts.
31
- *
32
- * @param importFn - The function that performs the dynamic import
33
- * @param delays - Array of delays in milliseconds. Each entry represents one retry attempt.
34
- * @param options - Optional configuration for retry behaviour
35
- * @returns Promise that resolves with the import result or rejects after all attempts are exhausted
36
- *
37
- * @example
38
- * retryImport(() => import('./MyModule'), [1000, 2000])
39
- * retryImport(() => import('./MyModule'), [500, 1500], {
40
- * onRetry: (attempt, delayMs) => console.log(`Retry ${attempt} after ${delayMs}ms`),
41
- * })
42
- */
43
- export declare const retryImport: <T>(importFn: () => Promise<T>, delays: number[], options?: RetryImportOptions) => Promise<T>;
@@ -1,35 +0,0 @@
1
- export type RetryPhase = "fallback" | "idle" | "scheduled";
2
- export interface RetrySnapshot {
3
- attempt: number;
4
- lastSource?: string;
5
- lastTriggerTime?: number;
6
- phase: RetryPhase;
7
- retryId: null | string;
8
- }
9
- export interface TriggerInput {
10
- cacheBust?: boolean;
11
- error?: unknown;
12
- source?: string;
13
- }
14
- export type TriggerResult = {
15
- reason: string;
16
- status: "deduped";
17
- } | {
18
- status: "accepted";
19
- } | {
20
- status: "fallback";
21
- } | {
22
- status: "internal-error";
23
- } | {
24
- status: "retry-disabled";
25
- };
26
- export declare const triggerRetry: (input?: TriggerInput) => TriggerResult;
27
- export declare const markRetryHealthyBoot: () => void;
28
- export declare const getRetrySnapshot: () => RetrySnapshot;
29
- /**
30
- * Sets orchestrator state to fallback and renders the fallback UI.
31
- * For use in debug/simulation contexts only — bypasses retry scheduling
32
- * while keeping the orchestrator snapshot consistent with fallback mode.
33
- */
34
- export declare const setFallbackStateForDebug: () => void;
35
- export declare const resetRetryOrchestratorForTests: () => void;
@@ -1,11 +0,0 @@
1
- export interface RetryState {
2
- retryAttempt: number;
3
- retryId: string;
4
- }
5
- export declare const getRetryStateFromUrl: () => null | RetryState;
6
- export declare const generateRetryId: () => string;
7
- export declare const getRetryAttemptFromUrl: () => null | number;
8
- export declare const getRetryInfoForBeacon: () => {
9
- retryAttempt?: number;
10
- retryId?: string;
11
- };
@@ -1,2 +0,0 @@
1
- import type { BeaconSchema } from "../schema";
2
- export declare const sendBeacon: (beacon: BeaconSchema) => void;
@@ -1 +0,0 @@
1
- export declare const serializeError: (error: unknown) => string;
@@ -1,13 +0,0 @@
1
- import type { BeaconSchema } from "../schema";
2
- /**
3
- * Checks if any of the provided messages should be ignored based on errors.ignore option.
4
- */
5
- export declare const shouldIgnoreMessages: (messages: (string | undefined)[]) => boolean;
6
- /**
7
- * Checks if any of the provided messages match a forceRetry pattern.
8
- */
9
- export declare const shouldForceRetry: (messages: (string | undefined)[]) => boolean;
10
- /**
11
- * Checks if a beacon should be ignored based on errors.ignore option.
12
- */
13
- export declare const shouldIgnoreBeacon: (beacon: BeaconSchema) => boolean;
@@ -1,8 +0,0 @@
1
- export declare const SPINNER_ID = "__spa-guard-spinner";
2
- export declare const defaultSpinnerSvg = "<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>";
3
- export declare function dismissSpinner(): void;
4
- export declare const sanitizeCssValue: (value: string) => string;
5
- export declare function getSpinnerHtml(backgroundOverride?: string): string;
6
- export declare function showSpinner(options?: {
7
- background?: string;
8
- }): () => void;
@@ -1,2 +0,0 @@
1
- export declare const handleStaticAssetFailure: (url: string) => void;
2
- export declare const resetStaticAssetRecovery: () => void;
@@ -1,2 +0,0 @@
1
- import type { SpaGuardTranslations } from "./index";
2
- export declare const translations: Record<string, SpaGuardTranslations>;