mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 23:16:21 +00:00
useNitroQuery: add accept() predicate; migrate two mod-tools chatlog views
Many composer/parser pairs on the Nitro wire are correlation-key based:
the request carries a key (roomId, issueId, etc.) and the response shows
up on the globally-shared event bus, where other components may be
listening for the same parser type with a different key. The previous
useNitroQuery resolved on the FIRST matching parser event regardless of
key — useless for that pattern, which is why two obvious migration
targets (ModToolsChatlogView, CfhChatlogView) were skipped earlier.
Adapter change
- New optional `accept?: (event) => boolean` on NitroQueryConfig.
- In awaitNitroResponse, events for which accept returns false are
IGNORED rather than resolving the promise. The listener stays
registered, the timeout still applies. This lets callers do:
accept: e => e.getParser()?.data.roomId === roomId
Migrations
- src/components/mod-tools/views/room/ModToolsChatlogView.tsx
- Was: useState<ChatRecordData>(null) + useMessageEvent with
`if (parser.data.roomId !== roomId) return; setRoomChatlog(...)` +
a mount-only useEffect dispatching the composer.
- Now: a single useNitroQuery call keyed on roomId; accept filters
by roomId; the query is enabled only when roomId is set.
The composer is no longer re-dispatched on remount within
staleTime; switching to a different room still triggers a fresh
fetch because the queryKey changes.
- src/components/mod-tools/views/tickets/CfhChatlogView.tsx
- Same pattern, keyed on issueId.
Both migrations drop ~15 lines per file (no more local state + manual
listener + manual send) while gaining cache/dedup/loading/error
handling from TanStack Query.
Verification
- yarn eslint on the four files: 1 pre-existing error (the
IMessageEvent "redundant union" false positive in createNitroQuery
that we already documented — local sandbox doesn't have the
renderer SDK installed, so its types resolve as `any`).
- yarn test: 49/49 passing.
- yarn tsc on the four files: clean.
This commit is contained in:
@@ -23,6 +23,14 @@ export interface NitroQueryConfig<TParser extends IMessageEvent, TData>
|
||||
* Maps the parser event to the data the component cares about.
|
||||
*/
|
||||
select?: (event: TParser) => TData;
|
||||
/**
|
||||
* Optional predicate to ignore parser events that don't match this
|
||||
* query (typically used as a correlation-key filter on a globally
|
||||
* shared event stream — e.g. `e => e.getParser()?.roomId === roomId`).
|
||||
* When the predicate returns false, the listener stays registered
|
||||
* and keeps waiting; the timeout still applies.
|
||||
*/
|
||||
accept?: (event: TParser) => boolean;
|
||||
/**
|
||||
* Max time to wait for the response before rejecting (default 15s).
|
||||
*/
|
||||
@@ -52,11 +60,11 @@ export const useNitroQuery = <TParser extends IMessageEvent, TData = TParser>(
|
||||
config: NitroQueryConfig<TParser, TData>
|
||||
): UseQueryResult<TData> =>
|
||||
{
|
||||
const { key, request, parser, select, timeoutMs = 15_000, enabled, staleTime, refetchOnMount } = config;
|
||||
const { key, request, parser, select, accept, timeoutMs = 15_000, enabled, staleTime, refetchOnMount } = config;
|
||||
|
||||
const options: UseQueryOptions<TData, Error, TData> = {
|
||||
queryKey: key,
|
||||
queryFn: () => awaitNitroResponse<TParser, TData>({ key, request, parser, select, timeoutMs }),
|
||||
queryFn: () => awaitNitroResponse<TParser, TData>({ key, request, parser, select, accept, timeoutMs }),
|
||||
enabled,
|
||||
staleTime,
|
||||
refetchOnMount
|
||||
@@ -71,11 +79,11 @@ export const useNitroQuery = <TParser extends IMessageEvent, TData = TParser>(
|
||||
* can use the same plumbing imperatively.
|
||||
*/
|
||||
export const awaitNitroResponse = <TParser extends IMessageEvent, TData>(
|
||||
config: Pick<NitroQueryConfig<TParser, TData>, 'request' | 'parser' | 'select' | 'timeoutMs'>
|
||||
config: Pick<NitroQueryConfig<TParser, TData>, 'request' | 'parser' | 'select' | 'accept' | 'timeoutMs'>
|
||||
): Promise<TData> =>
|
||||
new Promise<TData>((resolve, reject) =>
|
||||
{
|
||||
const { request, parser: ParserCtor, select, timeoutMs = 15_000 } = config;
|
||||
const { request, parser: ParserCtor, select, accept, timeoutMs = 15_000 } = config;
|
||||
|
||||
let settled = false;
|
||||
let timeoutHandle: ReturnType<typeof setTimeout> | null = null;
|
||||
@@ -90,6 +98,7 @@ export const awaitNitroResponse = <TParser extends IMessageEvent, TData>(
|
||||
listener = new (ParserCtor as any)((event: TParser) =>
|
||||
{
|
||||
if(settled) return;
|
||||
if(accept && !accept(event)) return;
|
||||
settled = true;
|
||||
|
||||
cleanup();
|
||||
|
||||
Reference in New Issue
Block a user