snapshot of https://github.com/makeplane/plane.git @ d868349a55de79979eb8b98701bf1702c67ad634 (2026-09-15)
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 16s
CodeQL / Analyze (python) (push) Failing after 3s
i18n sync check / check:sync (push) Failing after 3s
React Doctor / react-doctor (push) Failing after 16s
Branch Build CE / Build-Push Admin Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Admin Manifest (push) Has been cancelled
Branch Build CE / Build-Push Web Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Web Manifest (push) Has been cancelled
Branch Build CE / Build-Push Space Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Proxy Manifest (push) Has been cancelled
Branch Build CE / Merge Space Manifest (push) Has been cancelled
Branch Build CE / Prepare AIO Assets (push) Has been cancelled
Branch Build CE / Build Setup (push) Has been cancelled
Branch Build CE / Build-Push Live Collaboration Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Live Collaboration Manifest (push) Has been cancelled
Branch Build CE / Build-Push API Server Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge API Server Manifest (push) Has been cancelled
Branch Build CE / Build-Push Proxy Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Build-Push AIO Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge AIO Manifest (push) Has been cancelled
Branch Build CE / Upload Build Assets (push) Has been cancelled
Branch Build CE / Build Release (push) Has been cancelled
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 16s
CodeQL / Analyze (python) (push) Failing after 3s
i18n sync check / check:sync (push) Failing after 3s
React Doctor / react-doctor (push) Failing after 16s
Branch Build CE / Build-Push Admin Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Admin Manifest (push) Has been cancelled
Branch Build CE / Build-Push Web Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Web Manifest (push) Has been cancelled
Branch Build CE / Build-Push Space Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Proxy Manifest (push) Has been cancelled
Branch Build CE / Merge Space Manifest (push) Has been cancelled
Branch Build CE / Prepare AIO Assets (push) Has been cancelled
Branch Build CE / Build Setup (push) Has been cancelled
Branch Build CE / Build-Push Live Collaboration Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Live Collaboration Manifest (push) Has been cancelled
Branch Build CE / Build-Push API Server Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge API Server Manifest (push) Has been cancelled
Branch Build CE / Build-Push Proxy Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Build-Push AIO Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge AIO Manifest (push) Has been cancelled
Branch Build CE / Upload Build Assets (push) Has been cancelled
Branch Build CE / Build Release (push) Has been cancelled
This commit is contained in:
66
apps/web/core/lib/stale-asset-error.ts
Normal file
66
apps/web/core/lib/stale-asset-error.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
// Error signatures produced when a deploy removes hashed assets that an open tab
|
||||
// still references (stale-tab version skew).
|
||||
const STALE_ASSET_ERROR_SIGNATURES = [
|
||||
"Failed to fetch dynamically imported module", // Chromium
|
||||
"error loading dynamically imported module", // Firefox
|
||||
"Importing a module script failed", // Safari
|
||||
"Unable to preload CSS", // Vite preload helper
|
||||
// React Router's own wrapper when a route module's lazy import fails during
|
||||
// navigation — the original browser error above never reaches here as a
|
||||
// window event, only this synthesized message.
|
||||
"No result returned from dataStrategy for route",
|
||||
];
|
||||
|
||||
export const isStaleAssetErrorMessage = (message: string): boolean =>
|
||||
STALE_ASSET_ERROR_SIGNATURES.some((signature) => message.includes(signature));
|
||||
|
||||
export const isStaleAssetError = (error: unknown): boolean => {
|
||||
const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
|
||||
return isStaleAssetErrorMessage(message);
|
||||
};
|
||||
|
||||
// Reload-once-then-fall-through-to-boundary guard, shared by the window-level
|
||||
// listeners (entry.client.tsx) and the route ErrorBoundary (root.tsx) so both
|
||||
// paths to the same failure share one reload attempt instead of racing.
|
||||
const STALE_ASSET_RELOAD_KEY = "__plane_chunk_reload";
|
||||
const STALE_ASSET_RELOAD_WINDOW_MS = 30_000;
|
||||
|
||||
const hasRecentStaleAssetReload = (): boolean => {
|
||||
try {
|
||||
const lastReloadAt = Number(sessionStorage.getItem(STALE_ASSET_RELOAD_KEY));
|
||||
return Number.isFinite(lastReloadAt) && Date.now() - lastReloadAt < STALE_ASSET_RELOAD_WINDOW_MS;
|
||||
} catch {
|
||||
// No storage means no loop guard — never auto-reload in that case.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
let isRecoveringFromStaleAsset = false;
|
||||
|
||||
// Returns whether it actually triggered a reload, so callers that can otherwise
|
||||
// fall back to default browser error handling (e.g. Vite's preload-error
|
||||
// overlay) only suppress that fallback when a reload is really in flight.
|
||||
export const recoverFromStaleAsset = (): boolean => {
|
||||
if (isRecoveringFromStaleAsset) return false;
|
||||
isRecoveringFromStaleAsset = true;
|
||||
|
||||
if (hasRecentStaleAssetReload()) {
|
||||
// Second failure in a row — surface to the route error boundary instead of looping.
|
||||
isRecoveringFromStaleAsset = false;
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
sessionStorage.setItem(STALE_ASSET_RELOAD_KEY, String(Date.now()));
|
||||
} catch {
|
||||
isRecoveringFromStaleAsset = false;
|
||||
return false;
|
||||
}
|
||||
window.location.reload();
|
||||
return true;
|
||||
};
|
||||
Reference in New Issue
Block a user