@peerbit/react 0.0.26 → 0.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,22 +1,21 @@
1
1
  import { Documents, DocumentsChange, WithContext } from "@peerbit/document";
2
2
  import * as indexerTypes from "@peerbit/indexer-interface";
3
- import { WithIndexedContext } from "@peerbit/document/dist/src/search";
4
- type QueryLike = {
5
- query?: indexerTypes.Query[] | indexerTypes.QueryLike;
6
- sort?: indexerTypes.Sort[] | indexerTypes.Sort | indexerTypes.SortLike;
7
- };
3
+ import { WithIndexedContext } from "@peerbit/document";
8
4
  type QueryOptions = {
9
5
  query: QueryLike;
10
6
  id?: string;
11
7
  };
12
- type RemoteQueryOptions = {
13
- warmup?: number;
14
- joining?: {
15
- waitFor?: number;
16
- };
17
- eager?: boolean;
8
+ export type QueryLike = {
9
+ /** Mongo-style selector or array of selectors */
10
+ query?: indexerTypes.QueryLike | indexerTypes.Query[];
11
+ /** Sort definition compatible with `@peerbit/indexer-interface` */
12
+ sort?: indexerTypes.SortLike | indexerTypes.Sort | indexerTypes.Sort[];
18
13
  };
19
- export declare const useQuery: <T extends Record<string, any>, I extends Record<string, any>, R extends boolean | undefined = true, RT = R extends false ? WithContext<I> : WithIndexedContext<T, I>>(db?: Documents<T, I>, options?: {
14
+ /**
15
+ * All the non-DB-specific options supported by the original single-DB hook.
16
+ * They stay fully backward-compatible.
17
+ */
18
+ export type UseQuerySharedOptions<T, I, R extends boolean | undefined, RT> = {
20
19
  resolve?: R;
21
20
  transform?: (r: RT) => Promise<RT>;
22
21
  debounce?: number;
@@ -26,15 +25,34 @@ export declare const useQuery: <T extends Record<string, any>, I extends Record<
26
25
  reverse?: boolean;
27
26
  batchSize?: number;
28
27
  prefetch?: boolean;
28
+ ignoreUpdates?: boolean;
29
29
  onChange?: {
30
30
  merge?: boolean | ((c: DocumentsChange<T, I>) => DocumentsChange<T, I> | Promise<DocumentsChange<T, I>> | undefined);
31
31
  update?: (prev: RT[], change: DocumentsChange<T, I>) => RT[] | Promise<RT[]>;
32
32
  };
33
33
  local?: boolean;
34
- remote?: boolean | RemoteQueryOptions;
35
- } & QueryOptions) => {
34
+ remote?: boolean | {
35
+ warmup?: number;
36
+ joining?: {
37
+ waitFor?: number;
38
+ };
39
+ eager?: boolean;
40
+ };
41
+ } & QueryOptions;
42
+ /**
43
+ * `useQuery` – unified hook that accepts **either**
44
+ * 1. a single `Documents` instance
45
+ * 2. an array of `Documents` instances
46
+ * 3. *or* omits the first argument and provides `dbs` inside the `options` object.
47
+ *
48
+ * It supersedes the original single-DB version as well as the experimental
49
+ * `useMultiQuery` so callers never have to choose between two APIs.
50
+ */
51
+ export declare const useQuery: <T extends Record<string, any>, I extends Record<string, any>, R extends boolean | undefined = true, RT = R extends false ? WithContext<I> : WithIndexedContext<T, I>>(
52
+ /** Single DB or list of DBs. 100 % backward-compatible with the old single param. */
53
+ dbOrDbs: Documents<T, I> | Documents<T, I>[] | undefined, options: UseQuerySharedOptions<T, I, R, RT>) => {
36
54
  items: RT[];
37
- loadMore: (n?: number, pollEvenIfWasEmpty?: boolean) => Promise<boolean | undefined>;
55
+ loadMore: (n?: number) => Promise<boolean>;
38
56
  isLoading: boolean;
39
57
  empty: () => boolean;
40
58
  id: string | undefined;
@@ -1,27 +1,46 @@
1
- import { useState, useEffect, useRef } from "react";
1
+ import { useState, useEffect, useRef, useMemo } from "react";
2
2
  import { ClosedError, } from "@peerbit/document";
3
3
  import { AbortError } from "@peerbit/time";
4
4
  import { NoPeersError } from "@peerbit/shared-log";
5
5
  import { v4 as uuid } from "uuid";
6
- /* ────────────── main hook ────────────── */
7
- export const useQuery = (db, options) => {
6
+ /* ────────────────────────── Main Hook ────────────────────────── */
7
+ /**
8
+ * `useQuery` – unified hook that accepts **either**
9
+ * 1. a single `Documents` instance
10
+ * 2. an array of `Documents` instances
11
+ * 3. *or* omits the first argument and provides `dbs` inside the `options` object.
12
+ *
13
+ * It supersedes the original single-DB version as well as the experimental
14
+ * `useMultiQuery` so callers never have to choose between two APIs.
15
+ */
16
+ export const useQuery = (
17
+ /** Single DB or list of DBs. 100 % backward-compatible with the old single param. */
18
+ dbOrDbs, options) => {
19
+ /* ────────────── normalise DBs input ────────────── */
20
+ const dbs = useMemo(() => {
21
+ if (Array.isArray(dbOrDbs))
22
+ return dbOrDbs;
23
+ if (dbOrDbs)
24
+ return [dbOrDbs];
25
+ return [];
26
+ }, [dbOrDbs]);
8
27
  /* ────────────── state & refs ────────────── */
9
28
  const [all, setAll] = useState([]);
10
29
  const allRef = useRef([]);
11
30
  const [isLoading, setIsLoading] = useState(false);
12
- const loadingMoreRef = useRef(false);
13
- const iteratorRef = useRef(null);
31
+ const iteratorRefs = useRef([]);
14
32
  const emptyResultsRef = useRef(false);
15
33
  const closeControllerRef = useRef(null);
16
34
  const waitedOnceRef = useRef(false);
17
- const [id, setId] = useState(undefined);
18
- const reverseRef = useRef(options?.reverse);
35
+ /* keep an id mostly for debugging – mirrors original behaviour */
36
+ const [id, setId] = useState(options.id);
37
+ const reverseRef = useRef(options.reverse);
19
38
  useEffect(() => {
20
- reverseRef.current = options?.reverse;
21
- }, [options?.reverse]);
22
- /* ────────────── util ────────────── */
39
+ reverseRef.current = options.reverse;
40
+ }, [options.reverse]);
41
+ /* ────────────── utilities ────────────── */
23
42
  const log = (...a) => {
24
- if (!options?.debug)
43
+ if (!options.debug)
25
44
  return;
26
45
  if (typeof options.debug === "boolean")
27
46
  console.log(...a);
@@ -32,230 +51,159 @@ export const useQuery = (db, options) => {
32
51
  allRef.current = combined;
33
52
  setAll(combined);
34
53
  };
35
- const reset = (fromRef) => {
36
- const toClose = iteratorRef.current;
37
- if (toClose && fromRef && toClose !== fromRef) {
38
- return;
39
- }
40
- iteratorRef.current = null;
54
+ const reset = () => {
55
+ iteratorRefs.current.forEach(({ iterator }) => iterator.close());
56
+ iteratorRefs.current = [];
41
57
  closeControllerRef.current?.abort();
42
58
  closeControllerRef.current = new AbortController();
43
59
  emptyResultsRef.current = false;
44
- toClose?.iterator.close();
60
+ waitedOnceRef.current = false;
45
61
  allRef.current = [];
46
62
  setAll([]);
47
63
  setIsLoading(false);
48
- loadingMoreRef.current = false;
49
- log("Iterator reset", toClose?.id, fromRef?.id);
50
- setId(undefined);
64
+ log("Iterators reset");
51
65
  };
66
+ /* ────────── rebuild iterators when db list / query etc. change ────────── */
52
67
  useEffect(() => {
53
- waitedOnceRef.current = false;
54
- }, [db, options?.id ?? options?.query, options?.resolve, options?.reverse]);
55
- /* ────────────── effect: (re)create iterator ────────────── */
56
- useEffect(() => {
57
- if (!db || db.closed || options?.query == null) {
58
- reset(null);
68
+ /* derive canonical list of open DBs */
69
+ const openDbs = dbs.filter((d) => Boolean(d && !d.closed));
70
+ const { query, resolve } = options;
71
+ if (!openDbs.length || query == null) {
72
+ reset();
59
73
  return;
60
74
  }
61
- const initIterator = () => {
62
- let id = options?.id ?? uuid();
63
- let remoteQueryOptions = options.remote == null || options.remote === false
64
- ? false
65
- : {
66
- ...(typeof options.remote === "object"
67
- ? options.remote
68
- : {}),
69
- joining: typeof options.remote === "object" &&
70
- options.remote.joining?.waitFor !== undefined
71
- ? {
72
- waitFor: options.remote.joining?.waitFor ??
73
- 5e3,
74
- onMissedResults: ({ amount }) => {
75
- loadMore(amount, true);
76
- },
77
- }
78
- : undefined,
79
- };
80
- const ref = {
81
- id,
82
- iterator: db.index.iterate(options.query ?? {}, {
83
- local: options?.local ?? true,
84
- remote: remoteQueryOptions,
85
- resolve: options?.resolve,
86
- signal: closeControllerRef.current?.signal,
87
- }),
88
- itemsConsumed: 0,
89
- };
90
- iteratorRef.current = ref;
91
- if (options?.prefetch) {
92
- loadMore();
93
- }
94
- setId(id);
95
- log("Iterator initialised", ref.id);
75
+ reset();
76
+ const abortSignal = closeControllerRef.current?.signal;
77
+ iteratorRefs.current = openDbs.map((db) => {
78
+ const iterator = db.index.iterate(query ?? {}, {
79
+ local: options.local ?? true,
80
+ remote: options.remote ?? undefined,
81
+ resolve,
82
+ signal: abortSignal,
83
+ });
84
+ const ref = { id: uuid(), db, iterator, itemsConsumed: 0 };
85
+ log("Iterator init", ref.id, "db", db.address);
96
86
  return ref;
97
- };
98
- reset(iteratorRef.current);
99
- const newIteratorRef = initIterator();
100
- /* live-merge listener (optional) */
101
- let handleChange;
102
- if (options?.onChange && options.onChange.merge !== false) {
103
- const mergeFn = typeof options.onChange.merge === "function"
104
- ? options.onChange.merge
105
- : (c) => c;
106
- handleChange = async (e) => {
107
- log("Merge change", e.detail, "iterator", newIteratorRef.id);
108
- const filtered = await mergeFn(e.detail);
109
- if (!filtered ||
110
- (filtered.added.length === 0 &&
111
- filtered.removed.length === 0))
112
- return;
113
- let merged;
114
- if (options.onChange?.update) {
115
- merged = [
116
- ...(await options.onChange?.update(allRef.current, filtered)),
117
- ];
118
- }
119
- else {
120
- merged = await db.index.updateResults(allRef.current, filtered, options.query || {}, options.resolve ?? true);
121
- log("After update", {
122
- current: allRef.current,
123
- merged,
124
- filtered,
125
- query: options.query,
126
- });
127
- const expectedDiff = filtered.added.length - filtered.removed.length;
128
- if (merged === allRef.current ||
129
- (expectedDiff !== 0 &&
130
- merged.length === allRef.current.length)) {
131
- // no change
132
- log("no change after merge");
133
- return;
134
- }
135
- }
136
- updateAll(options?.reverse ? merged.reverse() : merged);
137
- };
138
- db.events.addEventListener("change", handleChange);
139
- }
140
- return () => {
141
- handleChange &&
142
- db.events.removeEventListener("change", handleChange);
143
- reset(newIteratorRef);
144
- };
145
- }, [
146
- db?.closed ? undefined : db?.address,
147
- options?.id ?? options?.query,
148
- options?.resolve,
149
- options?.reverse,
150
- ]);
151
- /* ────────────── loadMore (once-wait aware) ────────────── */
152
- const batchSize = options?.batchSize ?? 10;
87
+ });
88
+ /* prefetch if requested */
89
+ if (options.prefetch)
90
+ void loadMore();
91
+ /* store a deterministic id (useful for external keys) */
92
+ setId(uuid());
93
+ // eslint-disable-next-line react-hooks/exhaustive-deps
94
+ }, [dbs.map((d) => d?.address).join("|"), options.query, options.resolve, options.reverse]);
95
+ /* ────────────── loadMore implementation ────────────── */
96
+ const batchSize = options.batchSize ?? 10;
153
97
  const shouldWait = () => {
154
- if (waitedOnceRef.current) {
98
+ if (waitedOnceRef.current)
155
99
  return false;
156
- }
157
- if (options?.remote === false)
100
+ if (options.remote === false)
158
101
  return false;
159
- if (options?.remote === true)
160
- return true;
161
- if (options?.remote == null)
162
- return true;
163
- if (typeof options?.remote === "object") {
164
- return true;
165
- }
166
- return true;
102
+ return true; // mimic original behaviour – wait once if remote allowed
167
103
  };
168
104
  const markWaited = () => {
169
105
  waitedOnceRef.current = true;
170
106
  };
171
- const loadMore = async (n = batchSize, pollEvenIfWasEmpty = false) => {
172
- const iterator = iteratorRef.current;
173
- if (!iterator ||
174
- (emptyResultsRef.current && !pollEvenIfWasEmpty) ||
175
- iterator.iterator.done() ||
176
- loadingMoreRef.current) {
107
+ const loadMore = async (n = batchSize) => {
108
+ const iterators = iteratorRefs.current;
109
+ if (!iterators.length || emptyResultsRef.current)
177
110
  return false;
178
- }
179
111
  setIsLoading(true);
180
- loadingMoreRef.current = true;
181
112
  try {
182
- /* ── optional replicate-wait ── */
113
+ /* one-time replicator warm-up across all DBs */
183
114
  if (shouldWait()) {
184
- log("Wait for replicators", iterator.id);
185
- let t0 = Date.now();
186
- const warmup = typeof options?.remote === "object" &&
187
- typeof options?.remote.warmup === "number"
188
- ? options?.remote.warmup
189
- : undefined;
190
- if (warmup) {
191
- await db?.log
192
- .waitForReplicators({
193
- timeout: warmup,
194
- signal: closeControllerRef.current?.signal,
195
- })
196
- .catch((e) => {
197
- if (e instanceof AbortError ||
198
- e instanceof NoPeersError)
199
- return;
200
- console.warn("Remote replicators not ready", e);
201
- })
202
- .finally(() => {
203
- log("Wait for replicators done", iterator.id, "time", Date.now() - t0);
204
- markWaited();
205
- });
115
+ if (typeof options.remote === "object" && options.remote.warmup) {
116
+ await Promise.all(iterators.map(async ({ db }) => {
117
+ try {
118
+ await db.log.waitForReplicators({
119
+ timeout: options.remote.warmup,
120
+ signal: closeControllerRef.current?.signal,
121
+ });
122
+ }
123
+ catch (e) {
124
+ if (e instanceof AbortError || e instanceof NoPeersError)
125
+ return;
126
+ console.warn("Remote replicators not ready", e);
127
+ }
128
+ }));
206
129
  }
130
+ markWaited();
207
131
  }
208
- else {
209
- log("Skip wait for replicators", iterator.id);
210
- }
211
- /* ── fetch next batch ── */
212
- log("Retrieve next batch", iterator.id);
213
- let newItems = await iterator.iterator.next(n);
214
- if (options?.transform) {
215
- log("Transform start", iterator.id);
216
- newItems = await Promise.all(newItems.map(options.transform));
217
- log("Transform end", iterator.id);
218
- }
219
- /* iterator might have been reset while we were async… */
220
- if (iteratorRef.current !== iterator) {
221
- log("Iterator reset while loading more");
222
- return false;
132
+ /* pull items round-robin */
133
+ const newlyFetched = [];
134
+ for (const ref of iterators) {
135
+ if (ref.iterator.done())
136
+ continue;
137
+ const batch = await ref.iterator.next(n); // pull up to <n> at once
138
+ if (batch.length) {
139
+ ref.itemsConsumed += batch.length;
140
+ newlyFetched.push(...batch);
141
+ }
223
142
  }
224
- iterator.itemsConsumed += newItems.length;
225
- emptyResultsRef.current = newItems.length === 0;
226
- if (newItems.length) {
227
- log("Loaded more items for iterator", iterator.id, "current id", iteratorRef.current?.id, "new items", newItems.length, "previous results", allRef.current.length, "batchSize", batchSize, "items consumed", iterator.itemsConsumed);
228
- const prev = allRef.current;
229
- const dedup = new Set(prev.map((x) => x.__context.head));
230
- const unique = newItems.filter((x) => !dedup.has(x.__context.head));
231
- if (!unique.length)
232
- return;
233
- const combined = reverseRef.current
234
- ? [...unique.reverse(), ...prev]
235
- : [...prev, ...unique];
236
- updateAll(combined);
143
+ if (!newlyFetched.length) {
144
+ emptyResultsRef.current = iterators.every((i) => i.iterator.done());
145
+ return !emptyResultsRef.current;
237
146
  }
238
- else {
239
- log("No new items", iterator.id);
147
+ /* optional transform */
148
+ let processed = newlyFetched;
149
+ if (options.transform) {
150
+ processed = await Promise.all(processed.map(options.transform));
240
151
  }
241
- return !iterator.iterator.done();
152
+ /* deduplicate & merge */
153
+ const prev = allRef.current;
154
+ const dedupHeads = new Set(prev.map((x) => x.__context.head));
155
+ const unique = processed.filter((x) => !dedupHeads.has(x.__context.head));
156
+ if (!unique.length)
157
+ return !iterators.every((i) => i.iterator.done());
158
+ const combined = reverseRef.current ? [...unique.reverse(), ...prev] : [...prev, ...unique];
159
+ updateAll(combined);
160
+ emptyResultsRef.current = iterators.every((i) => i.iterator.done());
161
+ return !emptyResultsRef.current;
242
162
  }
243
163
  catch (e) {
244
164
  if (!(e instanceof ClosedError))
245
165
  throw e;
166
+ return false;
246
167
  }
247
168
  finally {
248
169
  setIsLoading(false);
249
- loadingMoreRef.current = false;
250
170
  }
251
171
  };
252
- /* ────────────── public API ────────────── */
172
+ /* ────────────── live-merge listeners ────────────── */
173
+ useEffect(() => {
174
+ if (!options.onChange || options.onChange.merge === false)
175
+ return;
176
+ const listeners = iteratorRefs.current.map(({ db, id: itId }) => {
177
+ const mergeFn = typeof options.onChange?.merge === "function" ? options.onChange.merge : (c) => c;
178
+ const handler = async (e) => {
179
+ log("Merge change", e.detail, "it", itId);
180
+ const filtered = await mergeFn(e.detail);
181
+ if (!filtered || (!filtered.added.length && !filtered.removed.length))
182
+ return;
183
+ let merged;
184
+ if (options.onChange?.update) {
185
+ merged = await options.onChange.update(allRef.current, filtered);
186
+ }
187
+ else {
188
+ merged = await db.index.updateResults(allRef.current, filtered, options.query || {}, options.resolve ?? true);
189
+ }
190
+ updateAll(options.reverse ? merged.reverse() : merged);
191
+ };
192
+ db.events.addEventListener("change", handler);
193
+ return { db, handler };
194
+ });
195
+ return () => {
196
+ listeners.forEach(({ db, handler }) => db.events.removeEventListener("change", handler));
197
+ };
198
+ // eslint-disable-next-line react-hooks/exhaustive-deps
199
+ }, [iteratorRefs.current.map((r) => r.db.address).join("|"), options.onChange]);
200
+ /* ────────────── public API – unchanged from the caller's perspective ────────────── */
253
201
  return {
254
202
  items: all,
255
203
  loadMore,
256
204
  isLoading,
257
205
  empty: () => emptyResultsRef.current,
258
- id: id,
206
+ id,
259
207
  };
260
208
  };
261
209
  //# sourceMappingURL=useQuery.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useQuery.js","sourceRoot":"","sources":["../../src/useQuery.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useQuery.js","sourceRoot":"","sources":["../../src/useQuery.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peerbit/react",
3
- "version": "0.0.26",
3
+ "version": "0.0.27",
4
4
  "homepage": "https://dao-xyz.github.io/peerbit-examples",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -70,5 +70,5 @@
70
70
  "last 1 safari version"
71
71
  ]
72
72
  },
73
- "gitHead": "d2ac39e97a21f0607ca0e77fe20affa0dbaaaa67"
73
+ "gitHead": "727b1345b244358196a3782f7b1a61b26d8db498"
74
74
  }
package/src/useQuery.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useRef, useReducer } from "react";
1
+ import { useState, useEffect, useRef, useMemo } from "react";
2
2
  import {
3
3
  ClosedError,
4
4
  Documents,
@@ -10,82 +10,113 @@ import * as indexerTypes from "@peerbit/indexer-interface";
10
10
  import { AbortError } from "@peerbit/time";
11
11
  import { NoPeersError } from "@peerbit/shared-log";
12
12
  import { v4 as uuid } from "uuid";
13
- import { WithIndexedContext } from "@peerbit/document/dist/src/search";
14
- import { on } from "events";
15
- /* ────────────── helper types ────────────── */
16
- type QueryLike = {
17
- query?: indexerTypes.Query[] | indexerTypes.QueryLike;
18
- sort?: indexerTypes.Sort[] | indexerTypes.Sort | indexerTypes.SortLike;
19
- };
13
+ import { WithIndexedContext } from "@peerbit/document";
14
+
20
15
  type QueryOptions = { query: QueryLike; id?: string };
21
16
 
22
- type RemoteQueryOptions = {
23
- warmup?: number;
24
- joining?: { waitFor?: number };
25
- eager?: boolean;
17
+ /* ────────────── helper types ────────────── */
18
+ export type QueryLike = {
19
+ /** Mongo-style selector or array of selectors */
20
+ query?: indexerTypes.QueryLike | indexerTypes.Query[];
21
+ /** Sort definition compatible with `@peerbit/indexer-interface` */
22
+ sort?: indexerTypes.SortLike | indexerTypes.Sort | indexerTypes.Sort[];
26
23
  };
27
24
 
28
- /* ────────────── main hook ────────────── */
25
+ /**
26
+ * All the non-DB-specific options supported by the original single-DB hook.
27
+ * They stay fully backward-compatible.
28
+ */
29
+ export type UseQuerySharedOptions<T, I, R extends boolean | undefined, RT> = {
30
+ /* original behavioural flags */
31
+ resolve?: R;
32
+ transform?: (r: RT) => Promise<RT>;
33
+ debounce?: number;
34
+ debug?: boolean | { id: string };
35
+ reverse?: boolean;
36
+ batchSize?: number;
37
+ prefetch?: boolean;
38
+ ignoreUpdates?: boolean;
39
+ onChange?: {
40
+ merge?:
41
+ | boolean
42
+ | ((
43
+ c: DocumentsChange<T, I>
44
+ ) =>
45
+ | DocumentsChange<T, I>
46
+ | Promise<DocumentsChange<T, I>>
47
+ | undefined);
48
+ update?: (
49
+ prev: RT[],
50
+ change: DocumentsChange<T, I>
51
+ ) => RT[] | Promise<RT[]>;
52
+ };
53
+ local?: boolean;
54
+ remote?:
55
+ | boolean
56
+ | {
57
+ warmup?: number;
58
+ joining?: { waitFor?: number };
59
+ eager?: boolean;
60
+ };
61
+ } & QueryOptions;
62
+
63
+ /* ────────────────────────── Main Hook ────────────────────────── */
64
+ /**
65
+ * `useQuery` – unified hook that accepts **either**
66
+ * 1. a single `Documents` instance
67
+ * 2. an array of `Documents` instances
68
+ * 3. *or* omits the first argument and provides `dbs` inside the `options` object.
69
+ *
70
+ * It supersedes the original single-DB version as well as the experimental
71
+ * `useMultiQuery` so callers never have to choose between two APIs.
72
+ */
29
73
  export const useQuery = <
30
74
  T extends Record<string, any>,
31
75
  I extends Record<string, any>,
32
76
  R extends boolean | undefined = true,
33
77
  RT = R extends false ? WithContext<I> : WithIndexedContext<T, I>
34
78
  >(
35
- db?: Documents<T, I>,
36
- options?: {
37
- resolve?: R;
38
- transform?: (r: RT) => Promise<RT>;
39
- debounce?: number;
40
- debug?: boolean | { id: string };
41
- reverse?: boolean;
42
- batchSize?: number;
43
- prefetch?: boolean;
44
- onChange?: {
45
- merge?:
46
- | boolean
47
- | ((
48
- c: DocumentsChange<T, I>
49
- ) =>
50
- | DocumentsChange<T, I>
51
- | Promise<DocumentsChange<T, I>>
52
- | undefined);
53
- update?: (
54
- prev: RT[],
55
- change: DocumentsChange<T, I>
56
- ) => RT[] | Promise<RT[]>;
57
- };
58
- local?: boolean;
59
- remote?: boolean | RemoteQueryOptions;
60
- } & QueryOptions
79
+ /** Single DB or list of DBs. 100 % backward-compatible with the old single param. */
80
+ dbOrDbs: Documents<T, I> | Documents<T, I>[] | undefined,
81
+ options: UseQuerySharedOptions<T, I, R, RT>
61
82
  ) => {
62
- /* ── «Item» is the concrete element type flowing through the hook ── */
83
+ /* ─────── internal type alias for convenience ─────── */
63
84
  type Item = RT;
64
85
 
86
+ /* ────────────── normalise DBs input ────────────── */
87
+ const dbs = useMemo<(Documents<T, I> | undefined)[]>(() => {
88
+ if (Array.isArray(dbOrDbs)) return dbOrDbs;
89
+ if (dbOrDbs) return [dbOrDbs];
90
+ return [];
91
+ }, [dbOrDbs]);
92
+
65
93
  /* ────────────── state & refs ────────────── */
66
94
  const [all, setAll] = useState<Item[]>([]);
67
95
  const allRef = useRef<Item[]>([]);
68
96
  const [isLoading, setIsLoading] = useState(false);
69
- const loadingMoreRef = useRef<boolean>(false);
70
- const iteratorRef = useRef<{
71
- id?: string;
72
- iterator: ResultsIterator<Item>;
73
- itemsConsumed: number;
74
- } | null>(null);
97
+ const iteratorRefs = useRef<
98
+ {
99
+ id: string;
100
+ db: Documents<T, I>;
101
+ iterator: ResultsIterator<Item>;
102
+ itemsConsumed: number;
103
+ }[]
104
+ >([]);
75
105
  const emptyResultsRef = useRef(false);
76
106
  const closeControllerRef = useRef<AbortController | null>(null);
77
107
  const waitedOnceRef = useRef(false);
78
108
 
79
- const [id, setId] = useState<string | undefined>(undefined);
109
+ /* keep an id mostly for debugging mirrors original behaviour */
110
+ const [id, setId] = useState<string | undefined>(options.id);
80
111
 
81
- const reverseRef = useRef(options?.reverse);
112
+ const reverseRef = useRef(options.reverse);
82
113
  useEffect(() => {
83
- reverseRef.current = options?.reverse;
84
- }, [options?.reverse]);
114
+ reverseRef.current = options.reverse;
115
+ }, [options.reverse]);
85
116
 
86
- /* ────────────── util ────────────── */
117
+ /* ────────────── utilities ────────────── */
87
118
  const log = (...a: any[]) => {
88
- if (!options?.debug) return;
119
+ if (!options.debug) return;
89
120
  if (typeof options.debug === "boolean") console.log(...a);
90
121
  else console.log(options.debug.id, ...a);
91
122
  };
@@ -95,311 +126,215 @@ export const useQuery = <
95
126
  setAll(combined);
96
127
  };
97
128
 
98
- const reset = (
99
- fromRef: {
100
- id?: string;
101
- iterator: ResultsIterator<Item>;
102
- } | null
103
- ) => {
104
- const toClose = iteratorRef.current;
105
- if (toClose && fromRef && toClose !== fromRef) {
106
- return;
107
- }
108
-
109
- iteratorRef.current = null;
129
+ const reset = () => {
130
+ iteratorRefs.current.forEach(({ iterator }) => iterator.close());
131
+ iteratorRefs.current = [];
110
132
 
111
133
  closeControllerRef.current?.abort();
112
134
  closeControllerRef.current = new AbortController();
113
135
  emptyResultsRef.current = false;
114
-
115
- toClose?.iterator.close();
136
+ waitedOnceRef.current = false;
116
137
 
117
138
  allRef.current = [];
118
139
  setAll([]);
119
-
120
140
  setIsLoading(false);
121
- loadingMoreRef.current = false;
122
- log("Iterator reset", toClose?.id, fromRef?.id);
123
- setId(undefined);
141
+ log("Iterators reset");
124
142
  };
125
143
 
144
+ /* ────────── rebuild iterators when db list / query etc. change ────────── */
126
145
  useEffect(() => {
127
- waitedOnceRef.current = false;
128
- }, [db, options?.id ?? options?.query, options?.resolve, options?.reverse]);
129
-
130
- /* ────────────── effect: (re)create iterator ────────────── */
131
- useEffect(() => {
132
- if (!db || db.closed || options?.query == null) {
133
- reset(null);
146
+ /* derive canonical list of open DBs */
147
+ const openDbs = dbs.filter((d): d is Documents<T, I> =>
148
+ Boolean(d && !d.closed)
149
+ );
150
+ const { query, resolve } = options;
151
+
152
+ if (!openDbs.length || query == null) {
153
+ reset();
134
154
  return;
135
155
  }
136
156
 
137
- const initIterator = () => {
138
- let id = options?.id ?? uuid();
139
- let remoteQueryOptions =
140
- options.remote == null || options.remote === false
141
- ? false
142
- : {
143
- ...(typeof options.remote === "object"
144
- ? options.remote
145
- : {}),
146
- joining:
147
- typeof options.remote === "object" &&
148
- options.remote.joining?.waitFor !== undefined
149
- ? {
150
- waitFor:
151
- options.remote.joining?.waitFor ??
152
- 5e3,
153
- onMissedResults: ({ amount }) => {
154
- loadMore(amount, true);
155
- },
156
- }
157
- : undefined,
158
- };
159
- const ref = {
160
- id,
161
- iterator: db.index.iterate(options.query ?? {}, {
162
- local: options?.local ?? true,
163
- remote: remoteQueryOptions,
164
- resolve: options?.resolve,
165
- signal: closeControllerRef.current?.signal,
166
- }) as ResultsIterator<Item>,
167
- itemsConsumed: 0,
168
- };
169
- iteratorRef.current = ref;
170
- if (options?.prefetch) {
171
- loadMore();
172
- }
173
- setId(id);
174
-
175
- log("Iterator initialised", ref.id);
176
- return ref;
177
- };
178
-
179
- reset(iteratorRef.current);
180
- const newIteratorRef = initIterator();
181
-
182
- /* live-merge listener (optional) */
183
- let handleChange:
184
- | ((e: CustomEvent<DocumentsChange<T, I>>) => void | Promise<void>)
185
- | undefined;
186
-
187
- if (options?.onChange && options.onChange.merge !== false) {
188
- const mergeFn =
189
- typeof options.onChange.merge === "function"
190
- ? options.onChange.merge
191
- : (c: DocumentsChange<T, I>) => c;
192
-
193
- handleChange = async (e: CustomEvent<DocumentsChange<T, I>>) => {
194
- log("Merge change", e.detail, "iterator", newIteratorRef.id);
195
- const filtered = await mergeFn(e.detail);
196
- if (
197
- !filtered ||
198
- (filtered.added.length === 0 &&
199
- filtered.removed.length === 0)
200
- )
201
- return;
202
-
203
- let merged: Item[];
204
- if (options.onChange?.update) {
205
- merged = [
206
- ...(await options.onChange?.update(
207
- allRef.current,
208
- filtered
209
- )),
210
- ];
211
- } else {
212
- merged = await db.index.updateResults(
213
- allRef.current as WithContext<RT>[],
214
- filtered,
215
- options.query || {},
216
- options.resolve ?? true
217
- );
157
+ reset();
158
+ const abortSignal = closeControllerRef.current?.signal;
218
159
 
219
- log("After update", {
220
- current: allRef.current,
221
- merged,
222
- filtered,
223
- query: options.query,
224
- });
225
- const expectedDiff =
226
- filtered.added.length - filtered.removed.length;
227
-
228
- if (
229
- merged === allRef.current ||
230
- (expectedDiff !== 0 &&
231
- merged.length === allRef.current.length)
232
- ) {
233
- // no change
234
- log("no change after merge");
235
- return;
236
- }
237
- }
238
-
239
- updateAll(options?.reverse ? merged.reverse() : merged);
240
- };
160
+ iteratorRefs.current = openDbs.map((db) => {
161
+ const iterator = db.index.iterate(query ?? {}, {
162
+ local: options.local ?? true,
163
+ remote: options.remote ?? undefined,
164
+ resolve,
165
+ signal: abortSignal,
166
+ }) as ResultsIterator<Item>;
241
167
 
242
- db.events.addEventListener("change", handleChange);
243
- }
168
+ const ref = { id: uuid(), db, iterator, itemsConsumed: 0 };
169
+ log("Iterator init", ref.id, "db", db.address);
170
+ return ref;
171
+ });
244
172
 
245
- return () => {
246
- handleChange &&
247
- db.events.removeEventListener("change", handleChange);
248
- reset(newIteratorRef);
249
- };
173
+ /* prefetch if requested */
174
+ if (options.prefetch) void loadMore();
175
+ /* store a deterministic id (useful for external keys) */
176
+ setId(uuid());
177
+ // eslint-disable-next-line react-hooks/exhaustive-deps
250
178
  }, [
251
- db?.closed ? undefined : db?.address,
252
- options?.id ?? options?.query,
253
- options?.resolve,
254
- options?.reverse,
179
+ dbs.map((d) => d?.address).join("|"),
180
+ options.query,
181
+ options.resolve,
182
+ options.reverse,
255
183
  ]);
256
184
 
257
- /* ────────────── loadMore (once-wait aware) ────────────── */
258
- const batchSize = options?.batchSize ?? 10;
185
+ /* ────────────── loadMore implementation ────────────── */
186
+ const batchSize = options.batchSize ?? 10;
259
187
 
260
188
  const shouldWait = (): boolean => {
261
- if (waitedOnceRef.current) {
262
- return false;
263
- }
264
- if (options?.remote === false) return false;
265
- if (options?.remote === true) return true;
266
- if (options?.remote == null) return true;
267
- if (typeof options?.remote === "object") {
268
- return true;
269
- }
270
- return true;
189
+ if (waitedOnceRef.current) return false;
190
+ if (options.remote === false) return false;
191
+ return true; // mimic original behaviour – wait once if remote allowed
271
192
  };
272
193
 
273
194
  const markWaited = () => {
274
195
  waitedOnceRef.current = true;
275
196
  };
276
197
 
277
- const loadMore = async (
278
- n: number = batchSize,
279
- pollEvenIfWasEmpty = false
280
- ) => {
281
- const iterator = iteratorRef.current;
282
- if (
283
- !iterator ||
284
- (emptyResultsRef.current && !pollEvenIfWasEmpty) ||
285
- iterator.iterator.done() ||
286
- loadingMoreRef.current
287
- ) {
288
- return false;
289
- }
198
+ const loadMore = async (n: number = batchSize): Promise<boolean> => {
199
+ const iterators = iteratorRefs.current;
200
+ if (!iterators.length || emptyResultsRef.current) return false;
290
201
 
291
202
  setIsLoading(true);
292
- loadingMoreRef.current = true;
293
-
294
203
  try {
295
- /* ── optional replicate-wait ── */
204
+ /* one-time replicator warm-up across all DBs */
296
205
  if (shouldWait()) {
297
- log("Wait for replicators", iterator.id);
298
- let t0 = Date.now();
299
-
300
- const warmup =
301
- typeof options?.remote === "object" &&
302
- typeof options?.remote.warmup === "number"
303
- ? options?.remote.warmup
304
- : undefined;
305
-
306
- if (warmup) {
307
- await db?.log
308
- .waitForReplicators({
309
- timeout: warmup,
310
- signal: closeControllerRef.current?.signal,
311
- })
312
- .catch((e) => {
313
- if (
314
- e instanceof AbortError ||
315
- e instanceof NoPeersError
316
- )
317
- return;
318
- console.warn("Remote replicators not ready", e);
206
+ if (
207
+ typeof options.remote === "object" &&
208
+ options.remote.warmup
209
+ ) {
210
+ await Promise.all(
211
+ iterators.map(async ({ db }) => {
212
+ try {
213
+ await db.log.waitForReplicators({
214
+ timeout: (options.remote as { warmup })
215
+ .warmup,
216
+ signal: closeControllerRef.current?.signal,
217
+ });
218
+ } catch (e) {
219
+ if (
220
+ e instanceof AbortError ||
221
+ e instanceof NoPeersError
222
+ )
223
+ return;
224
+ console.warn("Remote replicators not ready", e);
225
+ }
319
226
  })
320
- .finally(() => {
321
- log(
322
- "Wait for replicators done",
323
- iterator.id,
324
- "time",
325
- Date.now() - t0
326
- );
327
- markWaited();
328
- });
227
+ );
329
228
  }
330
- } else {
331
- log("Skip wait for replicators", iterator.id);
229
+ markWaited();
332
230
  }
333
231
 
334
- /* ── fetch next batch ── */
335
- log("Retrieve next batch", iterator.id);
336
-
337
- let newItems = await iterator.iterator.next(n);
338
-
339
- if (options?.transform) {
340
- log("Transform start", iterator.id);
341
-
342
- newItems = await Promise.all(newItems.map(options.transform));
343
- log("Transform end", iterator.id);
232
+ /* pull items round-robin */
233
+ const newlyFetched: Item[] = [];
234
+ for (const ref of iterators) {
235
+ if (ref.iterator.done()) continue;
236
+ const batch = await ref.iterator.next(n); // pull up to <n> at once
237
+ if (batch.length) {
238
+ ref.itemsConsumed += batch.length;
239
+ newlyFetched.push(...batch);
240
+ }
344
241
  }
345
242
 
346
- /* iterator might have been reset while we were async… */
347
-
348
- if (iteratorRef.current !== iterator) {
349
- log("Iterator reset while loading more");
350
- return false;
243
+ if (!newlyFetched.length) {
244
+ emptyResultsRef.current = iterators.every((i) =>
245
+ i.iterator.done()
246
+ );
247
+ return !emptyResultsRef.current;
351
248
  }
352
249
 
353
- iterator.itemsConsumed += newItems.length;
354
-
355
- emptyResultsRef.current = newItems.length === 0;
356
-
357
- if (newItems.length) {
358
- log(
359
- "Loaded more items for iterator",
360
- iterator.id,
361
- "current id",
362
- iteratorRef.current?.id,
363
- "new items",
364
- newItems.length,
365
- "previous results",
366
- allRef.current.length,
367
- "batchSize",
368
- batchSize,
369
- "items consumed",
370
- iterator.itemsConsumed
371
- );
372
- const prev = allRef.current;
373
- const dedup = new Set(
374
- prev.map((x) => (x as any).__context.head)
375
- );
376
- const unique = newItems.filter(
377
- (x) => !dedup.has((x as any).__context.head)
378
- );
379
- if (!unique.length) return;
380
-
381
- const combined = reverseRef.current
382
- ? [...unique.reverse(), ...prev]
383
- : [...prev, ...unique];
384
- updateAll(combined);
385
- } else {
386
- log("No new items", iterator.id);
250
+ /* optional transform */
251
+ let processed = newlyFetched;
252
+ if (options.transform) {
253
+ processed = await Promise.all(processed.map(options.transform));
387
254
  }
388
- return !iterator.iterator.done();
255
+
256
+ /* deduplicate & merge */
257
+ const prev = allRef.current;
258
+ const dedupHeads = new Set(
259
+ prev.map((x) => (x as any).__context.head)
260
+ );
261
+ const unique = processed.filter(
262
+ (x) => !dedupHeads.has((x as any).__context.head)
263
+ );
264
+ if (!unique.length)
265
+ return !iterators.every((i) => i.iterator.done());
266
+
267
+ const combined = reverseRef.current
268
+ ? [...unique.reverse(), ...prev]
269
+ : [...prev, ...unique];
270
+ updateAll(combined);
271
+
272
+ emptyResultsRef.current = iterators.every((i) => i.iterator.done());
273
+ return !emptyResultsRef.current;
389
274
  } catch (e) {
390
275
  if (!(e instanceof ClosedError)) throw e;
276
+ return false;
391
277
  } finally {
392
278
  setIsLoading(false);
393
- loadingMoreRef.current = false;
394
279
  }
395
280
  };
396
281
 
397
- /* ────────────── public API ────────────── */
282
+ /* ────────────── live-merge listeners ────────────── */
283
+ useEffect(() => {
284
+ if (!options.onChange || options.onChange.merge === false) return;
285
+
286
+ const listeners = iteratorRefs.current.map(({ db, id: itId }) => {
287
+ const mergeFn =
288
+ typeof options.onChange?.merge === "function"
289
+ ? options.onChange.merge
290
+ : (c: DocumentsChange<T, I>) => c;
291
+
292
+ const handler = async (e: CustomEvent<DocumentsChange<T, I>>) => {
293
+ log("Merge change", e.detail, "it", itId);
294
+ const filtered = await mergeFn(e.detail);
295
+ if (
296
+ !filtered ||
297
+ (!filtered.added.length && !filtered.removed.length)
298
+ )
299
+ return;
300
+
301
+ let merged: Item[];
302
+ if (options.onChange?.update) {
303
+ merged = await options.onChange.update(
304
+ allRef.current,
305
+ filtered
306
+ );
307
+ } else {
308
+ merged = await db.index.updateResults(
309
+ allRef.current as WithContext<RT>[],
310
+ filtered,
311
+ options.query || {},
312
+ options.resolve ?? true
313
+ );
314
+ }
315
+ updateAll(options.reverse ? merged.reverse() : merged);
316
+ };
317
+ db.events.addEventListener("change", handler);
318
+ return { db, handler };
319
+ });
320
+
321
+ return () => {
322
+ listeners.forEach(({ db, handler }) =>
323
+ db.events.removeEventListener("change", handler)
324
+ );
325
+ };
326
+ // eslint-disable-next-line react-hooks/exhaustive-deps
327
+ }, [
328
+ iteratorRefs.current.map((r) => r.db.address).join("|"),
329
+ options.onChange,
330
+ ]);
331
+
332
+ /* ────────────── public API – unchanged from the caller's perspective ────────────── */
398
333
  return {
399
334
  items: all,
400
335
  loadMore,
401
336
  isLoading,
402
337
  empty: () => emptyResultsRef.current,
403
- id: id,
338
+ id,
404
339
  };
405
340
  };