@peerbit/react 0.0.21 → 0.0.22
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 -213
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":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,EACH,WAAW,GAKd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAWlC,6CAA6C;AAC7C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAMpB,EAAoB,EACpB,OAqBgB,EAClB,EAAE;IAIA,gDAAgD;IAChD,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAS,EAAE,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAS,EAAE,CAAC,CAAC;IAClC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,cAAc,GAAG,MAAM,CAAU,KAAK,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,MAAM,CAIhB,IAAI,CAAC,CAAC;IAChB,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,kBAAkB,GAAG,MAAM,CAAyB,IAAI,CAAC,CAAC;IAChE,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,mBAAmB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAEzC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAqB,SAAS,CAAC,CAAC;IAC5D,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAEhE,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,SAAS,CAAC,GAAG,EAAE;QACX,UAAU,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;IAC1C,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEvB,wCAAwC;IACxC,MAAM,GAAG,GAAG,CAAC,GAAG,CAAQ,EAAE,EAAE;QACxB,IAAI,CAAC,OAAO,EAAE,KAAK;YAAE,OAAO;QAC5B,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;;YACrD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,QAAgB,EAAE,EAAE;QACnC,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC;QAC1B,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,CACV,OAGQ,EACV,EAAE;QACA,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;QACpC,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YAC5C,OAAO;QACX,CAAC;QAED,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAE3B,kBAAkB,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QACpC,kBAAkB,CAAC,OAAO,GAAG,IAAI,eAAe,EAAE,CAAC;QACnD,eAAe,CAAC,OAAO,GAAG,KAAK,CAAC;QAEhC,OAAO,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;QAE1B,IAAI,mBAAmB,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC;YACpB,MAAM,CAAC,EAAE,CAAC,CAAC;QACf,CAAC;QAED,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,cAAc,CAAC,OAAO,GAAG,KAAK,CAAC;QAC/B,GAAG,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QACzD,KAAK,CAAC,SAAS,CAAC,CAAC;IACrB,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACX,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;QACnC,aAAa,CAAC,OAAO,GAAG,KAAK,CAAC;IAClC,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAE5E,+DAA+D;IAC/D,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,IAAI,OAAO,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC;YAC7C,KAAK,CAAC,IAAI,CAAC,CAAC;YACZ,OAAO;QACX,CAAC;QAED,MAAM,YAAY,GAAG,GAAG,EAAE;YACtB,IAAI,EAAE,GAAG,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG;gBACR,EAAE;gBACF,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,EAAE;oBAC5C,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI;oBAC7B,MAAM,EACF,OAAO,CAAC,MAAM,IAAI,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK;wBAC9C,CAAC,CAAC,KAAK;wBACP,CAAC,CAAC,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ;4BACpC,CAAC,CAAC,OAAO,CAAC,MAAM;4BAChB,CAAC,CAAC,IAAI;oBACd,OAAO,EAAE,OAAO,EAAE,OAAO;iBAC5B,CAA0B;gBAC3B,aAAa,EAAE,CAAC;aACnB,CAAC;YACF,WAAW,CAAC,OAAO,GAAG,GAAG,CAAC;YAC1B,IAAI,OAAO,EAAE,QAAQ,EAAE,CAAC;gBACpB,QAAQ,EAAE,CAAC;YACf,CAAC;YACD,KAAK,CAAC,EAAE,CAAC,CAAC;YAEV,GAAG,CAAC,sBAAsB,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YACpC,OAAO,GAAG,CAAC;QACf,CAAC,CAAC;QAEF,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC3B,MAAM,cAAc,GAAG,YAAY,EAAE,CAAC;QAEtC,oCAAoC;QACpC,IAAI,YAEW,CAAC;QAEhB,IAAI,OAAO,EAAE,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YACxD,MAAM,OAAO,GACT,OAAO,OAAO,CAAC,QAAQ,CAAC,KAAK,KAAK,UAAU;gBACxC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK;gBACxB,CAAC,CAAC,CAAC,CAAqB,EAAE,EAAE,CAAC,CAAC,CAAC;YAEvC,YAAY,GAAG,KAAK,EAAE,CAAkC,EAAE,EAAE;gBACxD,GAAG,CACC,OAAO,EACP,cAAc,EACd,CAAC,CAAC,MAAM,EACR,UAAU,EACV,cAAc,CAAC,EAAE,CACpB,CAAC;gBACF,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBACzC,IACI,CAAC,QAAQ;oBACT,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;wBACxB,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;oBAElC,OAAO;gBAEX,IAAI,MAAc,CAAC;gBACnB,IAAI,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;oBAC3B,MAAM,GAAG;wBACL,GAAG,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC;qBACxD,CAAC;gBACN,CAAC;qBAAM,CAAC;oBACJ,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CACjC,MAAM,CAAC,OAA4B,EACnC,QAAQ,EACR,OAAO,CAAC,KAAK,IAAI,EAAE,EACnB,OAAO,CAAC,OAAO,IAAI,IAAI,CAC1B,CAAC;oBAEF,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBACrD,MAAM,YAAY,GACd,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;oBAEpD,IACI,MAAM,KAAK,MAAM,CAAC,OAAO;wBACzB,CAAC,YAAY,KAAK,CAAC;4BACf,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAC9C,CAAC;wBACC,YAAY;wBACZ,GAAG,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;wBACtC,OAAO;oBACX,CAAC;gBACL,CAAC;gBAED,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC5D,CAAC,CAAC;YAEF,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,GAAG,EAAE;YACR,YAAY;gBACR,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YAC1D,KAAK,CAAC,cAAc,CAAC,CAAC;QAC1B,CAAC,CAAC;IACN,CAAC,EAAE;QACC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO;QACpC,OAAO,EAAE,EAAE,IAAI,OAAO,EAAE,KAAK;QAC7B,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,OAAO;QAChB,YAAY;KACf,CAAC,CAAC;IAEH,8DAA8D;IAC9D,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,EAAE,CAAC;IAE3C,MAAM,UAAU,GAAG,GAAY,EAAE;QAC7B,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,OAAO,EAAE,MAAM,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;QAC5C,IAAI,OAAO,EAAE,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC1C,IAAI,OAAO,EAAE,MAAM,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACzC,IAAI,OAAO,OAAO,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,GAAuB,EAAE;QAC7C,IAAI,OAAO,OAAO,EAAE,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAC9D,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,GAAG,CAAC,qBAAqB,CAAC;QAClE,CAAC;QACD,OAAO,SAAS,CAAC;IACrB,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,GAAG,EAAE;QACpB,aAAa,CAAC,OAAO,GAAG,IAAI,CAAC;IACjC,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QACxB,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC;QACrC,IACI,CAAC,QAAQ;YACT,eAAe,CAAC,OAAO;YACvB,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE;YACxB,cAAc,CAAC,OAAO,EACxB,CAAC;YACC,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC;QAE9B,IAAI,CAAC;YACD,mCAAmC;YACnC,IAAI,UAAU,EAAE,EAAE,CAAC;gBACf,GAAG,CAAC,OAAO,EAAE,sBAAsB,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAElD,IAAI,OAAO,GACP,OAAO,OAAO,EAAE,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;gBAChE,MAAM,WAAW,GACb,OAAO,OAAO,EAAE,MAAM,KAAK,QAAQ;oBACnC,OAAO,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,QAAQ;oBACtC,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM;oBACxB,CAAC,CAAC,KAAK,CAAC;gBAEhB,IAAI,wBAAwB,GACxB,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;gBACtC,IAAI,OAAO,GAAG,EAAE,EAAE,GAAG;qBAChB,kBAAkB,CAAC;oBAChB,OAAO,EAAE,WAAW;oBACpB,MAAM,EAAE,kBAAkB,CAAC,OAAO,EAAE,MAAM;iBAC7C,CAAC;qBACD,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;oBACT,IACI,CAAC,YAAY,UAAU;wBACvB,CAAC,YAAY,YAAY;wBAEzB,OAAO;oBACX,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAE,CAAC,CAAC,CAAC;gBACpD,CAAC,CAAC;qBACD,OAAO,CAAC,GAAG,EAAE;oBACV,UAAU,EAAE,CAAC;oBACb,IAAI,wBAAwB,EAAE,CAAC;wBAC3B,mBAAmB,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,qEAAqE;wBAC1G,WAAW,EAAE,CAAC;oBAClB,CAAC;gBACL,CAAC,CAAC,CAAC;gBACP,IAAI,CAAC,wBAAwB,EAAE,CAAC;oBAC5B,MAAM,OAAO,CAAC;gBAClB,CAAC;YACL,CAAC;iBAAM,CAAC;gBACJ,GAAG,CAAC,OAAO,EAAE,2BAA2B,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC3D,CAAC;YAED,4BAA4B;YAC5B,GAAG,CAAC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YACjD,IAAI,QAAQ,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACvD,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;gBACrB,GAAG,CAAC,OAAO,EAAE,iBAAiB,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAE7C,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;gBAC9D,GAAG,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC/C,CAAC;YAED,yDAAyD;YAEzD,IAAI,WAAW,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACnC,GAAG,CAAC,OAAO,EAAE,mCAAmC,CAAC,CAAC;gBAClD,OAAO,KAAK,CAAC;YACjB,CAAC;YAED,QAAQ,CAAC,aAAa,IAAI,QAAQ,CAAC,MAAM,CAAC;YAE1C,eAAe,CAAC,OAAO,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;YAEhD,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAClB,GAAG,CACC,gCAAgC,EAChC,QAAQ,CAAC,EAAE,EACX,YAAY,EACZ,WAAW,CAAC,OAAO,EAAE,EAAE,EACvB,WAAW,EACX,QAAQ,CAAC,MAAM,EACf,kBAAkB,EAClB,MAAM,CAAC,OAAO,CAAC,MAAM,EACrB,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,QAAQ,CAAC,aAAa,CACzB,CAAC;gBACF,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC;gBAC5B,MAAM,KAAK,GAAG,IAAI,GAAG,CACjB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAC7C,CAAC;gBACF,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAE,CAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAC/C,CAAC;gBACF,IAAI,CAAC,MAAM,CAAC,MAAM;oBAAE,OAAO;gBAE3B,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO;oBAC/B,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC;oBAChC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC;gBAC3B,SAAS,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACJ,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC9C,CAAC;YACD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,IAAI,CAAC,CAAC,CAAC,YAAY,WAAW,CAAC;gBAAE,MAAM,CAAC,CAAC;QAC7C,CAAC;gBAAS,CAAC;YACP,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,cAAc,CAAC,OAAO,GAAG,KAAK,CAAC;QACnC,CAAC;IACL,CAAC,CAAC;IAEF,8CAA8C;IAC9C,OAAO;QACH,KAAK,EAAE,GAAG;QACV,QAAQ;QACR,SAAS;QACT,KAAK,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,OAAO;QACpC,EAAE,EAAE,EAAE;KACT,CAAC;AACN,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peerbit/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22",
|
|
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": "0aeb9e6d47a916b922efd66f4b14ac982664a9bd"
|
|
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,19 @@ import {
|
|
|
8
8
|
} from "@peerbit/document";
|
|
9
9
|
import * as indexerTypes from "@peerbit/indexer-interface";
|
|
10
10
|
import { AbortError } from "@peerbit/time";
|
|
11
|
+
import { NoPeersError } from "@peerbit/shared-log";
|
|
12
|
+
import { v4 as uuid } from "uuid";
|
|
11
13
|
|
|
14
|
+
/* ────────────── helper types ────────────── */
|
|
12
15
|
type QueryLike = {
|
|
13
16
|
query?: indexerTypes.Query[] | indexerTypes.QueryLike;
|
|
14
17
|
sort?: indexerTypes.Sort[] | indexerTypes.Sort | indexerTypes.SortLike;
|
|
15
18
|
};
|
|
16
|
-
type QueryOptions = { query: QueryLike; id
|
|
19
|
+
type QueryOptions = { query: QueryLike; id?: string };
|
|
17
20
|
|
|
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
|
-
};
|
|
21
|
+
type WaitForReplicatorsOption = { warmup?: number; eager?: boolean };
|
|
30
22
|
|
|
23
|
+
/* ────────────── main hook ────────────── */
|
|
31
24
|
export const useQuery = <
|
|
32
25
|
T extends Record<string, any>,
|
|
33
26
|
I extends Record<string, any>,
|
|
@@ -37,167 +30,179 @@ export const useQuery = <
|
|
|
37
30
|
db?: Documents<T, I>,
|
|
38
31
|
options?: {
|
|
39
32
|
resolve?: R;
|
|
40
|
-
|
|
41
|
-
transform?: (result: WithContext<RT>) => Promise<WithContext<RT>>;
|
|
33
|
+
transform?: (r: RT) => Promise<RT>;
|
|
42
34
|
debounce?: number;
|
|
43
35
|
debug?: boolean | { id: string };
|
|
44
36
|
reverse?: boolean;
|
|
45
|
-
batchSize?: number;
|
|
37
|
+
batchSize?: number;
|
|
38
|
+
prefetch?: boolean;
|
|
46
39
|
onChange?: {
|
|
47
40
|
merge?:
|
|
48
41
|
| boolean
|
|
49
42
|
| ((
|
|
50
|
-
|
|
43
|
+
c: DocumentsChange<T>
|
|
51
44
|
) =>
|
|
52
45
|
| DocumentsChange<T>
|
|
53
46
|
| Promise<DocumentsChange<T>>
|
|
54
|
-
| undefined);
|
|
55
|
-
update?: (
|
|
56
|
-
prev: WithContext<RT>[],
|
|
57
|
-
change: DocumentsChange<T>
|
|
58
|
-
) => WithContext<RT>[];
|
|
47
|
+
| undefined);
|
|
48
|
+
update?: (prev: RT[], change: DocumentsChange<T>) => RT[];
|
|
59
49
|
};
|
|
60
|
-
local?: boolean;
|
|
61
|
-
remote?:
|
|
62
|
-
| boolean
|
|
63
|
-
| {
|
|
64
|
-
eager?: boolean;
|
|
65
|
-
};
|
|
50
|
+
local?: boolean;
|
|
51
|
+
remote?: boolean | WaitForReplicatorsOption;
|
|
66
52
|
} & QueryOptions
|
|
67
53
|
) => {
|
|
68
|
-
|
|
69
|
-
|
|
54
|
+
/* ── «Item» is the concrete element type flowing through the hook ── */
|
|
55
|
+
type Item = RT;
|
|
56
|
+
|
|
57
|
+
/* ────────────── state & refs ────────────── */
|
|
58
|
+
const [all, setAll] = useState<Item[]>([]);
|
|
59
|
+
const allRef = useRef<Item[]>([]);
|
|
70
60
|
const [isLoading, setIsLoading] = useState(false);
|
|
71
|
-
const loadingMoreRef = useRef(false);
|
|
61
|
+
const loadingMoreRef = useRef<boolean>(false);
|
|
72
62
|
const iteratorRef = useRef<{
|
|
73
63
|
id?: string;
|
|
74
|
-
iterator: ResultsIterator<
|
|
64
|
+
iterator: ResultsIterator<Item>;
|
|
65
|
+
itemsConsumed: number;
|
|
75
66
|
} | null>(null);
|
|
76
67
|
const emptyResultsRef = useRef(false);
|
|
77
68
|
const closeControllerRef = useRef<AbortController | null>(null);
|
|
69
|
+
const waitedOnceRef = useRef(false);
|
|
70
|
+
const resetResultsOnReset = useRef(true);
|
|
78
71
|
|
|
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
|
-
);
|
|
72
|
+
const [id, setId] = useState<string | undefined>(undefined);
|
|
73
|
+
const [resetCounter, invokeReset] = useReducer((n) => n + 1, 0);
|
|
90
74
|
|
|
91
|
-
|
|
75
|
+
const reverseRef = useRef(options?.reverse);
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
reverseRef.current = options?.reverse;
|
|
78
|
+
}, [options?.reverse]);
|
|
79
|
+
|
|
80
|
+
/* ────────────── util ────────────── */
|
|
81
|
+
const log = (...a: any[]) => {
|
|
82
|
+
if (!options?.debug) return;
|
|
83
|
+
if (typeof options.debug === "boolean") console.log(...a);
|
|
84
|
+
else console.log(options.debug.id, ...a);
|
|
85
|
+
};
|
|
92
86
|
|
|
87
|
+
const updateAll = (combined: Item[]) => {
|
|
88
|
+
allRef.current = combined;
|
|
93
89
|
setAll(combined);
|
|
94
90
|
};
|
|
95
91
|
|
|
96
92
|
const reset = (
|
|
97
93
|
fromRef: {
|
|
98
94
|
id?: string;
|
|
99
|
-
iterator: ResultsIterator<
|
|
95
|
+
iterator: ResultsIterator<Item>;
|
|
100
96
|
} | null
|
|
101
97
|
) => {
|
|
102
|
-
|
|
98
|
+
const toClose = iteratorRef.current;
|
|
99
|
+
if (toClose && fromRef && toClose !== fromRef) {
|
|
103
100
|
return;
|
|
104
101
|
}
|
|
102
|
+
|
|
103
|
+
iteratorRef.current = null;
|
|
104
|
+
|
|
105
105
|
closeControllerRef.current?.abort();
|
|
106
106
|
closeControllerRef.current = new AbortController();
|
|
107
|
-
|
|
108
107
|
emptyResultsRef.current = false;
|
|
109
|
-
logWithId(options, "reset", {
|
|
110
|
-
id: iteratorRef.current?.id,
|
|
111
|
-
size: allRef.current.length,
|
|
112
|
-
});
|
|
113
108
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
109
|
+
toClose?.iterator.close();
|
|
110
|
+
|
|
111
|
+
if (resetResultsOnReset.current) {
|
|
112
|
+
allRef.current = [];
|
|
113
|
+
setAll([]);
|
|
114
|
+
}
|
|
115
|
+
|
|
118
116
|
setIsLoading(false);
|
|
119
117
|
loadingMoreRef.current = false;
|
|
120
|
-
|
|
118
|
+
log(options, "Iterator reset", toClose?.id, fromRef?.id);
|
|
119
|
+
setId(undefined);
|
|
121
120
|
};
|
|
122
121
|
|
|
123
|
-
// Initialize the iterator only once or when query changes
|
|
124
122
|
useEffect(() => {
|
|
125
|
-
|
|
123
|
+
resetResultsOnReset.current = true;
|
|
124
|
+
waitedOnceRef.current = false;
|
|
125
|
+
}, [db, options?.id ?? options?.query, options?.resolve, options?.reverse]);
|
|
126
|
+
|
|
127
|
+
/* ────────────── effect: (re)create iterator ────────────── */
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (!db || db.closed || options?.query == null) {
|
|
126
130
|
reset(null);
|
|
127
131
|
return;
|
|
128
132
|
}
|
|
129
133
|
|
|
130
134
|
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;
|
|
135
|
+
let id = options?.id ?? uuid();
|
|
136
|
+
const ref = {
|
|
137
|
+
id,
|
|
138
|
+
iterator: db.index.iterate(options.query ?? {}, {
|
|
139
|
+
local: options?.local ?? true,
|
|
140
|
+
remote:
|
|
141
|
+
options.remote == null || options.remote === false
|
|
142
|
+
? false
|
|
143
|
+
: typeof options.remote === "object"
|
|
144
|
+
? options.remote
|
|
145
|
+
: true,
|
|
146
|
+
resolve: options?.resolve,
|
|
147
|
+
}) as ResultsIterator<Item>,
|
|
148
|
+
itemsConsumed: 0,
|
|
149
|
+
};
|
|
150
|
+
iteratorRef.current = ref;
|
|
151
|
+
if (options?.prefetch) {
|
|
152
|
+
loadMore();
|
|
155
153
|
}
|
|
154
|
+
setId(id);
|
|
155
|
+
|
|
156
|
+
log("Iterator initialised", ref.id);
|
|
157
|
+
return ref;
|
|
156
158
|
};
|
|
157
159
|
|
|
158
|
-
// Reset state when the db or query changes.
|
|
159
160
|
reset(iteratorRef.current);
|
|
160
|
-
|
|
161
161
|
const newIteratorRef = initIterator();
|
|
162
162
|
|
|
163
|
+
/* live-merge listener (optional) */
|
|
163
164
|
let handleChange:
|
|
164
|
-
|
|
|
165
|
-
|
|
|
166
|
-
|
|
167
|
-
if (options?.onChange && options
|
|
168
|
-
|
|
165
|
+
| ((e: CustomEvent<DocumentsChange<T>>) => void | Promise<void>)
|
|
166
|
+
| undefined;
|
|
167
|
+
|
|
168
|
+
if (options?.onChange && options.onChange.merge !== false) {
|
|
169
|
+
const mergeFn =
|
|
169
170
|
typeof options.onChange.merge === "function"
|
|
170
171
|
? options.onChange.merge
|
|
171
|
-
: (
|
|
172
|
+
: (c: DocumentsChange<T>) => c;
|
|
173
|
+
|
|
172
174
|
handleChange = async (e: CustomEvent<DocumentsChange<T>>) => {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
+
log(
|
|
176
|
+
options,
|
|
177
|
+
"Merge change",
|
|
178
|
+
e.detail,
|
|
179
|
+
"iterator",
|
|
180
|
+
newIteratorRef.id
|
|
181
|
+
);
|
|
182
|
+
const filtered = await mergeFn(e.detail);
|
|
175
183
|
if (
|
|
176
|
-
!
|
|
177
|
-
(
|
|
178
|
-
|
|
179
|
-
)
|
|
184
|
+
!filtered ||
|
|
185
|
+
(filtered.added.length === 0 &&
|
|
186
|
+
filtered.removed.length === 0)
|
|
187
|
+
)
|
|
180
188
|
return;
|
|
181
|
-
|
|
182
|
-
let merged:
|
|
189
|
+
|
|
190
|
+
let merged: Item[];
|
|
183
191
|
if (options.onChange?.update) {
|
|
184
192
|
merged = [
|
|
185
|
-
...options.onChange
|
|
186
|
-
allRef.current,
|
|
187
|
-
filteredChange
|
|
188
|
-
),
|
|
193
|
+
...options.onChange?.update(allRef.current, filtered),
|
|
189
194
|
];
|
|
190
195
|
} else {
|
|
191
196
|
merged = await db.index.updateResults(
|
|
192
|
-
allRef.current,
|
|
193
|
-
|
|
194
|
-
options
|
|
195
|
-
options
|
|
197
|
+
allRef.current as WithContext<RT>[],
|
|
198
|
+
filtered,
|
|
199
|
+
options.query || {},
|
|
200
|
+
options.resolve ?? true
|
|
196
201
|
);
|
|
197
|
-
|
|
202
|
+
|
|
203
|
+
log(options, "After update", allRef.current, merged);
|
|
198
204
|
const expectedDiff =
|
|
199
|
-
|
|
200
|
-
filteredChange.removed.length;
|
|
205
|
+
filtered.added.length - filtered.removed.length;
|
|
201
206
|
|
|
202
207
|
if (
|
|
203
208
|
merged === allRef.current ||
|
|
@@ -205,23 +210,14 @@ export const useQuery = <
|
|
|
205
210
|
merged.length === allRef.current.length)
|
|
206
211
|
) {
|
|
207
212
|
// no change
|
|
208
|
-
|
|
213
|
+
log(options, "no change after merge");
|
|
209
214
|
return;
|
|
210
215
|
}
|
|
211
216
|
}
|
|
212
217
|
|
|
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
|
-
);
|
|
218
|
+
updateAll(options?.reverse ? merged.reverse() : merged);
|
|
224
219
|
};
|
|
220
|
+
|
|
225
221
|
db.events.addEventListener("change", handleChange);
|
|
226
222
|
}
|
|
227
223
|
|
|
@@ -232,137 +228,162 @@ export const useQuery = <
|
|
|
232
228
|
};
|
|
233
229
|
}, [
|
|
234
230
|
db?.closed ? undefined : db?.address,
|
|
235
|
-
options?.id
|
|
231
|
+
options?.id ?? options?.query,
|
|
236
232
|
options?.resolve,
|
|
233
|
+
options?.reverse,
|
|
234
|
+
resetCounter,
|
|
237
235
|
]);
|
|
238
236
|
|
|
239
|
-
|
|
237
|
+
/* ────────────── loadMore (once-wait aware) ────────────── */
|
|
240
238
|
const batchSize = options?.batchSize ?? 10;
|
|
239
|
+
|
|
240
|
+
const shouldWait = (): boolean => {
|
|
241
|
+
if (waitedOnceRef.current) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
if (options?.remote === false) return false;
|
|
245
|
+
if (options?.remote === true) return true;
|
|
246
|
+
if (options?.remote == null) return true;
|
|
247
|
+
if (typeof options?.remote === "object") {
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
return true;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
const reloadAfterTime = (): number | undefined => {
|
|
254
|
+
if (typeof options?.remote === "object" && options.remote.eager) {
|
|
255
|
+
return options.remote.warmup ?? db?.log.timeUntilRoleMaturity;
|
|
256
|
+
}
|
|
257
|
+
return undefined;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const markWaited = () => {
|
|
261
|
+
waitedOnceRef.current = true;
|
|
262
|
+
};
|
|
263
|
+
|
|
241
264
|
const loadMore = async () => {
|
|
265
|
+
const iterator = iteratorRef.current;
|
|
242
266
|
if (
|
|
243
|
-
!
|
|
267
|
+
!iterator ||
|
|
244
268
|
emptyResultsRef.current ||
|
|
245
|
-
|
|
269
|
+
iterator.iterator.done() ||
|
|
246
270
|
loadingMoreRef.current
|
|
247
271
|
) {
|
|
248
|
-
|
|
249
|
-
isLoading,
|
|
250
|
-
emptyResultsRef: emptyResultsRef.current,
|
|
251
|
-
iteratorRef: !iteratorRef.current,
|
|
252
|
-
});
|
|
253
|
-
return;
|
|
272
|
+
return false;
|
|
254
273
|
}
|
|
255
|
-
const iterator = iteratorRef.current;
|
|
256
274
|
|
|
257
275
|
setIsLoading(true);
|
|
258
276
|
loadingMoreRef.current = true;
|
|
277
|
+
|
|
259
278
|
try {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
options,
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
279
|
+
/* ── optional replicate-wait ── */
|
|
280
|
+
if (shouldWait()) {
|
|
281
|
+
log(options, "Wait for replicators", iterator.id);
|
|
282
|
+
|
|
283
|
+
let isEager =
|
|
284
|
+
typeof options?.remote === "object" && options.remote.eager;
|
|
285
|
+
const waitTimeout =
|
|
286
|
+
typeof options?.remote === "object" &&
|
|
287
|
+
typeof options?.remote.warmup === "number"
|
|
288
|
+
? options?.remote.warmup
|
|
289
|
+
: 5_000;
|
|
290
|
+
|
|
291
|
+
let shouldResetAfterMaturity =
|
|
292
|
+
isEager && !waitedOnceRef.current;
|
|
293
|
+
let promise = db?.log
|
|
271
294
|
.waitForReplicators({
|
|
272
|
-
timeout,
|
|
295
|
+
timeout: waitTimeout,
|
|
273
296
|
signal: closeControllerRef.current?.signal,
|
|
274
297
|
})
|
|
275
298
|
.catch((e) => {
|
|
276
|
-
if (
|
|
277
|
-
|
|
299
|
+
if (
|
|
300
|
+
e instanceof AbortError ||
|
|
301
|
+
e instanceof NoPeersError
|
|
302
|
+
)
|
|
278
303
|
return;
|
|
279
|
-
}
|
|
280
304
|
console.warn("Remote replicators not ready", e);
|
|
305
|
+
})
|
|
306
|
+
.finally(() => {
|
|
307
|
+
markWaited();
|
|
308
|
+
if (shouldResetAfterMaturity) {
|
|
309
|
+
resetResultsOnReset.current = false; // don't reset results, because we expect to get same or more results
|
|
310
|
+
invokeReset();
|
|
311
|
+
}
|
|
281
312
|
});
|
|
313
|
+
if (!shouldResetAfterMaturity) {
|
|
314
|
+
await promise;
|
|
315
|
+
}
|
|
316
|
+
} else {
|
|
317
|
+
log(options, "Skip wait for replicators", iterator.id);
|
|
282
318
|
}
|
|
283
319
|
|
|
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
|
-
|
|
320
|
+
/* ── fetch next batch ── */
|
|
321
|
+
log(options, "Retrieve next batch", iterator.id);
|
|
322
|
+
let newItems = await iterator.iterator.next(batchSize);
|
|
298
323
|
if (options?.transform) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
);
|
|
324
|
+
log(options, "Transform start", iterator.id);
|
|
325
|
+
|
|
326
|
+
newItems = await Promise.all(newItems.map(options.transform));
|
|
327
|
+
log(options, "Transform end", iterator.id);
|
|
302
328
|
}
|
|
303
329
|
|
|
330
|
+
/* iterator might have been reset while we were async… */
|
|
331
|
+
|
|
304
332
|
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;
|
|
333
|
+
log(options, "Iterator reset while loading more");
|
|
334
|
+
return false;
|
|
313
335
|
}
|
|
314
336
|
|
|
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
|
-
);
|
|
337
|
+
iterator.itemsConsumed += newItems.length;
|
|
324
338
|
|
|
325
339
|
emptyResultsRef.current = newItems.length === 0;
|
|
326
340
|
|
|
327
|
-
if (newItems.length
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
341
|
+
if (newItems.length) {
|
|
342
|
+
log(
|
|
343
|
+
"Loaded more items for iterator",
|
|
344
|
+
iterator.id,
|
|
345
|
+
"current id",
|
|
346
|
+
iteratorRef.current?.id,
|
|
347
|
+
"new items",
|
|
348
|
+
newItems.length,
|
|
349
|
+
"previous results",
|
|
350
|
+
allRef.current.length,
|
|
351
|
+
"batchSize",
|
|
352
|
+
batchSize,
|
|
353
|
+
"items consumed",
|
|
354
|
+
iterator.itemsConsumed
|
|
332
355
|
);
|
|
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
|
|
356
|
+
const prev = allRef.current;
|
|
357
|
+
const dedup = new Set(
|
|
358
|
+
prev.map((x) => (x as any).__context.head)
|
|
352
359
|
);
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
360
|
+
const unique = newItems.filter(
|
|
361
|
+
(x) => !dedup.has((x as any).__context.head)
|
|
362
|
+
);
|
|
363
|
+
if (!unique.length) return;
|
|
364
|
+
|
|
365
|
+
const combined = reverseRef.current
|
|
366
|
+
? [...unique.reverse(), ...prev]
|
|
367
|
+
: [...prev, ...unique];
|
|
368
|
+
updateAll(combined);
|
|
358
369
|
} else {
|
|
359
|
-
|
|
370
|
+
log(options, "No new items", iterator.id);
|
|
360
371
|
}
|
|
372
|
+
return !iterator.iterator.done();
|
|
373
|
+
} catch (e) {
|
|
374
|
+
if (!(e instanceof ClosedError)) throw e;
|
|
361
375
|
} finally {
|
|
362
376
|
setIsLoading(false);
|
|
363
377
|
loadingMoreRef.current = false;
|
|
364
378
|
}
|
|
365
379
|
};
|
|
366
380
|
|
|
367
|
-
|
|
381
|
+
/* ────────────── public API ────────────── */
|
|
382
|
+
return {
|
|
383
|
+
items: all,
|
|
384
|
+
loadMore,
|
|
385
|
+
isLoading,
|
|
386
|
+
empty: () => emptyResultsRef.current,
|
|
387
|
+
id: id,
|
|
388
|
+
};
|
|
368
389
|
};
|