@hivem/react
Advanced tools
+46
-68
@@ -40,3 +40,2 @@ "use strict"; | ||
| var clientAtom = (0, import_jotai.atom)(null); | ||
| var global_loaded_keys_atom = (0, import_jotai.atom)(/* @__PURE__ */ new Set()); | ||
| var global_debug_atom = (0, import_jotai.atom)(false); | ||
@@ -57,3 +56,2 @@ | ||
| const setClient = (0, import_jotai2.useSetAtom)(clientAtom); | ||
| const setLoadedKeys = (0, import_jotai2.useSetAtom)(global_loaded_keys_atom); | ||
| const setGlobalDebug = (0, import_jotai2.useSetAtom)(global_debug_atom); | ||
@@ -77,2 +75,3 @@ const [isReady, setIsReady] = (0, import_react.useState)(false); | ||
| let active = true; | ||
| if (debug) console.log("[HivemProvider] initializing client"); | ||
| const client = new import_js.HivemClient(stableConfig); | ||
@@ -82,7 +81,11 @@ clientRef.current = client; | ||
| const handleMessage = (msg) => { | ||
| if (debug) console.log("[HivemProvider] SSE message received:", msg.key, msg.value); | ||
| setKvState((current) => { | ||
| const next = msg.value !== void 0 ? (() => { | ||
| try { | ||
| return JSON.parse(msg.value); | ||
| const parsed = JSON.parse(msg.value); | ||
| if (debug) console.log("[HivemProvider] parsed value:", parsed); | ||
| return parsed; | ||
| } catch { | ||
| if (debug) console.log("[HivemProvider] using raw value:", msg.value); | ||
| return msg.value; | ||
@@ -92,3 +95,7 @@ } | ||
| const prev = current.get(msg.key); | ||
| if (Object.is(prev, next)) return current; | ||
| if (Object.is(prev, next)) { | ||
| if (debug) console.log("[HivemProvider] no change, skipping update for key:", msg.key); | ||
| return current; | ||
| } | ||
| if (debug) console.log("[HivemProvider] updating KV state:", msg.key, "from", JSON.stringify(prev), "to", JSON.stringify(next)); | ||
| const updated = new Map(current); | ||
@@ -102,9 +109,11 @@ if (next === void 0) { | ||
| }); | ||
| setLoadedKeys((prev) => new Set(prev).add(msg.key)); | ||
| }; | ||
| (async () => { | ||
| try { | ||
| if (debug) console.log("[HivemProvider] fetching auth"); | ||
| const auth = await getAuth(); | ||
| if (!active) return; | ||
| if (debug) console.log("[HivemProvider] auth received, identity:", auth.identity); | ||
| setAuth(auth); | ||
| if (debug) console.log("[HivemProvider] setting up SSE subscription"); | ||
| const { close } = client.subscribe( | ||
@@ -117,7 +126,10 @@ auth.identity, | ||
| setIsReady(true); | ||
| if (debug) console.log("[HivemProvider] provider ready"); | ||
| } catch (error) { | ||
| console.error("Failed to initialize Hivem provider:", error); | ||
| if (debug) console.log("[HivemProvider] initialization failed:", error); | ||
| } | ||
| })(); | ||
| return () => { | ||
| if (debug) console.log("[HivemProvider] cleaning up"); | ||
| active = false; | ||
@@ -128,2 +140,3 @@ closeRef.current?.(); | ||
| setIsReady(false); | ||
| if (debug) console.log("[HivemProvider] cleanup complete"); | ||
| }; | ||
@@ -144,24 +157,11 @@ }, [getAuth, setAuth, setKvState, stableConfig]); | ||
| const setKvState = (0, import_jotai3.useSetAtom)(global_kv_state_atom); | ||
| const setLoadedKeys = (0, import_jotai3.useSetAtom)(global_loaded_keys_atom); | ||
| const globalKeyAtom = (0, import_react2.useMemo)( | ||
| () => (0, import_jotai3.atom)((get2) => { | ||
| const map = get2(global_kv_state_atom); | ||
| const loaded = get2(global_loaded_keys_atom); | ||
| return { | ||
| value: map.get(key), | ||
| hasValue: loaded.has(key) | ||
| }; | ||
| }), | ||
| [key] | ||
| ); | ||
| const { value: atomValue, hasValue } = (0, import_jotai3.useAtomValue)(globalKeyAtom); | ||
| const kvState = (0, import_jotai3.useAtomValue)(global_kv_state_atom); | ||
| const [localValue, setLocalValue] = (0, import_react2.useState)(void 0); | ||
| const [error, setError] = (0, import_react2.useState)(null); | ||
| const [ready, setReady] = (0, import_react2.useState)(false); | ||
| const [ready, setReady] = (0, import_react2.useState)(!!defaultValue); | ||
| const [fetching, setFetching] = (0, import_react2.useState)(false); | ||
| const hasLoadedRef = (0, import_react2.useRef)(false); | ||
| const markReady = (0, import_react2.useCallback)(() => setReady((prev) => prev || true), []); | ||
| const load = (0, import_react2.useCallback)(async () => { | ||
| if (debug) console.log("[useKey]", key, "loading..."); | ||
| setFetching(true); | ||
| let globalData = void 0; | ||
| try { | ||
@@ -174,13 +174,3 @@ let data = await get(key); | ||
| } | ||
| setKvState((prev) => { | ||
| const prevValue = prev.get(key); | ||
| if (Object.is(prevValue, data)) { | ||
| if (debug) console.log("[useKey]", key, "no change, skipping set"); | ||
| return prev; | ||
| } | ||
| const next = new Map(prev); | ||
| next.set(key, data); | ||
| return next; | ||
| }); | ||
| setLoadedKeys((prev) => new Set(prev).add(key)); | ||
| globalData = data; | ||
| setLocalValue(data); | ||
@@ -193,9 +183,3 @@ setError(null); | ||
| if (debug) console.log("[useKey]", key, "specific not found error"); | ||
| setKvState((prev) => { | ||
| if (Object.is(prev.get(key), defaultValue)) return prev; | ||
| const next = new Map(prev); | ||
| next.set(key, defaultValue); | ||
| return next; | ||
| }); | ||
| setLoadedKeys((prev) => new Set(prev).add(key)); | ||
| globalData = defaultValue; | ||
| setLocalValue(defaultValue); | ||
@@ -205,19 +189,22 @@ if (debug) console.log("[useKey]", key, "used default on NOT_FOUND", defaultValue); | ||
| setError(e); | ||
| setLoadedKeys((prev) => new Set(prev).add(key)); | ||
| setLocalValue(void 0); | ||
| } | ||
| } finally { | ||
| if (globalData !== void 0) { | ||
| setKvState((prev) => { | ||
| const prevValue = prev.get(key); | ||
| if (Object.is(prevValue, globalData)) { | ||
| if (debug) console.log("[useKey]", key, "no change, skipping set"); | ||
| return prev; | ||
| } | ||
| const next = new Map(prev); | ||
| next.set(key, globalData); | ||
| return next; | ||
| }); | ||
| } | ||
| setFetching(false); | ||
| markReady(); | ||
| setReady(true); | ||
| if (debug) console.log("[useKey]", key, "loading done"); | ||
| if (debug) { | ||
| console.log(`[useKey:${key}] load state logs...`); | ||
| console.log(`[useKey:${key}] state change: localValue = ${JSON.stringify(localValue)}`); | ||
| console.log(`[useKey:${key}] state change: ready = ${ready}`); | ||
| console.log(`[useKey:${key}] state change: error = ${error ? error.message : "null"}`); | ||
| console.log(`[useKey:${key}] state change: fetching = ${fetching}`); | ||
| console.log(`[useKey:${key}] state change: hasValue = ${hasValue}`); | ||
| } | ||
| } | ||
| }, [key, get, setKvState, setLoadedKeys, defaultValue, debug]); | ||
| }, [key, get, setKvState, defaultValue, debug]); | ||
| const set = (0, import_react2.useCallback)( | ||
@@ -236,22 +223,13 @@ async (newValue) => { | ||
| (0, import_react2.useEffect)(() => { | ||
| const globalValue = kvState.get(key); | ||
| if (debug) { | ||
| console.log(`[useKey:${key}] atom change: atomValue=${JSON.stringify(atomValue)}, hasValue=${hasValue}`); | ||
| console.log(`[useKey:${key}] sync effect: globalValue=${JSON.stringify(globalValue)}, localValue=${JSON.stringify(localValue)}`); | ||
| } | ||
| }, [atomValue, hasValue]); | ||
| (0, import_react2.useEffect)(() => { | ||
| if (debug) console.log(`[useKey:${key}] ready check: hasValue=${hasValue}, calling markReady=${hasValue}`); | ||
| if (hasValue) markReady(); | ||
| }, [hasValue, markReady]); | ||
| (0, import_react2.useEffect)(() => { | ||
| if (!hasValue) { | ||
| if (debug) console.log(`[useKey:${key}] sync effect: SKIPPED (hasValue=false), atomValue=${JSON.stringify(atomValue)}`); | ||
| return; | ||
| if (!Object.is(globalValue, localValue)) { | ||
| if (debug) console.log(`[useKey:${key}] sync effect: updating localValue to ${JSON.stringify(globalValue)}`); | ||
| setLocalValue(globalValue); | ||
| } | ||
| if (debug) console.log(`[useKey:${key}] sync effect: APPLYING localValue=${JSON.stringify(atomValue)}`); | ||
| setLocalValue(atomValue); | ||
| }, [atomValue, hasValue]); | ||
| }, [kvState, key, localValue, debug]); | ||
| (0, import_react2.useEffect)(() => { | ||
| if (debug) console.log(`[useKey:${key}] load init: hasLoadedRef=${hasLoadedRef.current}`); | ||
| if (hasLoadedRef.current) return; | ||
| hasLoadedRef.current = true; | ||
| if (debug) console.log(`[useKey:${key}] load init`); | ||
| load(); | ||
@@ -266,5 +244,5 @@ }, [load]); | ||
| console.log(`[useKey:${key}] state change: fetching = ${fetching}`); | ||
| console.log(`[useKey:${key}] state change: hasValue = ${hasValue}`); | ||
| console.log(`[useKey:${key}] state change: globalValue = ${JSON.stringify(kvState.get(key))}`); | ||
| } | ||
| }, [debug, key, localValue, ready, error, fetching, hasValue]); | ||
| }, [debug, key, localValue, ready, error, fetching, kvState]); | ||
| (0, import_react2.useEffect)(() => { | ||
@@ -271,0 +249,0 @@ console.log(`[useKey:${key}] MOUNT`); |
+48
-70
@@ -12,3 +12,2 @@ // src/provider.tsx | ||
| var clientAtom = atom(null); | ||
| var global_loaded_keys_atom = atom(/* @__PURE__ */ new Set()); | ||
| var global_debug_atom = atom(false); | ||
@@ -29,3 +28,2 @@ | ||
| const setClient = useSetAtom(clientAtom); | ||
| const setLoadedKeys = useSetAtom(global_loaded_keys_atom); | ||
| const setGlobalDebug = useSetAtom(global_debug_atom); | ||
@@ -49,2 +47,3 @@ const [isReady, setIsReady] = useState(false); | ||
| let active = true; | ||
| if (debug) console.log("[HivemProvider] initializing client"); | ||
| const client = new HivemClient(stableConfig); | ||
@@ -54,7 +53,11 @@ clientRef.current = client; | ||
| const handleMessage = (msg) => { | ||
| if (debug) console.log("[HivemProvider] SSE message received:", msg.key, msg.value); | ||
| setKvState((current) => { | ||
| const next = msg.value !== void 0 ? (() => { | ||
| try { | ||
| return JSON.parse(msg.value); | ||
| const parsed = JSON.parse(msg.value); | ||
| if (debug) console.log("[HivemProvider] parsed value:", parsed); | ||
| return parsed; | ||
| } catch { | ||
| if (debug) console.log("[HivemProvider] using raw value:", msg.value); | ||
| return msg.value; | ||
@@ -64,3 +67,7 @@ } | ||
| const prev = current.get(msg.key); | ||
| if (Object.is(prev, next)) return current; | ||
| if (Object.is(prev, next)) { | ||
| if (debug) console.log("[HivemProvider] no change, skipping update for key:", msg.key); | ||
| return current; | ||
| } | ||
| if (debug) console.log("[HivemProvider] updating KV state:", msg.key, "from", JSON.stringify(prev), "to", JSON.stringify(next)); | ||
| const updated = new Map(current); | ||
@@ -74,9 +81,11 @@ if (next === void 0) { | ||
| }); | ||
| setLoadedKeys((prev) => new Set(prev).add(msg.key)); | ||
| }; | ||
| (async () => { | ||
| try { | ||
| if (debug) console.log("[HivemProvider] fetching auth"); | ||
| const auth = await getAuth(); | ||
| if (!active) return; | ||
| if (debug) console.log("[HivemProvider] auth received, identity:", auth.identity); | ||
| setAuth(auth); | ||
| if (debug) console.log("[HivemProvider] setting up SSE subscription"); | ||
| const { close } = client.subscribe( | ||
@@ -89,7 +98,10 @@ auth.identity, | ||
| setIsReady(true); | ||
| if (debug) console.log("[HivemProvider] provider ready"); | ||
| } catch (error) { | ||
| console.error("Failed to initialize Hivem provider:", error); | ||
| if (debug) console.log("[HivemProvider] initialization failed:", error); | ||
| } | ||
| })(); | ||
| return () => { | ||
| if (debug) console.log("[HivemProvider] cleaning up"); | ||
| active = false; | ||
@@ -100,2 +112,3 @@ closeRef.current?.(); | ||
| setIsReady(false); | ||
| if (debug) console.log("[HivemProvider] cleanup complete"); | ||
| }; | ||
@@ -107,4 +120,4 @@ }, [getAuth, setAuth, setKvState, stableConfig]); | ||
| // src/hooks.ts | ||
| import { useCallback, useMemo as useMemo2, useState as useState2, useEffect as useEffect2, useRef as useRef2 } from "react"; | ||
| import { useAtomValue, atom as atom2, useSetAtom as useSetAtom2 } from "jotai"; | ||
| import { useCallback, useState as useState2, useEffect as useEffect2 } from "react"; | ||
| import { useAtomValue, useSetAtom as useSetAtom2 } from "jotai"; | ||
| import { HivemError, HivemErrorCode } from "@hivem/js"; | ||
@@ -117,24 +130,11 @@ function useKey(key, options) { | ||
| const setKvState = useSetAtom2(global_kv_state_atom); | ||
| const setLoadedKeys = useSetAtom2(global_loaded_keys_atom); | ||
| const globalKeyAtom = useMemo2( | ||
| () => atom2((get2) => { | ||
| const map = get2(global_kv_state_atom); | ||
| const loaded = get2(global_loaded_keys_atom); | ||
| return { | ||
| value: map.get(key), | ||
| hasValue: loaded.has(key) | ||
| }; | ||
| }), | ||
| [key] | ||
| ); | ||
| const { value: atomValue, hasValue } = useAtomValue(globalKeyAtom); | ||
| const kvState = useAtomValue(global_kv_state_atom); | ||
| const [localValue, setLocalValue] = useState2(void 0); | ||
| const [error, setError] = useState2(null); | ||
| const [ready, setReady] = useState2(false); | ||
| const [ready, setReady] = useState2(!!defaultValue); | ||
| const [fetching, setFetching] = useState2(false); | ||
| const hasLoadedRef = useRef2(false); | ||
| const markReady = useCallback(() => setReady((prev) => prev || true), []); | ||
| const load = useCallback(async () => { | ||
| if (debug) console.log("[useKey]", key, "loading..."); | ||
| setFetching(true); | ||
| let globalData = void 0; | ||
| try { | ||
@@ -147,13 +147,3 @@ let data = await get(key); | ||
| } | ||
| setKvState((prev) => { | ||
| const prevValue = prev.get(key); | ||
| if (Object.is(prevValue, data)) { | ||
| if (debug) console.log("[useKey]", key, "no change, skipping set"); | ||
| return prev; | ||
| } | ||
| const next = new Map(prev); | ||
| next.set(key, data); | ||
| return next; | ||
| }); | ||
| setLoadedKeys((prev) => new Set(prev).add(key)); | ||
| globalData = data; | ||
| setLocalValue(data); | ||
@@ -166,9 +156,3 @@ setError(null); | ||
| if (debug) console.log("[useKey]", key, "specific not found error"); | ||
| setKvState((prev) => { | ||
| if (Object.is(prev.get(key), defaultValue)) return prev; | ||
| const next = new Map(prev); | ||
| next.set(key, defaultValue); | ||
| return next; | ||
| }); | ||
| setLoadedKeys((prev) => new Set(prev).add(key)); | ||
| globalData = defaultValue; | ||
| setLocalValue(defaultValue); | ||
@@ -178,19 +162,22 @@ if (debug) console.log("[useKey]", key, "used default on NOT_FOUND", defaultValue); | ||
| setError(e); | ||
| setLoadedKeys((prev) => new Set(prev).add(key)); | ||
| setLocalValue(void 0); | ||
| } | ||
| } finally { | ||
| if (globalData !== void 0) { | ||
| setKvState((prev) => { | ||
| const prevValue = prev.get(key); | ||
| if (Object.is(prevValue, globalData)) { | ||
| if (debug) console.log("[useKey]", key, "no change, skipping set"); | ||
| return prev; | ||
| } | ||
| const next = new Map(prev); | ||
| next.set(key, globalData); | ||
| return next; | ||
| }); | ||
| } | ||
| setFetching(false); | ||
| markReady(); | ||
| setReady(true); | ||
| if (debug) console.log("[useKey]", key, "loading done"); | ||
| if (debug) { | ||
| console.log(`[useKey:${key}] load state logs...`); | ||
| console.log(`[useKey:${key}] state change: localValue = ${JSON.stringify(localValue)}`); | ||
| console.log(`[useKey:${key}] state change: ready = ${ready}`); | ||
| console.log(`[useKey:${key}] state change: error = ${error ? error.message : "null"}`); | ||
| console.log(`[useKey:${key}] state change: fetching = ${fetching}`); | ||
| console.log(`[useKey:${key}] state change: hasValue = ${hasValue}`); | ||
| } | ||
| } | ||
| }, [key, get, setKvState, setLoadedKeys, defaultValue, debug]); | ||
| }, [key, get, setKvState, defaultValue, debug]); | ||
| const set = useCallback( | ||
@@ -209,22 +196,13 @@ async (newValue) => { | ||
| useEffect2(() => { | ||
| const globalValue = kvState.get(key); | ||
| if (debug) { | ||
| console.log(`[useKey:${key}] atom change: atomValue=${JSON.stringify(atomValue)}, hasValue=${hasValue}`); | ||
| console.log(`[useKey:${key}] sync effect: globalValue=${JSON.stringify(globalValue)}, localValue=${JSON.stringify(localValue)}`); | ||
| } | ||
| }, [atomValue, hasValue]); | ||
| useEffect2(() => { | ||
| if (debug) console.log(`[useKey:${key}] ready check: hasValue=${hasValue}, calling markReady=${hasValue}`); | ||
| if (hasValue) markReady(); | ||
| }, [hasValue, markReady]); | ||
| useEffect2(() => { | ||
| if (!hasValue) { | ||
| if (debug) console.log(`[useKey:${key}] sync effect: SKIPPED (hasValue=false), atomValue=${JSON.stringify(atomValue)}`); | ||
| return; | ||
| if (!Object.is(globalValue, localValue)) { | ||
| if (debug) console.log(`[useKey:${key}] sync effect: updating localValue to ${JSON.stringify(globalValue)}`); | ||
| setLocalValue(globalValue); | ||
| } | ||
| if (debug) console.log(`[useKey:${key}] sync effect: APPLYING localValue=${JSON.stringify(atomValue)}`); | ||
| setLocalValue(atomValue); | ||
| }, [atomValue, hasValue]); | ||
| }, [kvState, key, localValue, debug]); | ||
| useEffect2(() => { | ||
| if (debug) console.log(`[useKey:${key}] load init: hasLoadedRef=${hasLoadedRef.current}`); | ||
| if (hasLoadedRef.current) return; | ||
| hasLoadedRef.current = true; | ||
| if (debug) console.log(`[useKey:${key}] load init`); | ||
| load(); | ||
@@ -239,5 +217,5 @@ }, [load]); | ||
| console.log(`[useKey:${key}] state change: fetching = ${fetching}`); | ||
| console.log(`[useKey:${key}] state change: hasValue = ${hasValue}`); | ||
| console.log(`[useKey:${key}] state change: globalValue = ${JSON.stringify(kvState.get(key))}`); | ||
| } | ||
| }, [debug, key, localValue, ready, error, fetching, hasValue]); | ||
| }, [debug, key, localValue, ready, error, fetching, kvState]); | ||
| useEffect2(() => { | ||
@@ -244,0 +222,0 @@ console.log(`[useKey:${key}] MOUNT`); |
+1
-1
| { | ||
| "name": "@hivem/react", | ||
| "version": "0.2.5", | ||
| "version": "0.2.6", | ||
| "description": "React SDK for Hivem - auth-based KV service with sync support", | ||
@@ -5,0 +5,0 @@ "type": "module", |
25016
-5.38%590
-6.94%