UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

1 lines 3.86 kB
{"version":3,"file":"devSingleton.mjs","names":[],"sources":["../../src/utils/devSingleton.ts"],"sourcesContent":["const DEV = process.env.NODE_ENV === 'development';\n\ntype Registry = {\n global: Map<string, number>;\n scoped: Map<string, WeakMap<object, number>>;\n};\n\nconst GLOBAL_KEY = '__LOBE_UI_DEV_SINGLETON_REGISTRY__';\n\nconst getRegistry = (): Registry => {\n const g = globalThis as unknown as Record<string, unknown>;\n if (!g[GLOBAL_KEY]) {\n g[GLOBAL_KEY] = {\n global: new Map<string, number>(),\n scoped: new Map<string, WeakMap<object, number>>(),\n } satisfies Registry;\n }\n return g[GLOBAL_KEY] as Registry;\n};\n\nconst getScopedMap = (registry: Registry, name: string) => {\n const existing = registry.scoped.get(name);\n if (existing) return existing;\n const next = new WeakMap<object, number>();\n registry.scoped.set(name, next);\n return next;\n};\n\nconst singletonError = (name: string) =>\n new Error(\n `[lobe-ui] ${name} must be rendered only once in a single React tree. ` +\n `You probably mounted it multiple times (or in multiple roots).`,\n );\n\n/**\n * Dev-only singleton guard.\n * - If `scope` is provided, it's enforced per scope object (e.g. portal root).\n * - Otherwise it's enforced globally in the current JS runtime.\n */\nexport const registerDevSingleton = (name: string, scope?: object | null): (() => void) => {\n if (!DEV) return () => {};\n\n const registry = getRegistry();\n\n // Scoped singleton (preferred)\n if (scope) {\n const scoped = getScopedMap(registry, name);\n const prev = scoped.get(scope) ?? 0;\n const next = prev + 1;\n scoped.set(scope, next);\n\n if (next > 1) {\n // rollback to avoid poisoning the registry after throwing\n if (prev === 0) scoped.delete(scope);\n else scoped.set(scope, prev);\n throw singletonError(name);\n }\n\n return () => {\n const curr = scoped.get(scope) ?? 0;\n const after = curr - 1;\n if (after <= 0) scoped.delete(scope);\n else scoped.set(scope, after);\n };\n }\n\n // Global singleton (fallback)\n const prev = registry.global.get(name) ?? 0;\n const next = prev + 1;\n registry.global.set(name, next);\n\n if (next > 1) {\n // rollback to avoid poisoning the registry after throwing\n if (prev === 0) registry.global.delete(name);\n else registry.global.set(name, prev);\n throw singletonError(name);\n }\n\n return () => {\n const curr = registry.global.get(name) ?? 0;\n const after = curr - 1;\n if (after <= 0) registry.global.delete(name);\n else registry.global.set(name, after);\n };\n};\n"],"mappings":";AAAA,MAAM,MAAM,QAAQ,IAAI,aAAa;AAOrC,MAAM,aAAa;AAEnB,MAAM,oBAA8B;CAClC,MAAM,IAAI;CACV,IAAI,CAAC,EAAE,aACL,EAAE,cAAc;EACd,wBAAQ,IAAI,IAAoB;EAChC,wBAAQ,IAAI,IAAqC;CACnD;CAEF,OAAO,EAAE;AACX;AAEA,MAAM,gBAAgB,UAAoB,SAAiB;CACzD,MAAM,WAAW,SAAS,OAAO,IAAI,IAAI;CACzC,IAAI,UAAU,OAAO;CACrB,MAAM,uBAAO,IAAI,QAAwB;CACzC,SAAS,OAAO,IAAI,MAAM,IAAI;CAC9B,OAAO;AACT;AAEA,MAAM,kBAAkB,yBACtB,IAAI,MACF,aAAa,KAAK,mHAEpB;;;;;;AAOF,MAAa,wBAAwB,MAAc,UAAwC;CACzF,IAAI,CAAC,KAAK,aAAa,CAAC;CAExB,MAAM,WAAW,YAAY;CAG7B,IAAI,OAAO;EACT,MAAM,SAAS,aAAa,UAAU,IAAI;EAC1C,MAAM,OAAO,OAAO,IAAI,KAAK,KAAK;EAClC,MAAM,OAAO,OAAO;EACpB,OAAO,IAAI,OAAO,IAAI;EAEtB,IAAI,OAAO,GAAG;GAEZ,IAAI,SAAS,GAAG,OAAO,OAAO,KAAK;QAC9B,OAAO,IAAI,OAAO,IAAI;GAC3B,MAAM,eAAe,IAAI;EAC3B;EAEA,aAAa;GAEX,MAAM,SADO,OAAO,IAAI,KAAK,KAAK,KACb;GACrB,IAAI,SAAS,GAAG,OAAO,OAAO,KAAK;QAC9B,OAAO,IAAI,OAAO,KAAK;EAC9B;CACF;CAGA,MAAM,OAAO,SAAS,OAAO,IAAI,IAAI,KAAK;CAC1C,MAAM,OAAO,OAAO;CACpB,SAAS,OAAO,IAAI,MAAM,IAAI;CAE9B,IAAI,OAAO,GAAG;EAEZ,IAAI,SAAS,GAAG,SAAS,OAAO,OAAO,IAAI;OACtC,SAAS,OAAO,IAAI,MAAM,IAAI;EACnC,MAAM,eAAe,IAAI;CAC3B;CAEA,aAAa;EAEX,MAAM,SADO,SAAS,OAAO,IAAI,IAAI,KAAK,KACrB;EACrB,IAAI,SAAS,GAAG,SAAS,OAAO,OAAO,IAAI;OACtC,SAAS,OAAO,IAAI,MAAM,KAAK;CACtC;AACF"}