heliumts 0.7.4 → 0.7.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"staleRecovery.d.ts","sourceRoot":"","sources":["../../src/client/staleRecovery.ts"],"names":[],"mappings":"AAeA,KAAK,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC,CAAC;AAEvE,KAAK,iCAAiC,GAAG;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AA+DF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAWzD;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,iCAAsC,GAAG,IAAI,CAyGhG"}
1
+ {"version":3,"file":"staleRecovery.d.ts","sourceRoot":"","sources":["../../src/client/staleRecovery.ts"],"names":[],"mappings":"AAeA,KAAK,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC,CAAC;AAEvE,KAAK,iCAAiC,GAAG;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AA2EF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAWzD;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,iCAAsC,GAAG,IAAI,CA+HhG"}
@@ -10,6 +10,17 @@ const CHUNK_ERROR_PATTERNS = [
10
10
  /Importing a module script failed/i,
11
11
  /dynamically imported module/i,
12
12
  ];
13
+ function resolveStorage(windowObject, override) {
14
+ if (override !== undefined) {
15
+ return override;
16
+ }
17
+ try {
18
+ return windowObject.sessionStorage;
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
13
24
  function readStoredNumber(storage, key) {
14
25
  if (!storage) {
15
26
  return null;
@@ -90,12 +101,14 @@ export function installStaleClientRecovery(options = {}) {
90
101
  }
91
102
  trackedWindow[INSTALL_FLAG] = true;
92
103
  const now = options.now ?? (() => Date.now());
93
- const storage = options.storage ?? windowObject.sessionStorage;
104
+ const storage = resolveStorage(windowObject, options.storage);
94
105
  const staleThresholdMs = options.staleThresholdMs ?? STALE_RESUME_THRESHOLD_MS;
95
106
  const reloadCooldownMs = options.reloadCooldownMs ?? RELOAD_COOLDOWN_MS;
96
107
  const reload = options.reload ?? (() => windowObject.location.reload());
97
108
  let isReloading = false;
109
+ let hasPendingReload = false;
98
110
  let hiddenAt = readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);
111
+ const isVisible = () => !documentObject.hidden;
99
112
  const markHidden = () => {
100
113
  hiddenAt = now();
101
114
  writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, hiddenAt);
@@ -104,7 +117,11 @@ export function installStaleClientRecovery(options = {}) {
104
117
  hiddenAt = null;
105
118
  writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, null);
106
119
  };
107
- const attemptReload = () => {
120
+ const executeReload = () => {
121
+ if (!isVisible()) {
122
+ hasPendingReload = true;
123
+ return;
124
+ }
108
125
  if (isReloading) {
109
126
  return;
110
127
  }
@@ -114,9 +131,19 @@ export function installStaleClientRecovery(options = {}) {
114
131
  return;
115
132
  }
116
133
  isReloading = true;
134
+ hasPendingReload = false;
117
135
  writeStoredNumber(storage, LAST_RELOAD_STORAGE_KEY, current);
118
136
  reload();
119
137
  };
138
+ const flushPendingReload = () => {
139
+ if (!hasPendingReload) {
140
+ return;
141
+ }
142
+ executeReload();
143
+ };
144
+ const attemptReload = () => {
145
+ executeReload();
146
+ };
120
147
  const maybeRecoverFromStaleResume = () => {
121
148
  const hiddenTimestamp = hiddenAt ?? readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);
122
149
  if (hiddenTimestamp === null) {
@@ -133,6 +160,7 @@ export function installStaleClientRecovery(options = {}) {
133
160
  markHidden();
134
161
  return;
135
162
  }
163
+ flushPendingReload();
136
164
  maybeRecoverFromStaleResume();
137
165
  }, { passive: true });
138
166
  windowObject.addEventListener("pagehide", () => {
@@ -140,6 +168,7 @@ export function installStaleClientRecovery(options = {}) {
140
168
  }, { passive: true });
141
169
  windowObject.addEventListener("pageshow", (event) => {
142
170
  if (event.persisted) {
171
+ flushPendingReload();
143
172
  maybeRecoverFromStaleResume();
144
173
  }
145
174
  }, { passive: true });
@@ -1 +1 @@
1
- {"version":3,"file":"staleRecovery.js","sourceRoot":"","sources":["../../src/client/staleRecovery.ts"],"names":[],"mappings":"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","sourcesContent":["const STALE_RESUME_THRESHOLD_MS = 30 * 60 * 1000;\nconst RELOAD_COOLDOWN_MS = 30 * 1000;\n\nconst INSTALL_FLAG = \"__helium_stale_client_recovery_installed__\";\nconst HIDDEN_AT_STORAGE_KEY = \"__helium_stale_client_hidden_at__\";\nconst LAST_RELOAD_STORAGE_KEY = \"__helium_stale_client_last_reload_at__\";\n\nconst CHUNK_ERROR_PATTERNS: RegExp[] = [\n /ChunkLoadError/i,\n /Loading chunk\\s+\\d+\\s+failed/i,\n /Failed to fetch dynamically imported module/i,\n /Importing a module script failed/i,\n /dynamically imported module/i,\n];\n\ntype StorageLike = Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\">;\n\ntype InstallStaleClientRecoveryOptions = {\n windowObject?: Window;\n documentObject?: Document;\n storage?: StorageLike | null;\n now?: () => number;\n reload?: () => void;\n staleThresholdMs?: number;\n reloadCooldownMs?: number;\n disableDedupe?: boolean;\n};\n\ntype WindowWithInstallFlag = Window & {\n [INSTALL_FLAG]?: boolean;\n};\n\nfunction readStoredNumber(storage: StorageLike | null, key: string): number | null {\n if (!storage) {\n return null;\n }\n\n try {\n const raw = storage.getItem(key);\n if (!raw) {\n return null;\n }\n const parsed = Number(raw);\n return Number.isFinite(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\nfunction writeStoredNumber(storage: StorageLike | null, key: string, value: number | null): void {\n if (!storage) {\n return;\n }\n\n try {\n if (value === null) {\n storage.removeItem(key);\n return;\n }\n storage.setItem(key, String(value));\n } catch {\n // Ignore storage write failures (private mode, quota exceeded, etc.)\n }\n}\n\nfunction extractErrorText(reason: unknown): string {\n if (typeof reason === \"string\") {\n return reason;\n }\n\n if (reason instanceof Error) {\n return `${reason.name}: ${reason.message}`;\n }\n\n if (typeof reason === \"object\" && reason !== null) {\n const maybeMessage = Reflect.get(reason, \"message\");\n if (typeof maybeMessage === \"string\") {\n return maybeMessage;\n }\n\n const maybeName = Reflect.get(reason, \"name\");\n if (typeof maybeName === \"string\") {\n return maybeName;\n }\n }\n\n return \"\";\n}\n\n/**\n * @internal Exported for testing\n */\nexport function isChunkLoadError(reason: unknown): boolean {\n if (reason instanceof Error && reason.name === \"ChunkLoadError\") {\n return true;\n }\n\n const text = extractErrorText(reason);\n if (!text) {\n return false;\n }\n\n return CHUNK_ERROR_PATTERNS.some((pattern) => pattern.test(text));\n}\n\n/**\n * Installs default stale-client recovery for mobile suspend/resume and stale chunks.\n *\n * @internal Exported for testing\n */\nexport function installStaleClientRecovery(options: InstallStaleClientRecoveryOptions = {}): void {\n const windowObject = options.windowObject ?? (typeof window !== \"undefined\" ? window : undefined);\n const documentObject = options.documentObject ?? (typeof document !== \"undefined\" ? document : undefined);\n\n if (!windowObject || !documentObject) {\n return;\n }\n\n const trackedWindow = windowObject as WindowWithInstallFlag;\n if (!options.disableDedupe && trackedWindow[INSTALL_FLAG]) {\n return;\n }\n trackedWindow[INSTALL_FLAG] = true;\n\n const now = options.now ?? (() => Date.now());\n const storage = options.storage ?? windowObject.sessionStorage;\n const staleThresholdMs = options.staleThresholdMs ?? STALE_RESUME_THRESHOLD_MS;\n const reloadCooldownMs = options.reloadCooldownMs ?? RELOAD_COOLDOWN_MS;\n const reload = options.reload ?? (() => windowObject.location.reload());\n\n let isReloading = false;\n let hiddenAt = readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);\n\n const markHidden = () => {\n hiddenAt = now();\n writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, hiddenAt);\n };\n\n const clearHidden = () => {\n hiddenAt = null;\n writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, null);\n };\n\n const attemptReload = () => {\n if (isReloading) {\n return;\n }\n\n const current = now();\n const lastReloadAt = readStoredNumber(storage, LAST_RELOAD_STORAGE_KEY) ?? 0;\n if (current - lastReloadAt < reloadCooldownMs) {\n return;\n }\n\n isReloading = true;\n writeStoredNumber(storage, LAST_RELOAD_STORAGE_KEY, current);\n reload();\n };\n\n const maybeRecoverFromStaleResume = () => {\n const hiddenTimestamp = hiddenAt ?? readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);\n if (hiddenTimestamp === null) {\n return;\n }\n\n const hiddenDuration = now() - hiddenTimestamp;\n clearHidden();\n if (hiddenDuration >= staleThresholdMs) {\n attemptReload();\n }\n };\n\n documentObject.addEventListener(\n \"visibilitychange\",\n () => {\n if (documentObject.hidden) {\n markHidden();\n return;\n }\n maybeRecoverFromStaleResume();\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\n \"pagehide\",\n () => {\n markHidden();\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\n \"pageshow\",\n (event) => {\n if ((event as PageTransitionEvent).persisted) {\n maybeRecoverFromStaleResume();\n }\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\"error\", (event) => {\n const errorEvent = event as ErrorEvent;\n if (isChunkLoadError(errorEvent.error ?? errorEvent.message)) {\n attemptReload();\n }\n });\n\n windowObject.addEventListener(\"unhandledrejection\", (event) => {\n const rejectionEvent = event as PromiseRejectionEvent;\n if (isChunkLoadError(rejectionEvent.reason)) {\n attemptReload();\n }\n });\n}\n"]}
1
+ {"version":3,"file":"staleRecovery.js","sourceRoot":"","sources":["../../src/client/staleRecovery.ts"],"names":[],"mappings":"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","sourcesContent":["const STALE_RESUME_THRESHOLD_MS = 30 * 60 * 1000;\nconst RELOAD_COOLDOWN_MS = 30 * 1000;\n\nconst INSTALL_FLAG = \"__helium_stale_client_recovery_installed__\";\nconst HIDDEN_AT_STORAGE_KEY = \"__helium_stale_client_hidden_at__\";\nconst LAST_RELOAD_STORAGE_KEY = \"__helium_stale_client_last_reload_at__\";\n\nconst CHUNK_ERROR_PATTERNS: RegExp[] = [\n /ChunkLoadError/i,\n /Loading chunk\\s+\\d+\\s+failed/i,\n /Failed to fetch dynamically imported module/i,\n /Importing a module script failed/i,\n /dynamically imported module/i,\n];\n\ntype StorageLike = Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\">;\n\ntype InstallStaleClientRecoveryOptions = {\n windowObject?: Window;\n documentObject?: Document;\n storage?: StorageLike | null;\n now?: () => number;\n reload?: () => void;\n staleThresholdMs?: number;\n reloadCooldownMs?: number;\n disableDedupe?: boolean;\n};\n\ntype WindowWithInstallFlag = Window & {\n [INSTALL_FLAG]?: boolean;\n};\n\nfunction resolveStorage(windowObject: Window, override?: StorageLike | null): StorageLike | null {\n if (override !== undefined) {\n return override;\n }\n\n try {\n return windowObject.sessionStorage;\n } catch {\n return null;\n }\n}\n\nfunction readStoredNumber(storage: StorageLike | null, key: string): number | null {\n if (!storage) {\n return null;\n }\n\n try {\n const raw = storage.getItem(key);\n if (!raw) {\n return null;\n }\n const parsed = Number(raw);\n return Number.isFinite(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\nfunction writeStoredNumber(storage: StorageLike | null, key: string, value: number | null): void {\n if (!storage) {\n return;\n }\n\n try {\n if (value === null) {\n storage.removeItem(key);\n return;\n }\n storage.setItem(key, String(value));\n } catch {\n // Ignore storage write failures (private mode, quota exceeded, etc.)\n }\n}\n\nfunction extractErrorText(reason: unknown): string {\n if (typeof reason === \"string\") {\n return reason;\n }\n\n if (reason instanceof Error) {\n return `${reason.name}: ${reason.message}`;\n }\n\n if (typeof reason === \"object\" && reason !== null) {\n const maybeMessage = Reflect.get(reason, \"message\");\n if (typeof maybeMessage === \"string\") {\n return maybeMessage;\n }\n\n const maybeName = Reflect.get(reason, \"name\");\n if (typeof maybeName === \"string\") {\n return maybeName;\n }\n }\n\n return \"\";\n}\n\n/**\n * @internal Exported for testing\n */\nexport function isChunkLoadError(reason: unknown): boolean {\n if (reason instanceof Error && reason.name === \"ChunkLoadError\") {\n return true;\n }\n\n const text = extractErrorText(reason);\n if (!text) {\n return false;\n }\n\n return CHUNK_ERROR_PATTERNS.some((pattern) => pattern.test(text));\n}\n\n/**\n * Installs default stale-client recovery for mobile suspend/resume and stale chunks.\n *\n * @internal Exported for testing\n */\nexport function installStaleClientRecovery(options: InstallStaleClientRecoveryOptions = {}): void {\n const windowObject = options.windowObject ?? (typeof window !== \"undefined\" ? window : undefined);\n const documentObject = options.documentObject ?? (typeof document !== \"undefined\" ? document : undefined);\n\n if (!windowObject || !documentObject) {\n return;\n }\n\n const trackedWindow = windowObject as WindowWithInstallFlag;\n if (!options.disableDedupe && trackedWindow[INSTALL_FLAG]) {\n return;\n }\n trackedWindow[INSTALL_FLAG] = true;\n\n const now = options.now ?? (() => Date.now());\n const storage = resolveStorage(windowObject, options.storage);\n const staleThresholdMs = options.staleThresholdMs ?? STALE_RESUME_THRESHOLD_MS;\n const reloadCooldownMs = options.reloadCooldownMs ?? RELOAD_COOLDOWN_MS;\n const reload = options.reload ?? (() => windowObject.location.reload());\n\n let isReloading = false;\n let hasPendingReload = false;\n let hiddenAt = readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);\n\n const isVisible = () => !documentObject.hidden;\n\n const markHidden = () => {\n hiddenAt = now();\n writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, hiddenAt);\n };\n\n const clearHidden = () => {\n hiddenAt = null;\n writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, null);\n };\n\n const executeReload = () => {\n if (!isVisible()) {\n hasPendingReload = true;\n return;\n }\n\n if (isReloading) {\n return;\n }\n\n const current = now();\n const lastReloadAt = readStoredNumber(storage, LAST_RELOAD_STORAGE_KEY) ?? 0;\n if (current - lastReloadAt < reloadCooldownMs) {\n return;\n }\n\n isReloading = true;\n hasPendingReload = false;\n writeStoredNumber(storage, LAST_RELOAD_STORAGE_KEY, current);\n reload();\n };\n\n const flushPendingReload = () => {\n if (!hasPendingReload) {\n return;\n }\n executeReload();\n };\n\n const attemptReload = () => {\n executeReload();\n };\n\n const maybeRecoverFromStaleResume = () => {\n const hiddenTimestamp = hiddenAt ?? readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);\n if (hiddenTimestamp === null) {\n return;\n }\n\n const hiddenDuration = now() - hiddenTimestamp;\n clearHidden();\n if (hiddenDuration >= staleThresholdMs) {\n attemptReload();\n }\n };\n\n documentObject.addEventListener(\n \"visibilitychange\",\n () => {\n if (documentObject.hidden) {\n markHidden();\n return;\n }\n flushPendingReload();\n maybeRecoverFromStaleResume();\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\n \"pagehide\",\n () => {\n markHidden();\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\n \"pageshow\",\n (event) => {\n if ((event as PageTransitionEvent).persisted) {\n flushPendingReload();\n maybeRecoverFromStaleResume();\n }\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\"error\", (event) => {\n const errorEvent = event as ErrorEvent;\n if (isChunkLoadError(errorEvent.error ?? errorEvent.message)) {\n attemptReload();\n }\n });\n\n windowObject.addEventListener(\"unhandledrejection\", (event) => {\n const rejectionEvent = event as PromiseRejectionEvent;\n if (isChunkLoadError(rejectionEvent.reason)) {\n attemptReload();\n }\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "heliumts",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "description": "A lightweight full-stack React framework with file-based routing, RPC, and SSG support",
5
5
  "keywords": [
6
6
  "react",