From b3e3a4442049c18496e029e17e7b604a87ac4aa3 Mon Sep 17 00:00:00 2001 From: Sasha Date: Tue, 21 Feb 2023 23:42:08 +0100 Subject: [PATCH] implement useStoreMessages --- src/index.ts | 2 +- src/types.ts | 2 +- src/useCreateWaku.ts | 4 +- ...ilterSubscribe.ts => useFilterMessages.ts} | 22 +++--- src/useStoreMessages.ts | 77 +++++++++++++++++++ 5 files changed, 94 insertions(+), 13 deletions(-) rename src/{useFilterSubscribe.ts => useFilterMessages.ts} (73%) create mode 100644 src/useStoreMessages.ts diff --git a/src/index.ts b/src/index.ts index 4dc25f7..9596049 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,7 @@ export { useCreateLightNode, useCreateRelayNode, } from "./useCreateWaku"; -export { useFilterSubscribe } from "./useFilterSubscribe"; +export { useFilterMessages } from "./useFilterMessages"; export { FullNodeProvider, LightNodeProvider, diff --git a/src/types.ts b/src/types.ts index 107b6a5..d0d2e1d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,7 +7,7 @@ export type HookState = { error: undefined | string; }; -export type CrateWakuHook = HookState & { +export type CrateNodeResult = HookState & { node: undefined | T; }; diff --git a/src/useCreateWaku.ts b/src/useCreateWaku.ts index f1cc6ee..688f3e0 100644 --- a/src/useCreateWaku.ts +++ b/src/useCreateWaku.ts @@ -5,7 +5,7 @@ import type { FullNode, LightNode, RelayNode, Waku } from "@waku/interfaces"; import type { BootstrapNodeOptions, - CrateWakuHook, + CrateNodeResult, FullNodeOptions, LightNodeOptions, RelayNodeOptions, @@ -19,7 +19,7 @@ type CreateNodeParams = BootstrapNodeOptions & { const useCreateNode = ( params: CreateNodeParams, -): CrateWakuHook => { +): CrateNodeResult => { const { factory, options, protocols = [] } = params; const [node, setNode] = React.useState(undefined); diff --git a/src/useFilterSubscribe.ts b/src/useFilterMessages.ts similarity index 73% rename from src/useFilterSubscribe.ts rename to src/useFilterMessages.ts index 23cfde5..ee09f2b 100644 --- a/src/useFilterSubscribe.ts +++ b/src/useFilterMessages.ts @@ -1,20 +1,24 @@ import React from "react"; -import type { IDecodedMessage, IDecoder, Waku } from "@waku/interfaces"; +import type { IFilter, IDecodedMessage, IDecoder } from "@waku/interfaces"; import type { HookState } from "./types"; -type UseFilterSubscribeParams = { - node: Waku; +type AbstractFilterNode = { + filter: IFilter; +}; + +type UseFilterMessagesParams = { + node: AbstractFilterNode; decoder: IDecoder; }; -type UseFilterSubscribeResult = HookState & { +type UseFilterMessagesResult = HookState & { messages: IDecodedMessage[]; }; -export const useFilterSubscribe = ( - params: UseFilterSubscribeParams, -): UseFilterSubscribeResult => { +export const useFilterMessages = ( + params: UseFilterMessagesParams, +): UseFilterMessagesResult => { const { node, decoder } = params; const [error, setError] = React.useState(undefined); @@ -32,8 +36,8 @@ export const useFilterSubscribe = ( let unsubscribe: null | (() => Promise) = null; setLoading(true); - node?.filter - ?.subscribe([decoder], pushMessage) + node.filter + .subscribe([decoder], pushMessage) .then((unsubscribeFn) => { setLoading(false); unsubscribe = unsubscribeFn; diff --git a/src/useStoreMessages.ts b/src/useStoreMessages.ts new file mode 100644 index 0000000..a805135 --- /dev/null +++ b/src/useStoreMessages.ts @@ -0,0 +1,77 @@ +import React from "react"; +import type { + StoreQueryOptions, + IStore, + IDecoder, + IDecodedMessage, +} from "@waku/interfaces"; +import type { HookState } from "./types"; + +type AbstractStoreNode = { + store: IStore; +}; + +type UseStoreMessagesParams = { + node: AbstractStoreNode; + decoder: IDecoder; + options: StoreQueryOptions; +}; + +type UseStoreMessagesResult = HookState & { + messages: IDecodedMessage[]; +}; + +const useStoreMessages = ( + params: UseStoreMessagesParams, +): UseStoreMessagesResult => { + const { node, decoder, options } = params; + + const [error, setError] = React.useState(undefined); + const [isLoading, setLoading] = React.useState(false); + const [messages, setMessage] = React.useState([]); + + const pushMessage = React.useCallback( + (message: IDecodedMessage[]): void => { + setMessage((prev) => [...prev, ...message]); + }, + [setMessage], + ); + + React.useEffect(() => { + let cancelled: boolean = false; + setLoading(true); + + Promise + .resolve() + .then(async () => { + for await (const promises of node.store.queryGenerator([decoder], options)) { + if (cancelled) { + return; + } + + const messagesRaw = await Promise.all(promises); + const filteredMessages = messagesRaw.filter((v): v is IDecodedMessage => !!v); + + pushMessage(filteredMessages); + } + + setLoading(false); + }) + .catch((err) => { + setLoading(false); + setError( + `Failed to query messages from store: ${err?.message || "no message"}`, + ); + }); + + return () => { + cancelled = true; + }; + }, [node, decoder, options, pushMessage, setError, setLoading]); + + return { + error, + isLoading, + messages, + }; +};