@peerbit/document-react 0.1.0

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.
@@ -0,0 +1,433 @@
1
+ import { ClosedError, Documents } from "@peerbit/document";
2
+ import * as indexerTypes from "@peerbit/indexer-interface";
3
+ import { useEffect, useMemo, useRef, useState } from "react";
4
+ import { v4 as uuid } from "uuid";
5
+ /* ────────────────────────── Main Hook ────────────────────────── */
6
+ /**
7
+ * `useQuery` – unified hook that accepts **either**
8
+ * 1. a single `Documents` instance
9
+ * 2. an array of `Documents` instances
10
+ * 3. *or* omits the first argument and provides `dbs` inside the `options` object.
11
+ *
12
+ * It supersedes the original single-DB version as well as the experimental
13
+ * `useMultiQuery` so callers never have to choose between two APIs.
14
+ */
15
+ export const useQuery = (
16
+ /** Single DB or list of DBs. 100 % backward-compatible with the old single param. */
17
+ dbOrDbs, options) => {
18
+ /* ────────────── normalise DBs input ────────────── */
19
+ const dbs = useMemo(() => {
20
+ if (Array.isArray(dbOrDbs))
21
+ return dbOrDbs;
22
+ if (dbOrDbs)
23
+ return [dbOrDbs];
24
+ return [];
25
+ }, [dbOrDbs]);
26
+ /* ────────────── state & refs ────────────── */
27
+ const [all, setAll] = useState([]);
28
+ const allRef = useRef([]);
29
+ const [isLoading, setIsLoading] = useState(false);
30
+ const iteratorRefs = useRef([]);
31
+ const itemIdRef = useRef(new WeakMap());
32
+ const emptyResultsRef = useRef(false);
33
+ const closeControllerRef = useRef(null);
34
+ const waitedOnceRef = useRef(false);
35
+ /* keep an id mostly for debugging – mirrors original behaviour */
36
+ const [id, setId] = useState(options.id);
37
+ const reverseRef = useRef(options.reverse);
38
+ useEffect(() => {
39
+ reverseRef.current = options.reverse;
40
+ }, [options.reverse]);
41
+ /* ────────────── utilities ────────────── */
42
+ const log = (...a) => {
43
+ if (!options.debug)
44
+ return;
45
+ if (typeof options.debug === "boolean")
46
+ console.log(...a);
47
+ else
48
+ console.log(options.debug, ...a);
49
+ };
50
+ const updateAll = (combined) => {
51
+ allRef.current = combined;
52
+ setAll(combined);
53
+ };
54
+ const reset = () => {
55
+ iteratorRefs.current?.forEach(({ iterator }) => iterator.close());
56
+ iteratorRefs.current = [];
57
+ closeControllerRef.current?.abort(new Error("Reset"));
58
+ closeControllerRef.current = new AbortController();
59
+ emptyResultsRef.current = false;
60
+ waitedOnceRef.current = false;
61
+ allRef.current = [];
62
+ itemIdRef.current = new WeakMap();
63
+ setAll([]);
64
+ setIsLoading(false);
65
+ log("Iterators reset");
66
+ };
67
+ /* ────────── rebuild iterators when db list / query etc. change ────────── */
68
+ useEffect(() => {
69
+ /* derive canonical list of open DBs */
70
+ const openDbs = dbs.filter((d) => Boolean(d && !d.closed));
71
+ const { query, resolve } = options;
72
+ if (!openDbs.length || query == null) {
73
+ reset();
74
+ return;
75
+ }
76
+ reset();
77
+ const abortSignal = closeControllerRef.current?.signal;
78
+ const onMissedResults = (evt) => {
79
+ console.error("Not effective yet: missed results", evt);
80
+ /* if (allRef.current.length > 0 || typeof options.remote !== "object" || !options.updates) {
81
+ return;
82
+ }
83
+ console.log("Missed results, loading more", evt.amount);
84
+ loadMore(evt.amount); */
85
+ };
86
+ let draining = false;
87
+ const scheduleDrain = (ref, amount, opts) => {
88
+ log("Schedule drain", draining, ref, amount);
89
+ if (draining)
90
+ return;
91
+ draining = true;
92
+ loadMore(amount, opts)
93
+ .catch((e) => {
94
+ if (!(e instanceof ClosedError))
95
+ throw e;
96
+ })
97
+ .finally(() => {
98
+ draining = false;
99
+ });
100
+ };
101
+ iteratorRefs.current = openDbs.map((db) => {
102
+ let currentRef;
103
+ const iterator = db.index.iterate(query ?? {}, {
104
+ closePolicy: "manual",
105
+ local: options.local ?? true,
106
+ remote: options.remote
107
+ ? {
108
+ ...(typeof options?.remote === "object"
109
+ ? {
110
+ ...options.remote,
111
+ onLateResults: onMissedResults,
112
+ wait: {
113
+ ...options?.remote?.wait,
114
+ timeout: options?.remote?.wait?.timeout ?? 5000,
115
+ },
116
+ }
117
+ : options?.remote
118
+ ? {
119
+ onLateResults: onMissedResults,
120
+ }
121
+ : undefined),
122
+ }
123
+ : undefined,
124
+ resolve,
125
+ signal: abortSignal,
126
+ updates: {
127
+ push: typeof options.updates === "boolean"
128
+ ? options.updates
129
+ : typeof options.updates === "object" && options.updates.push
130
+ ? true
131
+ : false,
132
+ merge: typeof options.updates === "boolean" && options.updates
133
+ ? true
134
+ : typeof options.updates === "object" && options.updates.merge
135
+ ? true
136
+ : false,
137
+ notify: (reason) => {
138
+ log("notify", { reason, currentRef: !!currentRef });
139
+ if (reason === "change" || reason === "push" || reason === "join") {
140
+ const drainAmount = options.batchSize ?? 10;
141
+ scheduleDrain(iterator, drainAmount, {
142
+ force: true,
143
+ });
144
+ }
145
+ },
146
+ onBatch: (batch, props) => {
147
+ log("onBatch", { batch, props, currentRef: !!currentRef });
148
+ if (props.reason === "join" ||
149
+ props.reason === "change" ||
150
+ props.reason === "push") {
151
+ if (!currentRef)
152
+ return;
153
+ handleBatch(iteratorRefs.current, [
154
+ { ref: currentRef, items: batch },
155
+ ]);
156
+ }
157
+ },
158
+ },
159
+ });
160
+ const ref = {
161
+ id: uuid(),
162
+ db,
163
+ iterator,
164
+ itemsConsumed: 0,
165
+ };
166
+ currentRef = ref;
167
+ log("Iterator init", ref.id, "db", db.address);
168
+ return ref;
169
+ });
170
+ /* store a deterministic id (useful for external keys) */
171
+ setId(uuid());
172
+ /* prefetch if requested */
173
+ if (options.prefetch)
174
+ void loadMore();
175
+ // eslint-disable-next-line react-hooks/exhaustive-deps
176
+ }, [
177
+ dbs.map((d) => d?.address).join("|"),
178
+ options.query,
179
+ options.resolve,
180
+ options.reverse,
181
+ options.batchSize,
182
+ ]);
183
+ /* ────────────── loadMore implementation ────────────── */
184
+ const batchSize = options.batchSize ?? 10;
185
+ const shouldWait = () => {
186
+ if (waitedOnceRef.current)
187
+ return false;
188
+ if (options.remote === false)
189
+ return false;
190
+ return true; // mimic original behaviour – wait once if remote allowed
191
+ };
192
+ const markWaited = () => {
193
+ waitedOnceRef.current = true;
194
+ };
195
+ /* helper to turn primitive ids into stable map keys */
196
+ const idToKey = (value) => {
197
+ switch (typeof value) {
198
+ case "string":
199
+ return `s:${value}`;
200
+ case "number":
201
+ return `n:${value}`;
202
+ default:
203
+ return `b:${value.toString()}`;
204
+ }
205
+ };
206
+ const handleBatch = async (iterators, batches) => {
207
+ if (!iterators.length) {
208
+ log("No iterators in handleBatch");
209
+ return false;
210
+ }
211
+ const totalFetched = batches.reduce((sum, batch) => sum + batch.items.length, 0);
212
+ if (totalFetched === 0) {
213
+ log("No items fetched");
214
+ emptyResultsRef.current = iterators.every((i) => i.iterator.done());
215
+ return !emptyResultsRef.current;
216
+ }
217
+ let processed = batches;
218
+ if (options.transform) {
219
+ const transform = options.transform;
220
+ processed = await Promise.all(batches.map(async ({ ref, items }) => ({
221
+ ref,
222
+ items: await Promise.all(items.map(transform)),
223
+ })));
224
+ }
225
+ const prev = allRef.current;
226
+ const next = [...prev];
227
+ const keyIndex = new Map();
228
+ prev.forEach((item, idx) => {
229
+ const key = itemIdRef.current.get(item);
230
+ if (key)
231
+ keyIndex.set(key, idx);
232
+ });
233
+ const seenHeads = new Set(prev.map((x) => x.__context?.head));
234
+ const freshItems = [];
235
+ let hasMutations = false;
236
+ log("Processing batches", { processed, keyIndex });
237
+ for (const { ref, items } of processed) {
238
+ const db = ref.db;
239
+ for (const item of items) {
240
+ const ctx = item.__context;
241
+ const head = ctx?.head;
242
+ let key = null;
243
+ try {
244
+ key = idToKey(db.index.resolveId(item).primitive);
245
+ }
246
+ catch (error) {
247
+ log("useQuery: failed to resolve id", error);
248
+ }
249
+ if (key && keyIndex.has(key)) {
250
+ const existingIndex = keyIndex.get(key);
251
+ const current = next[existingIndex];
252
+ const currentContext = current?.__context;
253
+ const incomingContext = ctx;
254
+ const shouldReplace = !currentContext ||
255
+ !incomingContext ||
256
+ currentContext.modified <= incomingContext.modified;
257
+ if (shouldReplace && current !== item) {
258
+ itemIdRef.current.delete(current);
259
+ next[existingIndex] = item;
260
+ hasMutations = true;
261
+ }
262
+ if (key) {
263
+ itemIdRef.current.set(item, key);
264
+ keyIndex.set(key, existingIndex);
265
+ }
266
+ if (head != null)
267
+ seenHeads.add(head);
268
+ continue;
269
+ }
270
+ if (head != null && seenHeads.has(head))
271
+ continue;
272
+ if (head != null)
273
+ seenHeads.add(head);
274
+ freshItems.push(item);
275
+ if (key) {
276
+ itemIdRef.current.set(item, key);
277
+ keyIndex.set(key, prev.length + freshItems.length - 1);
278
+ }
279
+ }
280
+ }
281
+ if (!freshItems.length && !hasMutations) {
282
+ emptyResultsRef.current = iterators.every((i) => i.iterator.done());
283
+ log("No new items or mutations");
284
+ return !emptyResultsRef.current;
285
+ }
286
+ const combined = reverseRef.current
287
+ ? [...freshItems.reverse(), ...next]
288
+ : [...next, ...freshItems];
289
+ log("Updating all with", {
290
+ prevLength: prev.length,
291
+ freshLength: freshItems.length,
292
+ combinedLength: combined.length,
293
+ });
294
+ updateAll(combined);
295
+ emptyResultsRef.current = iterators.every((i) => i.iterator.done());
296
+ return !emptyResultsRef.current;
297
+ };
298
+ const drainRoundRobin = async (iterators, n) => {
299
+ const batches = [];
300
+ for (const ref of iterators) {
301
+ if (ref.iterator.done())
302
+ continue;
303
+ const batch = await ref.iterator.next(n);
304
+ log("Iterator", ref.id, "fetched", batch.length, "items");
305
+ if (batch.length) {
306
+ ref.itemsConsumed += batch.length;
307
+ batches.push({ ref, items: batch });
308
+ }
309
+ }
310
+ return handleBatch(iterators, batches);
311
+ };
312
+ /* maybe make the rule that if results are empty and we get results from joining
313
+ set the results to the joining results
314
+ when results are not empty use onMerge option to merge the results ? */
315
+ const loadMore = async (n = batchSize, opts) => {
316
+ const iterators = iteratorRefs.current;
317
+ if (!iterators.length) {
318
+ log("No iterators or already empty", {
319
+ length: iterators.length,
320
+ emptyResultsRef: emptyResultsRef.current,
321
+ });
322
+ return false;
323
+ }
324
+ if (emptyResultsRef.current && !opts?.force) {
325
+ log("Skipping loadMore due to empty state");
326
+ return false;
327
+ }
328
+ else if (opts?.force) {
329
+ emptyResultsRef.current = false;
330
+ }
331
+ setIsLoading(true);
332
+ try {
333
+ /* one-time replicator warm-up across all DBs */
334
+ if (shouldWait()) {
335
+ /* if (
336
+ typeof options.remote === "object" &&
337
+ options.remote.wait
338
+ ) {
339
+ await Promise.all(
340
+ iterators.map(async ({ db }) => {
341
+ try {
342
+ await db.log.waitForReplicators({
343
+ timeout: (options.remote as { warmup })
344
+ .warmup,
345
+ signal: closeControllerRef.current?.signal,
346
+ });
347
+ } catch (e) {
348
+ if (
349
+ e instanceof AbortError ||
350
+ e instanceof NoPeersError
351
+ )
352
+ return;
353
+ console.warn("Remote replicators not ready", e);
354
+ }
355
+ })
356
+ );
357
+ }*/
358
+ markWaited();
359
+ }
360
+ return drainRoundRobin(iterators, n);
361
+ }
362
+ catch (e) {
363
+ if (!(e instanceof ClosedError))
364
+ throw e;
365
+ return false;
366
+ }
367
+ finally {
368
+ setIsLoading(false);
369
+ }
370
+ };
371
+ /* ────────────── live-merge listeners ────────────── */
372
+ useEffect(() => {
373
+ if (!options.updates) {
374
+ return;
375
+ }
376
+ /* const listeners = iteratorRefs.current.map(({ db, id: itId }) => {
377
+ const mergeFn =
378
+ typeof options.onChange?.merge === "function"
379
+ ? options.onChange.merge
380
+ : (c: DocumentsChange<T, I>) => c;
381
+
382
+ const handler = async (e: CustomEvent<DocumentsChange<T, I>>) => {
383
+ log("Merge change", e.detail, "it", itId);
384
+ const filtered = await mergeFn(e.detail);
385
+ if (
386
+ !filtered ||
387
+ (!filtered.added.length && !filtered.removed.length)
388
+ )
389
+ return;
390
+
391
+ let merged: Item[];
392
+ if (options.onChange?.update) {
393
+ merged = await options.onChange.update(
394
+ allRef.current,
395
+ filtered
396
+ );
397
+ } else {
398
+ merged = await db.index.updateResults(
399
+ allRef.current as WithContext<RT>[],
400
+ filtered,
401
+ options.query || {},
402
+ options.resolve ?? true
403
+ );
404
+ }
405
+ updateAll(options.reverse ? merged.reverse() : merged);
406
+ };
407
+ db.events.addEventListener("change", handler);
408
+ return { db, handler };
409
+ });
410
+
411
+ return () => {
412
+ listeners.forEach(({ db, handler }) =>
413
+ db.events.removeEventListener("change", handler)
414
+ );
415
+ }; */
416
+ // eslint-disable-next-line react-hooks/exhaustive-deps
417
+ }, [
418
+ iteratorRefs.current.map((r) => r.db.address).join("|"),
419
+ options.updates,
420
+ options.query,
421
+ options.resolve,
422
+ options.reverse,
423
+ ]);
424
+ /* ────────────── public API – unchanged from the caller's perspective ────────────── */
425
+ return {
426
+ items: all,
427
+ loadMore,
428
+ isLoading,
429
+ empty: () => emptyResultsRef.current,
430
+ id,
431
+ };
432
+ };
433
+ //# sourceMappingURL=useQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useQuery.js","sourceRoot":"","sources":["../../src/useQuery.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function debounceLeadingTrailing<T extends (this: any, ...args: any[]) => void>(func: T, delay: number): ((this: ThisParameterType<T>, ...args: Parameters<T>) => void) & {
2
+ cancel: () => void;
3
+ };
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,uBAAuB,CACtC,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,EAE7C,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,MAAM,GACX,CAAC,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,GAAG;IACnE,MAAM,EAAE,MAAM,IAAI,CAAC;CACnB,CA+CA"}
@@ -0,0 +1,41 @@
1
+ export function debounceLeadingTrailing(func, delay) {
2
+ let timeoutId = null;
3
+ let lastArgs = null;
4
+ let lastThis;
5
+ let pendingTrailing = false;
6
+ const debounced = function (...args) {
7
+ if (!timeoutId) {
8
+ // Leading call: no timer means this is the first call in this period.
9
+ func.apply(this, args);
10
+ }
11
+ else {
12
+ // Subsequent calls during the delay mark that a trailing call is needed.
13
+ pendingTrailing = true;
14
+ }
15
+ // Always update with the most recent context and arguments.
16
+ lastArgs = args;
17
+ lastThis = this;
18
+ // Reset the timer.
19
+ if (timeoutId) {
20
+ clearTimeout(timeoutId);
21
+ }
22
+ timeoutId = setTimeout(() => {
23
+ timeoutId = null;
24
+ // If there were any calls during the delay, call the function on the trailing edge.
25
+ if (pendingTrailing && lastArgs) {
26
+ func.apply(lastThis, lastArgs);
27
+ }
28
+ // Reset the trailing flag after the trailing call.
29
+ pendingTrailing = false;
30
+ }, delay);
31
+ };
32
+ debounced.cancel = () => {
33
+ if (timeoutId) {
34
+ clearTimeout(timeoutId);
35
+ timeoutId = null;
36
+ }
37
+ pendingTrailing = false;
38
+ };
39
+ return debounced;
40
+ }
41
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,uBAAuB,CAGtC,IAAO,EACP,KAAa;IAIb,IAAI,SAAS,GAAyC,IAAI,CAAC;IAC3D,IAAI,QAAQ,GAAyB,IAAI,CAAC;IAC1C,IAAI,QAAa,CAAC;IAClB,IAAI,eAAe,GAAG,KAAK,CAAC;IAE5B,MAAM,SAAS,GAAG,UAEjB,GAAG,IAAmB;QAEtB,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,sEAAsE;YACtE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YACP,yEAAyE;YACzE,eAAe,GAAG,IAAI,CAAC;QACxB,CAAC;QACD,4DAA4D;QAC5D,QAAQ,GAAG,IAAI,CAAC;QAChB,QAAQ,GAAG,IAAI,CAAC;QAEhB,mBAAmB;QACnB,IAAI,SAAS,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC;QACD,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAC3B,SAAS,GAAG,IAAI,CAAC;YACjB,oFAAoF;YACpF,IAAI,eAAe,IAAI,QAAQ,EAAE,CAAC;gBACjC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAChC,CAAC;YACD,mDAAmD;YACnD,eAAe,GAAG,KAAK,CAAC;QACzB,CAAC,EAAE,KAAK,CAAC,CAAC;IACX,CAEC,CAAC;IAEF,SAAS,CAAC,MAAM,GAAG,GAAG,EAAE;QACvB,IAAI,SAAS,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,SAAS,GAAG,IAAI,CAAC;QAClB,CAAC;QACD,eAAe,GAAG,KAAK,CAAC;IACzB,CAAC,CAAC;IAEF,OAAO,SAAS,CAAC;AAClB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@peerbit/document-react",
3
+ "version": "0.1.0",
4
+ "description": "React hooks for @peerbit/document",
5
+ "sideEffects": false,
6
+ "type": "module",
7
+ "types": "./dist/src/index.d.ts",
8
+ "typesVersions": {
9
+ "*": {
10
+ "*": [
11
+ "*",
12
+ "dist/*",
13
+ "dist/src/*",
14
+ "dist/src/*/index"
15
+ ],
16
+ "src/*": [
17
+ "*",
18
+ "dist/*",
19
+ "dist/src/*",
20
+ "dist/src/*/index"
21
+ ]
22
+ }
23
+ },
24
+ "files": [
25
+ "src",
26
+ "dist",
27
+ "!vitest",
28
+ "!dist/vitest",
29
+ "!**/*.tsbuildinfo"
30
+ ],
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/src/index.d.ts",
34
+ "import": "./dist/src/index.js"
35
+ }
36
+ },
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "peerDependencies": {
41
+ "react": "^18.0.0 || ^19.0.0"
42
+ },
43
+ "dependencies": {
44
+ "uuid": "^10.0.0",
45
+ "@peerbit/document": "10.1.0",
46
+ "@peerbit/react": "0.0.34",
47
+ "@peerbit/logger": "2.0.0",
48
+ "@peerbit/indexer-interface": "2.1.0"
49
+ },
50
+ "devDependencies": {
51
+ "@dao-xyz/borsh": "^6.0.0",
52
+ "@testing-library/dom": "^10.4.0",
53
+ "@testing-library/react": "^16.1.0",
54
+ "@types/react": "^19.2.4",
55
+ "@types/react-dom": "^19.2.3",
56
+ "@types/libsodium-wrappers": "^0.7.14",
57
+ "libsodium-wrappers": "^0.7.14",
58
+ "react-dom": "^19.0.0",
59
+ "happy-dom": "^20.0.10",
60
+ "vitest": "^4.0.12",
61
+ "@peerbit/blocks-interface": "1.5.0",
62
+ "peerbit": "4.4.0",
63
+ "@peerbit/program": "1.0.0"
64
+ },
65
+ "author": "dao.xyz",
66
+ "license": "MIT",
67
+ "scripts": {
68
+ "clean": "aegir clean",
69
+ "build": "aegir build --no-bundle",
70
+ "test": "vitest run --project node && vitest run --project dom",
71
+ "test:node": "vitest run --project node",
72
+ "test:dom": "vitest run --project dom",
73
+ "lint": "aegir lint"
74
+ }
75
+ }
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from "./utils.js";
2
+ export { useLocal } from "./useLocal.js";
3
+ export { useQuery, type UseQuerySharedOptions } from "./useQuery.js";
4
+ export { useCount } from "./useCount.js";
5
+ export { FastMutex } from "@peerbit/react";
@@ -0,0 +1,57 @@
1
+ import { ClosedError, Documents } from "@peerbit/document";
2
+ import * as indexerTypes from "@peerbit/indexer-interface";
3
+ import { useEffect, useRef, useState } from "react";
4
+ import { debounceLeadingTrailing } from "./utils.js";
5
+
6
+ type QueryOptons = {
7
+ query: indexerTypes.Query[] | indexerTypes.QueryLike;
8
+ id?: string;
9
+ };
10
+ export const useCount = <T extends Record<string, any>>(
11
+ db?: Documents<T, any, any>,
12
+ options?: {
13
+ debounce?: number;
14
+ debug?: boolean; // add debug option here
15
+ } & QueryOptons,
16
+ ) => {
17
+ const [count, setCount] = useState<number>(0);
18
+ const countRef = useRef<number>(0);
19
+
20
+ useEffect(() => {
21
+ if (!db || db.closed) {
22
+ return;
23
+ }
24
+
25
+ const _l = async (args?: any) => {
26
+ try {
27
+ const count = await db.count({
28
+ query: options?.query,
29
+ approximate: true,
30
+ });
31
+ countRef.current = count;
32
+ setCount(count);
33
+ } catch (error) {
34
+ if (error instanceof ClosedError) {
35
+ return;
36
+ }
37
+ throw error;
38
+ }
39
+ };
40
+
41
+ const debounced = debounceLeadingTrailing(_l, options?.debounce ?? 1000);
42
+
43
+ const handleChange = () => {
44
+ debounced();
45
+ };
46
+
47
+ debounced();
48
+ db.events.addEventListener("change", handleChange);
49
+
50
+ return () => {
51
+ db.events.removeEventListener("change", handleChange);
52
+ debounced.cancel();
53
+ };
54
+ }, [db?.closed ? undefined : db?.rootAddress, options?.id ?? options?.query]);
55
+
56
+ return count;
57
+ };