UNPKG

@yunu-lab/rpc-react

Version:
336 lines (335 loc) 9.88 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const toolkit = require("@reduxjs/toolkit"); const jsxRuntime = require("react/jsx-runtime"); const React = require("react"); const reactRedux = require("react-redux"); const rpcTs = require("@yunu-lab/rpc-ts"); const extendStore = (options) => { const { repository, store, slices = {} } = options; const rpcSlice = toolkit.createSlice({ name: "rpc", initialState: {}, reducers: { setData: (state, action) => { const { type, data } = action.payload; state[type] = data; } } }); const newReducer = toolkit.combineReducers({ ...slices, rpc: rpcSlice.reducer }); store.replaceReducer(newReducer); const unsubscribe = repository.onDataChanged((events) => { events.forEach((event) => { console.log( event, "--------------------------------events-----------------------" ); const { type, payload } = event; const storageType = repository.getStorageType(String(type)); if (storageType === "singleton") { store.dispatch( rpcSlice.actions.setData({ type: String(type), data: payload }) ); } else { const dataObject = payload.reduce( (acc, item) => { const id = item.id; acc[id] = item; return acc; }, {} ); store.dispatch( rpcSlice.actions.setData({ type: String(type), data: dataObject }) ); } }); }); return { store, repository, unsubscribe }; }; const RpcContext = React.createContext(null); const RpcProvider = ({ children, repository }) => { return /* @__PURE__ */ jsxRuntime.jsx(RpcContext.Provider, { value: { repository }, children }); }; const useRpc = () => { const context = React.useContext(RpcContext); if (!context) { throw new Error("useRpc must be used within an RpcProvider"); } const repository = React.useMemo( () => context.repository, [context.repository] ); return { repository }; }; const createRpcHooks = (typeKeys) => { const toPascalCase = (s) => { return s.split("_").map( (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase() ).join(""); }; const hooks = {}; typeKeys.forEach((typeName) => { const hookName = `use${toPascalCase( String(typeName) )}`; const typeKey = typeName; function useHook(id) { const { repository } = useRpc(); const allData = reactRedux.useSelector( (state) => state.rpc[typeKey] || {} ); const findById = React.useCallback( (id2) => repository.findById(typeKey, id2), [repository] ); const findAll = React.useCallback( () => repository.findAll(typeKey), [repository] ); const mergeRpc = React.useCallback( (data) => repository.mergeRpc(typeKey, data), [repository] ); if (id !== void 0) { return findById(id); } return { [`${String(typeKey)}s`]: Object.values(allData), [`${String(typeKey)}Map`]: allData, findById, findAll, mergeRpc }; } hooks[hookName] = useHook; const fullRelatedHookName = `use${toPascalCase( String(typeName) )}FullRelatedData`; function useFullRelatedHook(id) { const { repository } = useRpc(); const allRpcData = reactRedux.useSelector( (state) => state.rpc ); const [fullData, setFullData] = React.useState(null); const allRpcDataString = React.useMemo( () => JSON.stringify(allRpcData), [allRpcData] ); const getData = React.useCallback(() => { try { const result = repository.getFullRelatedData( typeName, id ); setFullData(result); } catch { setFullData(null); } }, [repository, id]); React.useEffect(() => { console.log( `[${String( typeName )}FullRelatedData] Fetching full related data for id:`, id ); getData(); }, [getData, allRpcDataString, id]); return fullData; } hooks[fullRelatedHookName] = useFullRelatedHook; }); typeKeys.forEach((typeName) => { const listenerHookName = `use${toPascalCase( String(typeName) )}Listener`; function useListenerHook(callback) { const { repository } = useRpc(); const callbackRef = React.useRef(callback); const listenerIdRef = React.useRef(null); const isSubscribedRef = React.useRef(false); callbackRef.current = callback; const filteredCallback = React.useCallback( (events) => { const filteredEvents = events.filter( (event) => event.type === typeName ); if (filteredEvents.length > 0) { const event = filteredEvents[0]; console.log( `[${String( typeName )}Listener] Calling callback with:`, event ); const storageType = repository.getStorageType?.(String(typeName)); if (storageType === "singleton" && Array.isArray(event.payload) && event.payload.length > 0) { const singletonEvent = { ...event, payload: event.payload[0] }; callbackRef.current(singletonEvent); } else { callbackRef.current(event); } } }, [] ); React.useEffect(() => { if (listenerIdRef.current && typeof repository.offDataChanged === "function") { repository.offDataChanged(listenerIdRef.current); listenerIdRef.current = null; isSubscribedRef.current = false; } if (!isSubscribedRef.current) { listenerIdRef.current = repository.onDataChanged( filteredCallback, { types: [typeName] } ); isSubscribedRef.current = true; } return () => { if (listenerIdRef.current && typeof repository.offDataChanged === "function") { repository.offDataChanged( listenerIdRef.current ); listenerIdRef.current = null; isSubscribedRef.current = false; } }; }, [repository, filteredCallback]); return () => { }; } hooks[listenerHookName] = useListenerHook; }); function useDataListener(callback, options) { const { repository } = useRpc(); const callbackRef = React.useRef(callback); const listenerIdRef = React.useRef(null); callbackRef.current = callback; React.useEffect(() => { if (listenerIdRef.current && typeof repository.offDataChanged === "function") { repository.offDataChanged(listenerIdRef.current); listenerIdRef.current = null; } listenerIdRef.current = repository.onDataChanged( callbackRef.current, { types: options?.types || typeKeys } ); return () => { if (listenerIdRef.current && typeof repository.offDataChanged === "function") { repository.offDataChanged(listenerIdRef.current); listenerIdRef.current = null; } }; }, [repository, options?.types]); return () => { }; } hooks.useDataListener = useDataListener; typeKeys.forEach((typeName) => { const relatedHookName = `use${toPascalCase( String(typeName) )}Related`; function useRelatedHook(id, targetType) { const { repository } = useRpc(); const sourceData = reactRedux.useSelector( (state) => state.rpc[typeName] || {} ); const targetData = reactRedux.useSelector( (state) => state.rpc[targetType] || {} ); const [relatedData, setRelatedData] = React.useState([]); const sourceDataString = React.useMemo( () => JSON.stringify(sourceData), [sourceData] ); const targetDataString = React.useMemo( () => JSON.stringify(targetData), [targetData] ); const getRelatedData = React.useCallback(() => { try { const result = repository.getRelated( typeName, id, targetType ); setRelatedData(result); } catch { setRelatedData([]); } }, [repository, id, targetType]); React.useEffect(() => { console.log( `[${String( typeName )}Related] Fetching related data for id:`, id, "targetType:", targetType ); getRelatedData(); }, [ getRelatedData, id, sourceDataString, targetDataString, targetType ]); return relatedData; } hooks[relatedHookName] = useRelatedHook; }); function useHandleMessages() { const { repository } = useRpc(); const handleMessages = (messages, callbacks) => { repository.handleMessages(messages, callbacks); }; const handleMessagesTyped = (messages, callbacks) => { repository.handleMessages(messages, callbacks); }; return { handleMessages, handleMessagesTyped }; } hooks.useHandleMessages = useHandleMessages; return hooks; }; Object.defineProperty(exports, "Rpc", { enumerable: true, get: () => rpcTs.Rpc }); Object.defineProperty(exports, "RpcRepository", { enumerable: true, get: () => rpcTs.RpcRepository }); exports.RpcProvider = RpcProvider; exports.createRpcHooks = createRpcHooks; exports.extendStore = extendStore; exports.useRpc = useRpc; //# sourceMappingURL=index.js.map