@peerbit/react 0.0.21 → 0.0.23
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.
- package/lib/esm/useCount.d.ts +1 -1
- package/lib/esm/useCount.js +4 -1
- package/lib/esm/useCount.js.map +1 -1
- package/lib/esm/useQuery.d.ts +14 -13
- package/lib/esm/useQuery.js +166 -131
- package/lib/esm/useQuery.js.map +1 -1
- package/package.json +2 -2
- package/src/useCount.tsx +5 -2
- package/src/useQuery.tsx +234 -214
package/lib/esm/useCount.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Documents } from "@peerbit/document";
|
|
|
2
2
|
import * as indexerTypes from "@peerbit/indexer-interface";
|
|
3
3
|
type QueryOptons = {
|
|
4
4
|
query: indexerTypes.Query[] | indexerTypes.QueryLike;
|
|
5
|
-
id
|
|
5
|
+
id?: string;
|
|
6
6
|
};
|
|
7
7
|
export declare const useCount: <T extends Record<string, any>>(db?: Documents<T, any, any>, options?: {
|
|
8
8
|
debounce?: number;
|
package/lib/esm/useCount.js
CHANGED
|
@@ -34,7 +34,10 @@ export const useCount = (db, options) => {
|
|
|
34
34
|
db.events.removeEventListener("change", handleChange);
|
|
35
35
|
debounced.cancel();
|
|
36
36
|
};
|
|
37
|
-
}, [
|
|
37
|
+
}, [
|
|
38
|
+
db?.closed ? undefined : db?.rootAddress,
|
|
39
|
+
options?.id ?? options?.query,
|
|
40
|
+
]);
|
|
38
41
|
return count;
|
|
39
42
|
};
|
|
40
43
|
//# sourceMappingURL=useCount.js.map
|
package/lib/esm/useCount.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCount.js","sourceRoot":"","sources":["../../src/useCount.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0B,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAMlD,MAAM,CAAC,MAAM,QAAQ,GAAG,CACpB,EAA2B,EAC3B,OAGe,EACjB,EAAE;IACA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAS,CAAC,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,MAAM,CAAS,CAAC,CAAC,CAAC;IAEnC,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO;QACX,CAAC;QAED,MAAM,EAAE,GAAG,KAAK,EAAE,IAAU,EAAE,EAAE;YAC5B,IAAI,CAAC;gBACD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC;oBACzB,KAAK,EAAE,OAAO,EAAE,KAAK;oBACrB,WAAW,EAAE,IAAI;iBACpB,CAAC,CAAC;gBACH,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;gBACzB,QAAQ,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;oBAC/B,OAAO;gBACX,CAAC;gBACD,MAAM,KAAK,CAAC;YAChB,CAAC;QACL,CAAC,CAAC;QAEF,MAAM,SAAS,GAAG,uBAAuB,CACrC,EAAE,EACF,OAAO,EAAE,QAAQ,IAAI,IAAI,CAC5B,CAAC;QAEF,MAAM,YAAY,GAAG,GAAG,EAAE;YACtB,SAAS,EAAE,CAAC;QAChB,CAAC,CAAC;QAEF,SAAS,EAAE,CAAC;QACZ,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAEnD,OAAO,GAAG,EAAE;YACR,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YACtD,SAAS,CAAC,MAAM,EAAE,CAAC;QACvB,CAAC,CAAC;IACN,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"useCount.js","sourceRoot":"","sources":["../../src/useCount.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0B,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAMlD,MAAM,CAAC,MAAM,QAAQ,GAAG,CACpB,EAA2B,EAC3B,OAGe,EACjB,EAAE;IACA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAS,CAAC,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,MAAM,CAAS,CAAC,CAAC,CAAC;IAEnC,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO;QACX,CAAC;QAED,MAAM,EAAE,GAAG,KAAK,EAAE,IAAU,EAAE,EAAE;YAC5B,IAAI,CAAC;gBACD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC;oBACzB,KAAK,EAAE,OAAO,EAAE,KAAK;oBACrB,WAAW,EAAE,IAAI;iBACpB,CAAC,CAAC;gBACH,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;gBACzB,QAAQ,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;oBAC/B,OAAO;gBACX,CAAC;gBACD,MAAM,KAAK,CAAC;YAChB,CAAC;QACL,CAAC,CAAC;QAEF,MAAM,SAAS,GAAG,uBAAuB,CACrC,EAAE,EACF,OAAO,EAAE,QAAQ,IAAI,IAAI,CAC5B,CAAC;QAEF,MAAM,YAAY,GAAG,GAAG,EAAE;YACtB,SAAS,EAAE,CAAC;QAChB,CAAC,CAAC;QAEF,SAAS,EAAE,CAAC;QACZ,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAEnD,OAAO,GAAG,EAAE;YACR,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YACtD,SAAS,CAAC,MAAM,EAAE,CAAC;QACvB,CAAC,CAAC;IACN,CAAC,EAAE;QACC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,WAAW;QACxC,OAAO,EAAE,EAAE,IAAI,OAAO,EAAE,KAAK;KAChC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC"}
|
package/lib/esm/useQuery.d.ts
CHANGED
|
@@ -6,32 +6,33 @@ type QueryLike = {
|
|
|
6
6
|
};
|
|
7
7
|
type QueryOptions = {
|
|
8
8
|
query: QueryLike;
|
|
9
|
-
id
|
|
9
|
+
id?: string;
|
|
10
|
+
};
|
|
11
|
+
type WaitForReplicatorsOption = {
|
|
12
|
+
warmup?: number;
|
|
13
|
+
eager?: boolean;
|
|
10
14
|
};
|
|
11
15
|
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> : WithContext<T>>(db?: Documents<T, I>, options?: {
|
|
12
16
|
resolve?: R;
|
|
13
|
-
|
|
14
|
-
timeout?: number;
|
|
15
|
-
};
|
|
16
|
-
transform?: (result: WithContext<RT>) => Promise<WithContext<RT>>;
|
|
17
|
+
transform?: (r: RT) => Promise<RT>;
|
|
17
18
|
debounce?: number;
|
|
18
19
|
debug?: boolean | {
|
|
19
20
|
id: string;
|
|
20
21
|
};
|
|
21
22
|
reverse?: boolean;
|
|
22
23
|
batchSize?: number;
|
|
24
|
+
prefetch?: boolean;
|
|
23
25
|
onChange?: {
|
|
24
|
-
merge?: boolean | ((
|
|
25
|
-
update?: (prev:
|
|
26
|
+
merge?: boolean | ((c: DocumentsChange<T>) => DocumentsChange<T> | Promise<DocumentsChange<T>> | undefined);
|
|
27
|
+
update?: (prev: RT[], change: DocumentsChange<T>) => RT[];
|
|
26
28
|
};
|
|
27
29
|
local?: boolean;
|
|
28
|
-
remote?: boolean |
|
|
29
|
-
eager?: boolean;
|
|
30
|
-
};
|
|
30
|
+
remote?: boolean | WaitForReplicatorsOption;
|
|
31
31
|
} & QueryOptions) => {
|
|
32
|
-
items:
|
|
33
|
-
loadMore: () => Promise<
|
|
32
|
+
items: RT[];
|
|
33
|
+
loadMore: () => Promise<boolean | undefined>;
|
|
34
34
|
isLoading: boolean;
|
|
35
|
-
empty: boolean;
|
|
35
|
+
empty: () => boolean;
|
|
36
|
+
id: string | undefined;
|
|
36
37
|
};
|
|
37
38
|
export {};
|
package/lib/esm/useQuery.js
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
import { useState, useEffect, useRef } from "react";
|
|
1
|
+
import { useState, useEffect, useRef, useReducer } from "react";
|
|
2
2
|
import { ClosedError, } from "@peerbit/document";
|
|
3
3
|
import { AbortError } from "@peerbit/time";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
if (typeof options.debug === "boolean") {
|
|
8
|
-
console.log(...args);
|
|
9
|
-
}
|
|
10
|
-
else if (typeof options.debug.id === "string") {
|
|
11
|
-
console.log(options.debug.id, ...args);
|
|
12
|
-
}
|
|
13
|
-
};
|
|
4
|
+
import { NoPeersError } from "@peerbit/shared-log";
|
|
5
|
+
import { v4 as uuid } from "uuid";
|
|
6
|
+
/* ────────────── main hook ────────────── */
|
|
14
7
|
export const useQuery = (db, options) => {
|
|
8
|
+
/* ────────────── state & refs ────────────── */
|
|
15
9
|
const [all, setAll] = useState([]);
|
|
16
10
|
const allRef = useRef([]);
|
|
17
11
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -19,103 +13,113 @@ export const useQuery = (db, options) => {
|
|
|
19
13
|
const iteratorRef = useRef(null);
|
|
20
14
|
const emptyResultsRef = useRef(false);
|
|
21
15
|
const closeControllerRef = useRef(null);
|
|
22
|
-
const
|
|
23
|
-
|
|
16
|
+
const waitedOnceRef = useRef(false);
|
|
17
|
+
const resetResultsOnReset = useRef(true);
|
|
18
|
+
const [id, setId] = useState(undefined);
|
|
19
|
+
const [resetCounter, invokeReset] = useReducer((n) => n + 1, 0);
|
|
20
|
+
const reverseRef = useRef(options?.reverse);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
reverseRef.current = options?.reverse;
|
|
23
|
+
}, [options?.reverse]);
|
|
24
|
+
/* ────────────── util ────────────── */
|
|
25
|
+
const log = (...a) => {
|
|
26
|
+
if (!options?.debug)
|
|
27
|
+
return;
|
|
28
|
+
if (typeof options.debug === "boolean")
|
|
29
|
+
console.log(...a);
|
|
30
|
+
else
|
|
31
|
+
console.log(options.debug.id, ...a);
|
|
32
|
+
};
|
|
33
|
+
const updateAll = (combined) => {
|
|
24
34
|
allRef.current = combined;
|
|
25
35
|
setAll(combined);
|
|
26
36
|
};
|
|
27
37
|
const reset = (fromRef) => {
|
|
28
|
-
|
|
38
|
+
const toClose = iteratorRef.current;
|
|
39
|
+
if (toClose && fromRef && toClose !== fromRef) {
|
|
29
40
|
return;
|
|
30
41
|
}
|
|
42
|
+
iteratorRef.current = null;
|
|
31
43
|
closeControllerRef.current?.abort();
|
|
32
44
|
closeControllerRef.current = new AbortController();
|
|
33
45
|
emptyResultsRef.current = false;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
iteratorRef.current?.iterator?.close();
|
|
40
|
-
iteratorRef.current = null;
|
|
41
|
-
setAll([]);
|
|
46
|
+
toClose?.iterator.close();
|
|
47
|
+
if (resetResultsOnReset.current) {
|
|
48
|
+
allRef.current = [];
|
|
49
|
+
setAll([]);
|
|
50
|
+
}
|
|
42
51
|
setIsLoading(false);
|
|
43
52
|
loadingMoreRef.current = false;
|
|
44
|
-
|
|
53
|
+
log(options, "Iterator reset", toClose?.id, fromRef?.id);
|
|
54
|
+
setId(undefined);
|
|
45
55
|
};
|
|
46
|
-
// Initialize the iterator only once or when query changes
|
|
47
56
|
useEffect(() => {
|
|
48
|
-
|
|
57
|
+
resetResultsOnReset.current = true;
|
|
58
|
+
waitedOnceRef.current = false;
|
|
59
|
+
}, [db, options?.id ?? options?.query, options?.resolve, options?.reverse]);
|
|
60
|
+
/* ────────────── effect: (re)create iterator ────────────── */
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (!db || db.closed || options?.query == null) {
|
|
49
63
|
reset(null);
|
|
50
64
|
return;
|
|
51
65
|
}
|
|
52
66
|
const initIterator = () => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
loadMore();
|
|
70
|
-
return ref;
|
|
71
|
-
}
|
|
72
|
-
catch (error) {
|
|
73
|
-
console.error("Error initializing iterator", error);
|
|
74
|
-
return null;
|
|
67
|
+
let id = options?.id ?? uuid();
|
|
68
|
+
const ref = {
|
|
69
|
+
id,
|
|
70
|
+
iterator: db.index.iterate(options.query ?? {}, {
|
|
71
|
+
local: options?.local ?? true,
|
|
72
|
+
remote: options.remote == null || options.remote === false
|
|
73
|
+
? false
|
|
74
|
+
: typeof options.remote === "object"
|
|
75
|
+
? options.remote
|
|
76
|
+
: true,
|
|
77
|
+
resolve: options?.resolve,
|
|
78
|
+
}),
|
|
79
|
+
itemsConsumed: 0,
|
|
80
|
+
};
|
|
81
|
+
iteratorRef.current = ref;
|
|
82
|
+
if (options?.prefetch) {
|
|
83
|
+
loadMore();
|
|
75
84
|
}
|
|
85
|
+
setId(id);
|
|
86
|
+
log("Iterator initialised", ref.id);
|
|
87
|
+
return ref;
|
|
76
88
|
};
|
|
77
|
-
// Reset state when the db or query changes.
|
|
78
89
|
reset(iteratorRef.current);
|
|
79
90
|
const newIteratorRef = initIterator();
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
/* live-merge listener (optional) */
|
|
92
|
+
let handleChange;
|
|
93
|
+
if (options?.onChange && options.onChange.merge !== false) {
|
|
94
|
+
const mergeFn = typeof options.onChange.merge === "function"
|
|
83
95
|
? options.onChange.merge
|
|
84
|
-
: (
|
|
96
|
+
: (c) => c;
|
|
85
97
|
handleChange = async (e) => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (!
|
|
89
|
-
(
|
|
90
|
-
|
|
98
|
+
log(options, "Merge change", e.detail, "iterator", newIteratorRef.id);
|
|
99
|
+
const filtered = await mergeFn(e.detail);
|
|
100
|
+
if (!filtered ||
|
|
101
|
+
(filtered.added.length === 0 &&
|
|
102
|
+
filtered.removed.length === 0))
|
|
91
103
|
return;
|
|
92
|
-
|
|
93
|
-
let merged = [];
|
|
104
|
+
let merged;
|
|
94
105
|
if (options.onChange?.update) {
|
|
95
106
|
merged = [
|
|
96
|
-
...options.onChange
|
|
107
|
+
...options.onChange?.update(allRef.current, filtered),
|
|
97
108
|
];
|
|
98
109
|
}
|
|
99
110
|
else {
|
|
100
|
-
merged = await db.index.updateResults(allRef.current,
|
|
101
|
-
|
|
102
|
-
const expectedDiff =
|
|
103
|
-
filteredChange.removed.length;
|
|
111
|
+
merged = await db.index.updateResults(allRef.current, filtered, options.query || {}, options.resolve ?? true);
|
|
112
|
+
log(options, "After update", allRef.current, merged);
|
|
113
|
+
const expectedDiff = filtered.added.length - filtered.removed.length;
|
|
104
114
|
if (merged === allRef.current ||
|
|
105
115
|
(expectedDiff !== 0 &&
|
|
106
116
|
merged.length === allRef.current.length)) {
|
|
107
117
|
// no change
|
|
108
|
-
|
|
118
|
+
log(options, "no change after merge");
|
|
109
119
|
return;
|
|
110
120
|
}
|
|
111
121
|
}
|
|
112
|
-
|
|
113
|
-
added: e.detail.added.length,
|
|
114
|
-
removed: e.detail.removed.length,
|
|
115
|
-
merged: merged.length,
|
|
116
|
-
allRef: allRef.current.length,
|
|
117
|
-
});
|
|
118
|
-
updateAll(options?.reverse ? merged.reverse() : merged, e.detail);
|
|
122
|
+
updateAll(options?.reverse ? merged.reverse() : merged);
|
|
119
123
|
};
|
|
120
124
|
db.events.addEventListener("change", handleChange);
|
|
121
125
|
}
|
|
@@ -126,99 +130,130 @@ export const useQuery = (db, options) => {
|
|
|
126
130
|
};
|
|
127
131
|
}, [
|
|
128
132
|
db?.closed ? undefined : db?.address,
|
|
129
|
-
options?.id
|
|
133
|
+
options?.id ?? options?.query,
|
|
130
134
|
options?.resolve,
|
|
135
|
+
options?.reverse,
|
|
136
|
+
resetCounter,
|
|
131
137
|
]);
|
|
132
|
-
|
|
138
|
+
/* ────────────── loadMore (once-wait aware) ────────────── */
|
|
133
139
|
const batchSize = options?.batchSize ?? 10;
|
|
140
|
+
const shouldWait = () => {
|
|
141
|
+
if (waitedOnceRef.current) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
if (options?.remote === false)
|
|
145
|
+
return false;
|
|
146
|
+
if (options?.remote === true)
|
|
147
|
+
return true;
|
|
148
|
+
if (options?.remote == null)
|
|
149
|
+
return true;
|
|
150
|
+
if (typeof options?.remote === "object") {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
return true;
|
|
154
|
+
};
|
|
155
|
+
const reloadAfterTime = () => {
|
|
156
|
+
if (typeof options?.remote === "object" && options.remote.eager) {
|
|
157
|
+
return options.remote.warmup ?? db?.log.timeUntilRoleMaturity;
|
|
158
|
+
}
|
|
159
|
+
return undefined;
|
|
160
|
+
};
|
|
161
|
+
const markWaited = () => {
|
|
162
|
+
waitedOnceRef.current = true;
|
|
163
|
+
};
|
|
134
164
|
const loadMore = async () => {
|
|
135
|
-
|
|
165
|
+
const iterator = iteratorRef.current;
|
|
166
|
+
if (!iterator ||
|
|
136
167
|
emptyResultsRef.current ||
|
|
137
|
-
|
|
168
|
+
iterator.iterator.done() ||
|
|
138
169
|
loadingMoreRef.current) {
|
|
139
|
-
|
|
140
|
-
isLoading,
|
|
141
|
-
emptyResultsRef: emptyResultsRef.current,
|
|
142
|
-
iteratorRef: !iteratorRef.current,
|
|
143
|
-
});
|
|
144
|
-
return;
|
|
170
|
+
return false;
|
|
145
171
|
}
|
|
146
|
-
const iterator = iteratorRef.current;
|
|
147
172
|
setIsLoading(true);
|
|
148
173
|
loadingMoreRef.current = true;
|
|
149
174
|
try {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
let
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
175
|
+
/* ── optional replicate-wait ── */
|
|
176
|
+
if (shouldWait()) {
|
|
177
|
+
log(options, "Wait for replicators", iterator.id);
|
|
178
|
+
let isEager = typeof options?.remote === "object" && options.remote.eager;
|
|
179
|
+
const waitTimeout = typeof options?.remote === "object" &&
|
|
180
|
+
typeof options?.remote.warmup === "number"
|
|
181
|
+
? options?.remote.warmup
|
|
182
|
+
: 5_000;
|
|
183
|
+
let shouldResetAfterMaturity = isEager && !waitedOnceRef.current;
|
|
184
|
+
let promise = db?.log
|
|
158
185
|
.waitForReplicators({
|
|
159
|
-
timeout,
|
|
186
|
+
timeout: waitTimeout,
|
|
160
187
|
signal: closeControllerRef.current?.signal,
|
|
161
188
|
})
|
|
162
189
|
.catch((e) => {
|
|
163
|
-
if (e instanceof AbortError
|
|
164
|
-
|
|
190
|
+
if (e instanceof AbortError ||
|
|
191
|
+
e instanceof NoPeersError)
|
|
165
192
|
return;
|
|
166
|
-
}
|
|
167
193
|
console.warn("Remote replicators not ready", e);
|
|
194
|
+
})
|
|
195
|
+
.finally(() => {
|
|
196
|
+
markWaited();
|
|
197
|
+
if (shouldResetAfterMaturity) {
|
|
198
|
+
resetResultsOnReset.current = false; // don't reset results, because we expect to get same or more results
|
|
199
|
+
invokeReset();
|
|
200
|
+
}
|
|
168
201
|
});
|
|
202
|
+
if (!shouldResetAfterMaturity) {
|
|
203
|
+
await promise;
|
|
204
|
+
}
|
|
169
205
|
}
|
|
170
|
-
|
|
171
|
-
|
|
206
|
+
else {
|
|
207
|
+
log(options, "Skip wait for replicators", iterator.id);
|
|
208
|
+
}
|
|
209
|
+
/* ── fetch next batch ── */
|
|
210
|
+
log(options, "Retrieve next batch", iterator.id);
|
|
172
211
|
let newItems = await iterator.iterator.next(batchSize);
|
|
173
212
|
if (options?.transform) {
|
|
174
|
-
|
|
213
|
+
log(options, "Transform start", iterator.id);
|
|
214
|
+
newItems = await Promise.all(newItems.map(options.transform));
|
|
215
|
+
log(options, "Transform end", iterator.id);
|
|
175
216
|
}
|
|
217
|
+
/* iterator might have been reset while we were async… */
|
|
176
218
|
if (iteratorRef.current !== iterator) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
logWithId(options, "Iterator ref changed, not updating state", {
|
|
180
|
-
refBefore: iterator.id,
|
|
181
|
-
currentRef: iteratorRef.current?.id,
|
|
182
|
-
ignoredItems: newItems.length,
|
|
183
|
-
});
|
|
184
|
-
return;
|
|
219
|
+
log(options, "Iterator reset while loading more");
|
|
220
|
+
return false;
|
|
185
221
|
}
|
|
186
|
-
|
|
187
|
-
iteratorRef.current?.id, "new items length", newItems.length, "all items length", allRef.current.length);
|
|
222
|
+
iterator.itemsConsumed += newItems.length;
|
|
188
223
|
emptyResultsRef.current = newItems.length === 0;
|
|
189
|
-
if (newItems.length
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
224
|
+
if (newItems.length) {
|
|
225
|
+
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);
|
|
226
|
+
const prev = allRef.current;
|
|
227
|
+
const dedup = new Set(prev.map((x) => x.__context.head));
|
|
228
|
+
const unique = newItems.filter((x) => !dedup.has(x.__context.head));
|
|
229
|
+
if (!unique.length)
|
|
195
230
|
return;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
updateAll(combined, null);
|
|
231
|
+
const combined = reverseRef.current
|
|
232
|
+
? [...unique.reverse(), ...prev]
|
|
233
|
+
: [...prev, ...unique];
|
|
234
|
+
updateAll(combined);
|
|
201
235
|
}
|
|
202
236
|
else {
|
|
203
|
-
|
|
204
|
-
iteratorRef.current?.id +
|
|
205
|
-
" existing results length", allRef.current.length);
|
|
237
|
+
log(options, "No new items", iterator.id);
|
|
206
238
|
}
|
|
239
|
+
return !iterator.iterator.done();
|
|
207
240
|
}
|
|
208
|
-
catch (
|
|
209
|
-
if (
|
|
210
|
-
|
|
211
|
-
logWithId(options, "Database closed error");
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
throw error;
|
|
215
|
-
}
|
|
241
|
+
catch (e) {
|
|
242
|
+
if (!(e instanceof ClosedError))
|
|
243
|
+
throw e;
|
|
216
244
|
}
|
|
217
245
|
finally {
|
|
218
246
|
setIsLoading(false);
|
|
219
247
|
loadingMoreRef.current = false;
|
|
220
248
|
}
|
|
221
249
|
};
|
|
222
|
-
|
|
250
|
+
/* ────────────── public API ────────────── */
|
|
251
|
+
return {
|
|
252
|
+
items: all,
|
|
253
|
+
loadMore,
|
|
254
|
+
isLoading,
|
|
255
|
+
empty: () => emptyResultsRef.current,
|
|
256
|
+
id: id,
|
|
257
|
+
};
|
|
223
258
|
};
|
|
224
259
|
//# sourceMappingURL=useQuery.js.map
|
package/lib/esm/useQuery.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useQuery.js","sourceRoot":"","sources":["../../src/useQuery.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;
|
|
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.
|
|
3
|
+
"version": "0.0.23",
|
|
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": "
|
|
73
|
+
"gitHead": "22ca16d2f5cf13dbc538602dd6e9d0a00382b768"
|
|
74
74
|
}
|
package/src/useCount.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { debounceLeadingTrailing } from "./utils";
|
|
|
5
5
|
|
|
6
6
|
type QueryOptons = {
|
|
7
7
|
query: indexerTypes.Query[] | indexerTypes.QueryLike;
|
|
8
|
-
id
|
|
8
|
+
id?: string;
|
|
9
9
|
};
|
|
10
10
|
export const useCount = <T extends Record<string, any>>(
|
|
11
11
|
db?: Documents<T, any, any>,
|
|
@@ -54,7 +54,10 @@ export const useCount = <T extends Record<string, any>>(
|
|
|
54
54
|
db.events.removeEventListener("change", handleChange);
|
|
55
55
|
debounced.cancel();
|
|
56
56
|
};
|
|
57
|
-
}, [
|
|
57
|
+
}, [
|
|
58
|
+
db?.closed ? undefined : db?.rootAddress,
|
|
59
|
+
options?.id ?? options?.query,
|
|
60
|
+
]);
|
|
58
61
|
|
|
59
62
|
return count;
|
|
60
63
|
};
|
package/src/useQuery.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect, useRef } from "react";
|
|
1
|
+
import { useState, useEffect, useRef, useReducer } from "react";
|
|
2
2
|
import {
|
|
3
3
|
ClosedError,
|
|
4
4
|
Documents,
|
|
@@ -8,26 +8,18 @@ import {
|
|
|
8
8
|
} from "@peerbit/document";
|
|
9
9
|
import * as indexerTypes from "@peerbit/indexer-interface";
|
|
10
10
|
import { AbortError } from "@peerbit/time";
|
|
11
|
-
|
|
11
|
+
import { NoPeersError } from "@peerbit/shared-log";
|
|
12
|
+
import { v4 as uuid } from "uuid";
|
|
13
|
+
/* ────────────── helper types ────────────── */
|
|
12
14
|
type QueryLike = {
|
|
13
15
|
query?: indexerTypes.Query[] | indexerTypes.QueryLike;
|
|
14
16
|
sort?: indexerTypes.Sort[] | indexerTypes.Sort | indexerTypes.SortLike;
|
|
15
17
|
};
|
|
16
|
-
type QueryOptions = { query: QueryLike; id
|
|
18
|
+
type QueryOptions = { query: QueryLike; id?: string };
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
options: { debug?: boolean | { id: string } } | undefined,
|
|
20
|
-
...args: any[]
|
|
21
|
-
) => {
|
|
22
|
-
if (!options?.debug) return;
|
|
23
|
-
|
|
24
|
-
if (typeof options.debug === "boolean") {
|
|
25
|
-
console.log(...args);
|
|
26
|
-
} else if (typeof options.debug.id === "string") {
|
|
27
|
-
console.log(options.debug.id, ...args);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
20
|
+
type WaitForReplicatorsOption = { warmup?: number; eager?: boolean };
|
|
30
21
|
|
|
22
|
+
/* ────────────── main hook ────────────── */
|
|
31
23
|
export const useQuery = <
|
|
32
24
|
T extends Record<string, any>,
|
|
33
25
|
I extends Record<string, any>,
|
|
@@ -37,167 +29,179 @@ export const useQuery = <
|
|
|
37
29
|
db?: Documents<T, I>,
|
|
38
30
|
options?: {
|
|
39
31
|
resolve?: R;
|
|
40
|
-
|
|
41
|
-
transform?: (result: WithContext<RT>) => Promise<WithContext<RT>>;
|
|
32
|
+
transform?: (r: RT) => Promise<RT>;
|
|
42
33
|
debounce?: number;
|
|
43
34
|
debug?: boolean | { id: string };
|
|
44
35
|
reverse?: boolean;
|
|
45
|
-
batchSize?: number;
|
|
36
|
+
batchSize?: number;
|
|
37
|
+
prefetch?: boolean;
|
|
46
38
|
onChange?: {
|
|
47
39
|
merge?:
|
|
48
40
|
| boolean
|
|
49
41
|
| ((
|
|
50
|
-
|
|
42
|
+
c: DocumentsChange<T>
|
|
51
43
|
) =>
|
|
52
44
|
| DocumentsChange<T>
|
|
53
45
|
| Promise<DocumentsChange<T>>
|
|
54
|
-
| undefined);
|
|
55
|
-
update?: (
|
|
56
|
-
prev: WithContext<RT>[],
|
|
57
|
-
change: DocumentsChange<T>
|
|
58
|
-
) => WithContext<RT>[];
|
|
46
|
+
| undefined);
|
|
47
|
+
update?: (prev: RT[], change: DocumentsChange<T>) => RT[];
|
|
59
48
|
};
|
|
60
|
-
local?: boolean;
|
|
61
|
-
remote?:
|
|
62
|
-
| boolean
|
|
63
|
-
| {
|
|
64
|
-
eager?: boolean;
|
|
65
|
-
};
|
|
49
|
+
local?: boolean;
|
|
50
|
+
remote?: boolean | WaitForReplicatorsOption;
|
|
66
51
|
} & QueryOptions
|
|
67
52
|
) => {
|
|
68
|
-
|
|
69
|
-
|
|
53
|
+
/* ── «Item» is the concrete element type flowing through the hook ── */
|
|
54
|
+
type Item = RT;
|
|
55
|
+
|
|
56
|
+
/* ────────────── state & refs ────────────── */
|
|
57
|
+
const [all, setAll] = useState<Item[]>([]);
|
|
58
|
+
const allRef = useRef<Item[]>([]);
|
|
70
59
|
const [isLoading, setIsLoading] = useState(false);
|
|
71
|
-
const loadingMoreRef = useRef(false);
|
|
60
|
+
const loadingMoreRef = useRef<boolean>(false);
|
|
72
61
|
const iteratorRef = useRef<{
|
|
73
62
|
id?: string;
|
|
74
|
-
iterator: ResultsIterator<
|
|
63
|
+
iterator: ResultsIterator<Item>;
|
|
64
|
+
itemsConsumed: number;
|
|
75
65
|
} | null>(null);
|
|
76
66
|
const emptyResultsRef = useRef(false);
|
|
77
67
|
const closeControllerRef = useRef<AbortController | null>(null);
|
|
68
|
+
const waitedOnceRef = useRef(false);
|
|
69
|
+
const resetResultsOnReset = useRef(true);
|
|
78
70
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
fromChange?: DocumentsChange<any> | null
|
|
82
|
-
) => {
|
|
83
|
-
logWithId(
|
|
84
|
-
options,
|
|
85
|
-
"Loading more items, new combined length",
|
|
86
|
-
combined.length,
|
|
87
|
-
"from change",
|
|
88
|
-
fromChange
|
|
89
|
-
);
|
|
71
|
+
const [id, setId] = useState<string | undefined>(undefined);
|
|
72
|
+
const [resetCounter, invokeReset] = useReducer((n) => n + 1, 0);
|
|
90
73
|
|
|
91
|
-
|
|
74
|
+
const reverseRef = useRef(options?.reverse);
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
reverseRef.current = options?.reverse;
|
|
77
|
+
}, [options?.reverse]);
|
|
78
|
+
|
|
79
|
+
/* ────────────── util ────────────── */
|
|
80
|
+
const log = (...a: any[]) => {
|
|
81
|
+
if (!options?.debug) return;
|
|
82
|
+
if (typeof options.debug === "boolean") console.log(...a);
|
|
83
|
+
else console.log(options.debug.id, ...a);
|
|
84
|
+
};
|
|
92
85
|
|
|
86
|
+
const updateAll = (combined: Item[]) => {
|
|
87
|
+
allRef.current = combined;
|
|
93
88
|
setAll(combined);
|
|
94
89
|
};
|
|
95
90
|
|
|
96
91
|
const reset = (
|
|
97
92
|
fromRef: {
|
|
98
93
|
id?: string;
|
|
99
|
-
iterator: ResultsIterator<
|
|
94
|
+
iterator: ResultsIterator<Item>;
|
|
100
95
|
} | null
|
|
101
96
|
) => {
|
|
102
|
-
|
|
97
|
+
const toClose = iteratorRef.current;
|
|
98
|
+
if (toClose && fromRef && toClose !== fromRef) {
|
|
103
99
|
return;
|
|
104
100
|
}
|
|
101
|
+
|
|
102
|
+
iteratorRef.current = null;
|
|
103
|
+
|
|
105
104
|
closeControllerRef.current?.abort();
|
|
106
105
|
closeControllerRef.current = new AbortController();
|
|
107
|
-
|
|
108
106
|
emptyResultsRef.current = false;
|
|
109
|
-
logWithId(options, "reset", {
|
|
110
|
-
id: iteratorRef.current?.id,
|
|
111
|
-
size: allRef.current.length,
|
|
112
|
-
});
|
|
113
107
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
108
|
+
toClose?.iterator.close();
|
|
109
|
+
|
|
110
|
+
if (resetResultsOnReset.current) {
|
|
111
|
+
allRef.current = [];
|
|
112
|
+
setAll([]);
|
|
113
|
+
}
|
|
114
|
+
|
|
118
115
|
setIsLoading(false);
|
|
119
116
|
loadingMoreRef.current = false;
|
|
120
|
-
|
|
117
|
+
log(options, "Iterator reset", toClose?.id, fromRef?.id);
|
|
118
|
+
setId(undefined);
|
|
121
119
|
};
|
|
122
120
|
|
|
123
|
-
// Initialize the iterator only once or when query changes
|
|
124
121
|
useEffect(() => {
|
|
125
|
-
|
|
122
|
+
resetResultsOnReset.current = true;
|
|
123
|
+
waitedOnceRef.current = false;
|
|
124
|
+
}, [db, options?.id ?? options?.query, options?.resolve, options?.reverse]);
|
|
125
|
+
|
|
126
|
+
/* ────────────── effect: (re)create iterator ────────────── */
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
if (!db || db.closed || options?.query == null) {
|
|
126
129
|
reset(null);
|
|
127
130
|
return;
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
const initIterator = () => {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
loadMore(); // initial load
|
|
151
|
-
return ref;
|
|
152
|
-
} catch (error) {
|
|
153
|
-
console.error("Error initializing iterator", error);
|
|
154
|
-
return null;
|
|
134
|
+
let id = options?.id ?? uuid();
|
|
135
|
+
const ref = {
|
|
136
|
+
id,
|
|
137
|
+
iterator: db.index.iterate(options.query ?? {}, {
|
|
138
|
+
local: options?.local ?? true,
|
|
139
|
+
remote:
|
|
140
|
+
options.remote == null || options.remote === false
|
|
141
|
+
? false
|
|
142
|
+
: typeof options.remote === "object"
|
|
143
|
+
? options.remote
|
|
144
|
+
: true,
|
|
145
|
+
resolve: options?.resolve,
|
|
146
|
+
}) as ResultsIterator<Item>,
|
|
147
|
+
itemsConsumed: 0,
|
|
148
|
+
};
|
|
149
|
+
iteratorRef.current = ref;
|
|
150
|
+
if (options?.prefetch) {
|
|
151
|
+
loadMore();
|
|
155
152
|
}
|
|
153
|
+
setId(id);
|
|
154
|
+
|
|
155
|
+
log("Iterator initialised", ref.id);
|
|
156
|
+
return ref;
|
|
156
157
|
};
|
|
157
158
|
|
|
158
|
-
// Reset state when the db or query changes.
|
|
159
159
|
reset(iteratorRef.current);
|
|
160
|
-
|
|
161
160
|
const newIteratorRef = initIterator();
|
|
162
161
|
|
|
162
|
+
/* live-merge listener (optional) */
|
|
163
163
|
let handleChange:
|
|
164
|
-
|
|
|
165
|
-
|
|
|
166
|
-
|
|
167
|
-
if (options?.onChange && options
|
|
168
|
-
|
|
164
|
+
| ((e: CustomEvent<DocumentsChange<T>>) => void | Promise<void>)
|
|
165
|
+
| undefined;
|
|
166
|
+
|
|
167
|
+
if (options?.onChange && options.onChange.merge !== false) {
|
|
168
|
+
const mergeFn =
|
|
169
169
|
typeof options.onChange.merge === "function"
|
|
170
170
|
? options.onChange.merge
|
|
171
|
-
: (
|
|
171
|
+
: (c: DocumentsChange<T>) => c;
|
|
172
|
+
|
|
172
173
|
handleChange = async (e: CustomEvent<DocumentsChange<T>>) => {
|
|
173
|
-
|
|
174
|
-
|
|
174
|
+
log(
|
|
175
|
+
options,
|
|
176
|
+
"Merge change",
|
|
177
|
+
e.detail,
|
|
178
|
+
"iterator",
|
|
179
|
+
newIteratorRef.id
|
|
180
|
+
);
|
|
181
|
+
const filtered = await mergeFn(e.detail);
|
|
175
182
|
if (
|
|
176
|
-
!
|
|
177
|
-
(
|
|
178
|
-
|
|
179
|
-
)
|
|
183
|
+
!filtered ||
|
|
184
|
+
(filtered.added.length === 0 &&
|
|
185
|
+
filtered.removed.length === 0)
|
|
186
|
+
)
|
|
180
187
|
return;
|
|
181
|
-
|
|
182
|
-
let merged:
|
|
188
|
+
|
|
189
|
+
let merged: Item[];
|
|
183
190
|
if (options.onChange?.update) {
|
|
184
191
|
merged = [
|
|
185
|
-
...options.onChange
|
|
186
|
-
allRef.current,
|
|
187
|
-
filteredChange
|
|
188
|
-
),
|
|
192
|
+
...options.onChange?.update(allRef.current, filtered),
|
|
189
193
|
];
|
|
190
194
|
} else {
|
|
191
195
|
merged = await db.index.updateResults(
|
|
192
|
-
allRef.current,
|
|
193
|
-
|
|
194
|
-
options
|
|
195
|
-
options
|
|
196
|
+
allRef.current as WithContext<RT>[],
|
|
197
|
+
filtered,
|
|
198
|
+
options.query || {},
|
|
199
|
+
options.resolve ?? true
|
|
196
200
|
);
|
|
197
|
-
|
|
201
|
+
|
|
202
|
+
log(options, "After update", allRef.current, merged);
|
|
198
203
|
const expectedDiff =
|
|
199
|
-
|
|
200
|
-
filteredChange.removed.length;
|
|
204
|
+
filtered.added.length - filtered.removed.length;
|
|
201
205
|
|
|
202
206
|
if (
|
|
203
207
|
merged === allRef.current ||
|
|
@@ -205,23 +209,14 @@ export const useQuery = <
|
|
|
205
209
|
merged.length === allRef.current.length)
|
|
206
210
|
) {
|
|
207
211
|
// no change
|
|
208
|
-
|
|
212
|
+
log(options, "no change after merge");
|
|
209
213
|
return;
|
|
210
214
|
}
|
|
211
215
|
}
|
|
212
216
|
|
|
213
|
-
|
|
214
|
-
added: e.detail.added.length,
|
|
215
|
-
removed: e.detail.removed.length,
|
|
216
|
-
merged: merged.length,
|
|
217
|
-
allRef: allRef.current.length,
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
updateAll(
|
|
221
|
-
options?.reverse ? merged.reverse() : merged,
|
|
222
|
-
e.detail
|
|
223
|
-
);
|
|
217
|
+
updateAll(options?.reverse ? merged.reverse() : merged);
|
|
224
218
|
};
|
|
219
|
+
|
|
225
220
|
db.events.addEventListener("change", handleChange);
|
|
226
221
|
}
|
|
227
222
|
|
|
@@ -232,137 +227,162 @@ export const useQuery = <
|
|
|
232
227
|
};
|
|
233
228
|
}, [
|
|
234
229
|
db?.closed ? undefined : db?.address,
|
|
235
|
-
options?.id
|
|
230
|
+
options?.id ?? options?.query,
|
|
236
231
|
options?.resolve,
|
|
232
|
+
options?.reverse,
|
|
233
|
+
resetCounter,
|
|
237
234
|
]);
|
|
238
235
|
|
|
239
|
-
|
|
236
|
+
/* ────────────── loadMore (once-wait aware) ────────────── */
|
|
240
237
|
const batchSize = options?.batchSize ?? 10;
|
|
238
|
+
|
|
239
|
+
const shouldWait = (): boolean => {
|
|
240
|
+
if (waitedOnceRef.current) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
if (options?.remote === false) return false;
|
|
244
|
+
if (options?.remote === true) return true;
|
|
245
|
+
if (options?.remote == null) return true;
|
|
246
|
+
if (typeof options?.remote === "object") {
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
return true;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const reloadAfterTime = (): number | undefined => {
|
|
253
|
+
if (typeof options?.remote === "object" && options.remote.eager) {
|
|
254
|
+
return options.remote.warmup ?? db?.log.timeUntilRoleMaturity;
|
|
255
|
+
}
|
|
256
|
+
return undefined;
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const markWaited = () => {
|
|
260
|
+
waitedOnceRef.current = true;
|
|
261
|
+
};
|
|
262
|
+
|
|
241
263
|
const loadMore = async () => {
|
|
264
|
+
const iterator = iteratorRef.current;
|
|
242
265
|
if (
|
|
243
|
-
!
|
|
266
|
+
!iterator ||
|
|
244
267
|
emptyResultsRef.current ||
|
|
245
|
-
|
|
268
|
+
iterator.iterator.done() ||
|
|
246
269
|
loadingMoreRef.current
|
|
247
270
|
) {
|
|
248
|
-
|
|
249
|
-
isLoading,
|
|
250
|
-
emptyResultsRef: emptyResultsRef.current,
|
|
251
|
-
iteratorRef: !iteratorRef.current,
|
|
252
|
-
});
|
|
253
|
-
return;
|
|
271
|
+
return false;
|
|
254
272
|
}
|
|
255
|
-
const iterator = iteratorRef.current;
|
|
256
273
|
|
|
257
274
|
setIsLoading(true);
|
|
258
275
|
loadingMoreRef.current = true;
|
|
276
|
+
|
|
259
277
|
try {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
options,
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
278
|
+
/* ── optional replicate-wait ── */
|
|
279
|
+
if (shouldWait()) {
|
|
280
|
+
log(options, "Wait for replicators", iterator.id);
|
|
281
|
+
|
|
282
|
+
let isEager =
|
|
283
|
+
typeof options?.remote === "object" && options.remote.eager;
|
|
284
|
+
const waitTimeout =
|
|
285
|
+
typeof options?.remote === "object" &&
|
|
286
|
+
typeof options?.remote.warmup === "number"
|
|
287
|
+
? options?.remote.warmup
|
|
288
|
+
: 5_000;
|
|
289
|
+
|
|
290
|
+
let shouldResetAfterMaturity =
|
|
291
|
+
isEager && !waitedOnceRef.current;
|
|
292
|
+
let promise = db?.log
|
|
271
293
|
.waitForReplicators({
|
|
272
|
-
timeout,
|
|
294
|
+
timeout: waitTimeout,
|
|
273
295
|
signal: closeControllerRef.current?.signal,
|
|
274
296
|
})
|
|
275
297
|
.catch((e) => {
|
|
276
|
-
if (
|
|
277
|
-
|
|
298
|
+
if (
|
|
299
|
+
e instanceof AbortError ||
|
|
300
|
+
e instanceof NoPeersError
|
|
301
|
+
)
|
|
278
302
|
return;
|
|
279
|
-
}
|
|
280
303
|
console.warn("Remote replicators not ready", e);
|
|
304
|
+
})
|
|
305
|
+
.finally(() => {
|
|
306
|
+
markWaited();
|
|
307
|
+
if (shouldResetAfterMaturity) {
|
|
308
|
+
resetResultsOnReset.current = false; // don't reset results, because we expect to get same or more results
|
|
309
|
+
invokeReset();
|
|
310
|
+
}
|
|
281
311
|
});
|
|
312
|
+
if (!shouldResetAfterMaturity) {
|
|
313
|
+
await promise;
|
|
314
|
+
}
|
|
315
|
+
} else {
|
|
316
|
+
log(options, "Skip wait for replicators", iterator.id);
|
|
282
317
|
}
|
|
283
318
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
iteratorRef.current?.id,
|
|
288
|
-
"should resolve?: " + options?.resolve,
|
|
289
|
-
"query local?: " + options?.local,
|
|
290
|
-
"query remote?: " + options?.remote,
|
|
291
|
-
"isReplicating: " + (await db?.log.isReplicating())
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
let newItems: WithContext<RT>[] = await iterator.iterator.next(
|
|
295
|
-
batchSize
|
|
296
|
-
);
|
|
297
|
-
|
|
319
|
+
/* ── fetch next batch ── */
|
|
320
|
+
log(options, "Retrieve next batch", iterator.id);
|
|
321
|
+
let newItems = await iterator.iterator.next(batchSize);
|
|
298
322
|
if (options?.transform) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
);
|
|
323
|
+
log(options, "Transform start", iterator.id);
|
|
324
|
+
|
|
325
|
+
newItems = await Promise.all(newItems.map(options.transform));
|
|
326
|
+
log(options, "Transform end", iterator.id);
|
|
302
327
|
}
|
|
303
328
|
|
|
329
|
+
/* iterator might have been reset while we were async… */
|
|
330
|
+
|
|
304
331
|
if (iteratorRef.current !== iterator) {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
logWithId(options, "Iterator ref changed, not updating state", {
|
|
308
|
-
refBefore: iterator.id,
|
|
309
|
-
currentRef: iteratorRef.current?.id,
|
|
310
|
-
ignoredItems: newItems.length,
|
|
311
|
-
});
|
|
312
|
-
return;
|
|
332
|
+
log(options, "Iterator reset while loading more");
|
|
333
|
+
return false;
|
|
313
334
|
}
|
|
314
335
|
|
|
315
|
-
|
|
316
|
-
options,
|
|
317
|
-
"loadMore: loaded more items for iterator " +
|
|
318
|
-
iteratorRef.current?.id,
|
|
319
|
-
"new items length",
|
|
320
|
-
newItems.length,
|
|
321
|
-
"all items length",
|
|
322
|
-
allRef.current.length
|
|
323
|
-
);
|
|
336
|
+
iterator.itemsConsumed += newItems.length;
|
|
324
337
|
|
|
325
338
|
emptyResultsRef.current = newItems.length === 0;
|
|
326
339
|
|
|
327
|
-
if (newItems.length
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
340
|
+
if (newItems.length) {
|
|
341
|
+
log(
|
|
342
|
+
"Loaded more items for iterator",
|
|
343
|
+
iterator.id,
|
|
344
|
+
"current id",
|
|
345
|
+
iteratorRef.current?.id,
|
|
346
|
+
"new items",
|
|
347
|
+
newItems.length,
|
|
348
|
+
"previous results",
|
|
349
|
+
allRef.current.length,
|
|
350
|
+
"batchSize",
|
|
351
|
+
batchSize,
|
|
352
|
+
"items consumed",
|
|
353
|
+
iterator.itemsConsumed
|
|
332
354
|
);
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
"no new items after dedup, not updating state. Prev length",
|
|
337
|
-
prev.length
|
|
338
|
-
);
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
const combined = options?.reverse
|
|
342
|
-
? [...newItemsNoHash.reverse(), ...prev]
|
|
343
|
-
: [...prev, ...newItemsNoHash];
|
|
344
|
-
updateAll(combined, null);
|
|
345
|
-
} else {
|
|
346
|
-
logWithId(
|
|
347
|
-
options,
|
|
348
|
-
"no new items, not updating state for iterator " +
|
|
349
|
-
iteratorRef.current?.id +
|
|
350
|
-
" existing results length",
|
|
351
|
-
allRef.current.length
|
|
355
|
+
const prev = allRef.current;
|
|
356
|
+
const dedup = new Set(
|
|
357
|
+
prev.map((x) => (x as any).__context.head)
|
|
352
358
|
);
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
359
|
+
const unique = newItems.filter(
|
|
360
|
+
(x) => !dedup.has((x as any).__context.head)
|
|
361
|
+
);
|
|
362
|
+
if (!unique.length) return;
|
|
363
|
+
|
|
364
|
+
const combined = reverseRef.current
|
|
365
|
+
? [...unique.reverse(), ...prev]
|
|
366
|
+
: [...prev, ...unique];
|
|
367
|
+
updateAll(combined);
|
|
358
368
|
} else {
|
|
359
|
-
|
|
369
|
+
log(options, "No new items", iterator.id);
|
|
360
370
|
}
|
|
371
|
+
return !iterator.iterator.done();
|
|
372
|
+
} catch (e) {
|
|
373
|
+
if (!(e instanceof ClosedError)) throw e;
|
|
361
374
|
} finally {
|
|
362
375
|
setIsLoading(false);
|
|
363
376
|
loadingMoreRef.current = false;
|
|
364
377
|
}
|
|
365
378
|
};
|
|
366
379
|
|
|
367
|
-
|
|
380
|
+
/* ────────────── public API ────────────── */
|
|
381
|
+
return {
|
|
382
|
+
items: all,
|
|
383
|
+
loadMore,
|
|
384
|
+
isLoading,
|
|
385
|
+
empty: () => emptyResultsRef.current,
|
|
386
|
+
id: id,
|
|
387
|
+
};
|
|
368
388
|
};
|