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}`;
|
||||
}
|
||||
|
||||
/** Key for storing registry on window to survive HMR */
|
||||
const REGISTRY_KEY = '__NITESHIFT_DIALS_REGISTRY__';
|
||||
|
||||
/**
|
||||
* Singleton registry for all dials
|
||||
*/
|
||||
class DialRegistry {
|
||||
private static instance: DialRegistry | null = null;
|
||||
|
||||
/** All registered dials */
|
||||
private dials = new Map<string, DialRegistration>();
|
||||
|
||||
|
|
@ -43,21 +44,11 @@ class DialRegistry {
|
|||
/** Project ID for storage scoping */
|
||||
private projectId?: string;
|
||||
|
||||
private constructor() {
|
||||
constructor() {
|
||||
// Load persisted values on initialization
|
||||
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
|
||||
*/
|
||||
|
|
@ -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 const getDialRegistry = () => DialRegistry.getInstance();
|
||||
export const getDialRegistry = getGlobalRegistry;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue