mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 04:37:11 +01:00
Fix dials HMR by using window-based singleton
The static class property singleton pattern doesn't survive HMR when module boundaries get crossed. New dials would register with a fresh registry instance while DialsOverlay stayed subscribed to the old one. Fix: Store the singleton on `window.__NITESHIFT_DIALS_REGISTRY__` so it persists across module re-evaluations during hot reload. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
2727fd6dff
commit
23a3c6cf6b
1 changed files with 26 additions and 14 deletions
|
|
@ -25,12 +25,13 @@ function getStorageKey(projectId?: string): string {
|
||||||
: `${STORAGE_KEY_PREFIX}-v${STORAGE_VERSION}`;
|
: `${STORAGE_KEY_PREFIX}-v${STORAGE_VERSION}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Key for storing registry on window to survive HMR */
|
||||||
|
const REGISTRY_KEY = '__NITESHIFT_DIALS_REGISTRY__';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton registry for all dials
|
* Singleton registry for all dials
|
||||||
*/
|
*/
|
||||||
class DialRegistry {
|
class DialRegistry {
|
||||||
private static instance: DialRegistry | null = null;
|
|
||||||
|
|
||||||
/** All registered dials */
|
/** All registered dials */
|
||||||
private dials = new Map<string, DialRegistration>();
|
private dials = new Map<string, DialRegistration>();
|
||||||
|
|
||||||
|
|
@ -43,21 +44,11 @@ class DialRegistry {
|
||||||
/** Project ID for storage scoping */
|
/** Project ID for storage scoping */
|
||||||
private projectId?: string;
|
private projectId?: string;
|
||||||
|
|
||||||
private constructor() {
|
constructor() {
|
||||||
// Load persisted values on initialization
|
// Load persisted values on initialization
|
||||||
this.loadFromStorage();
|
this.loadFromStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the singleton instance
|
|
||||||
*/
|
|
||||||
static getInstance(): DialRegistry {
|
|
||||||
if (!DialRegistry.instance) {
|
|
||||||
DialRegistry.instance = new DialRegistry();
|
|
||||||
}
|
|
||||||
return DialRegistry.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the project ID for storage scoping
|
* Set the project ID for storage scoping
|
||||||
*/
|
*/
|
||||||
|
|
@ -310,5 +301,26 @@ class DialRegistry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the singleton registry instance
|
||||||
|
* Uses window storage to survive HMR module re-evaluation
|
||||||
|
*/
|
||||||
|
function getGlobalRegistry(): DialRegistry {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
if (!(window as any)[REGISTRY_KEY]) {
|
||||||
|
(window as any)[REGISTRY_KEY] = new DialRegistry();
|
||||||
|
}
|
||||||
|
return (window as any)[REGISTRY_KEY];
|
||||||
|
}
|
||||||
|
// SSR fallback - module-level instance
|
||||||
|
if (!ssrInstance) {
|
||||||
|
ssrInstance = new DialRegistry();
|
||||||
|
}
|
||||||
|
return ssrInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** SSR fallback instance */
|
||||||
|
let ssrInstance: DialRegistry | null = null;
|
||||||
|
|
||||||
// Export singleton instance getter
|
// Export singleton instance getter
|
||||||
export const getDialRegistry = () => DialRegistry.getInstance();
|
export const getDialRegistry = getGlobalRegistry;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue