@peerbit/react 0.0.15 → 0.0.17
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/index.d.ts +1 -0
- package/lib/esm/index.js +1 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/useLocal.d.ts +3 -1
- package/lib/esm/useLocal.js +15 -6
- package/lib/esm/useLocal.js.map +1 -1
- package/lib/esm/usePeer.js +15 -4
- package/lib/esm/usePeer.js.map +1 -1
- package/lib/esm/useQuery.d.ts +34 -0
- package/lib/esm/useQuery.js +183 -0
- package/lib/esm/useQuery.js.map +1 -0
- package/package.json +3 -3
- package/src/index.ts +1 -0
- package/src/useLocal.tsx +35 -11
- package/src/usePeer.tsx +18 -4
- package/src/useQuery.tsx +290 -0
package/lib/esm/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./utils.js";
|
|
|
3
3
|
export { FastMutex } from "./lockstorage.js";
|
|
4
4
|
export { useProgram } from "./useProgram.js";
|
|
5
5
|
export { useLocal } from "./useLocal.js";
|
|
6
|
+
export { useQuery as useQuery } from "./useQuery.js";
|
|
6
7
|
export { useOnline } from "./useOnline.js";
|
|
7
8
|
export { useCount } from "./useCount.js";
|
|
8
9
|
export { debounceLeadingTrailing } from "./utils.js";
|
package/lib/esm/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./utils.js";
|
|
|
3
3
|
export { FastMutex } from "./lockstorage.js";
|
|
4
4
|
export { useProgram } from "./useProgram.js";
|
|
5
5
|
export { useLocal } from "./useLocal.js";
|
|
6
|
+
export { useQuery as useQuery } from "./useQuery.js";
|
|
6
7
|
export { useOnline } from "./useOnline.js";
|
|
7
8
|
export { useCount } from "./useCount.js";
|
|
8
9
|
export { debounceLeadingTrailing } from "./utils.js";
|
package/lib/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,YAAY,EACZ,WAAW,EACX,OAAO,EACP,eAAe,GAClB,MAAM,cAAc,CAAC;AACtB,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,YAAY,EACZ,WAAW,EACX,OAAO,EACP,eAAe,GAClB,MAAM,cAAc,CAAC;AACtB,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC"}
|
package/lib/esm/useLocal.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export declare const useLocal: <T extends Record<string, any>, I extends Record<
|
|
|
13
13
|
transform?: (result: RT) => Promise<RT>;
|
|
14
14
|
onChanges?: (all: RT[]) => void;
|
|
15
15
|
debounce?: number;
|
|
16
|
-
debug?: boolean
|
|
16
|
+
debug?: boolean | {
|
|
17
|
+
id: string;
|
|
18
|
+
};
|
|
17
19
|
} & QueryOptons) => RT[];
|
|
18
20
|
export {};
|
package/lib/esm/useLocal.js
CHANGED
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
import { ClosedError } from "@peerbit/document";
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
import { debounceLeadingTrailing } from "./utils";
|
|
4
|
+
const logWithId = (options, ...args) => {
|
|
5
|
+
if (!options?.debug)
|
|
6
|
+
return;
|
|
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
14
|
export const useLocal = (db, options) => {
|
|
5
15
|
const [all, setAll] = useState([]);
|
|
6
16
|
const emptyResultsRef = useRef(false);
|
|
7
17
|
useEffect(() => {
|
|
8
|
-
if (!db || db.closed) {
|
|
18
|
+
if (!db || db.closed || options?.query === null) {
|
|
19
|
+
// null query means no query at all
|
|
9
20
|
return;
|
|
10
21
|
}
|
|
22
|
+
logWithId(options, "reset local", db?.closed ? undefined : db?.rootAddress, options?.id, options?.resolve, options?.onChanges, options?.transform);
|
|
11
23
|
const _l = async (args) => {
|
|
12
24
|
try {
|
|
13
25
|
const iterator = db.index.iterate(options?.query ?? {}, {
|
|
@@ -19,6 +31,7 @@ export const useLocal = (db, options) => {
|
|
|
19
31
|
if (options?.transform) {
|
|
20
32
|
results = await Promise.all(results.map((x) => options.transform(x)));
|
|
21
33
|
}
|
|
34
|
+
logWithId(options, options?.id, results, "query", options?.query);
|
|
22
35
|
emptyResultsRef.current = results.length === 0;
|
|
23
36
|
setAll(() => {
|
|
24
37
|
options?.onChanges?.(results);
|
|
@@ -32,10 +45,7 @@ export const useLocal = (db, options) => {
|
|
|
32
45
|
throw error;
|
|
33
46
|
}
|
|
34
47
|
};
|
|
35
|
-
const debounced = debounceLeadingTrailing(_l, options?.debounce ??
|
|
36
|
-
let ts = setTimeout(() => {
|
|
37
|
-
_l();
|
|
38
|
-
}, 3000);
|
|
48
|
+
const debounced = debounceLeadingTrailing(_l, options?.debounce ?? 123);
|
|
39
49
|
const handleChange = () => {
|
|
40
50
|
if (emptyResultsRef.current) {
|
|
41
51
|
debounced.cancel();
|
|
@@ -50,7 +60,6 @@ export const useLocal = (db, options) => {
|
|
|
50
60
|
return () => {
|
|
51
61
|
db.events.removeEventListener("change", handleChange);
|
|
52
62
|
debounced.cancel();
|
|
53
|
-
clearTimeout(ts);
|
|
54
63
|
};
|
|
55
64
|
}, [
|
|
56
65
|
db?.closed ? undefined : db?.rootAddress,
|
package/lib/esm/useLocal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLocal.js","sourceRoot":"","sources":["../../src/useLocal.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;AAWlD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAMpB,EAAoB,EACpB,OAMe,EACjB,EAAE;IACA,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAO,EAAE,CAAC,CAAC;IACzC,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEtC,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"useLocal.js","sourceRoot":"","sources":["../../src/useLocal.tsx"],"names":[],"mappings":"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"}
|
package/lib/esm/usePeer.js
CHANGED
|
@@ -15,6 +15,9 @@ import { webSockets } from "@libp2p/websockets";
|
|
|
15
15
|
import { circuitRelayTransport } from "@libp2p/circuit-relay-v2";
|
|
16
16
|
import * as filters from "@libp2p/websockets/filters";
|
|
17
17
|
import { detectIncognito } from "detectincognitojs";
|
|
18
|
+
const isInStandaloneMode = () => window.matchMedia("(display-mode: standalone)").matches ||
|
|
19
|
+
window.navigator["standalone"] ||
|
|
20
|
+
document.referrer.includes("android-app://");
|
|
18
21
|
export class ClientBusyError extends Error {
|
|
19
22
|
constructor(message) {
|
|
20
23
|
super(message);
|
|
@@ -26,6 +29,10 @@ if (!window.name) {
|
|
|
26
29
|
}
|
|
27
30
|
export const PeerContext = React.createContext({});
|
|
28
31
|
export const usePeer = () => useContext(PeerContext);
|
|
32
|
+
const subscribeToUnload = (fn) => {
|
|
33
|
+
window.addEventListener("pagehide", fn);
|
|
34
|
+
window.addEventListener("beforeunload", fn);
|
|
35
|
+
};
|
|
29
36
|
export const PeerProvider = (options) => {
|
|
30
37
|
const [peer, setPeer] = React.useState(undefined);
|
|
31
38
|
const [promise, setPromise] = React.useState(undefined);
|
|
@@ -96,9 +103,13 @@ export const PeerProvider = (options) => {
|
|
|
96
103
|
const localId = getClientId("local");
|
|
97
104
|
try {
|
|
98
105
|
const lockKey = localId + "-singleton";
|
|
99
|
-
|
|
106
|
+
subscribeToUnload(function () {
|
|
107
|
+
mutex.release(lockKey);
|
|
108
|
+
});
|
|
109
|
+
if (isInStandaloneMode()) {
|
|
110
|
+
// PWA issue fix (? TODO is this needed ?
|
|
100
111
|
mutex.release(lockKey);
|
|
101
|
-
}
|
|
112
|
+
}
|
|
102
113
|
await mutex.lock(lockKey, () => true, {
|
|
103
114
|
replaceIfSameClient: true,
|
|
104
115
|
});
|
|
@@ -117,9 +128,9 @@ export const PeerProvider = (options) => {
|
|
|
117
128
|
releaseFirstLock,
|
|
118
129
|
releaseLockIfSameId: true,
|
|
119
130
|
});
|
|
120
|
-
|
|
131
|
+
subscribeToUnload(function () {
|
|
121
132
|
mutex.release(kp.path);
|
|
122
|
-
};
|
|
133
|
+
});
|
|
123
134
|
nodeId = kp.key;
|
|
124
135
|
setTabIndex(kp.index);
|
|
125
136
|
}
|
package/lib/esm/usePeer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePeer.js","sourceRoot":"","sources":["../../src/usePeer.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"usePeer.js","sourceRoot":"","sources":["../../src/usePeer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Documents, DocumentsChange, WithContext } from "@peerbit/document";
|
|
2
|
+
import * as indexerTypes from "@peerbit/indexer-interface";
|
|
3
|
+
type QueryLike = {
|
|
4
|
+
query?: indexerTypes.Query[] | indexerTypes.QueryLike;
|
|
5
|
+
sort?: indexerTypes.Sort[] | indexerTypes.Sort | indexerTypes.SortLike;
|
|
6
|
+
};
|
|
7
|
+
type QueryOptions = {
|
|
8
|
+
query: QueryLike;
|
|
9
|
+
id: string;
|
|
10
|
+
};
|
|
11
|
+
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
|
+
resolve?: R;
|
|
13
|
+
transform?: (result: WithContext<RT>) => Promise<WithContext<RT>>;
|
|
14
|
+
debounce?: number;
|
|
15
|
+
debug?: boolean | {
|
|
16
|
+
id: string;
|
|
17
|
+
};
|
|
18
|
+
reverse?: boolean;
|
|
19
|
+
batchSize?: number;
|
|
20
|
+
onChange?: {
|
|
21
|
+
merge?: boolean | ((change: DocumentsChange<T>) => DocumentsChange<T> | Promise<DocumentsChange<T>> | undefined);
|
|
22
|
+
update?: (prev: WithContext<RT>[], change: DocumentsChange<T>) => WithContext<RT>[];
|
|
23
|
+
};
|
|
24
|
+
local?: boolean;
|
|
25
|
+
remote?: boolean | {
|
|
26
|
+
eager?: boolean;
|
|
27
|
+
};
|
|
28
|
+
} & QueryOptions) => {
|
|
29
|
+
items: WithContext<RT>[];
|
|
30
|
+
loadMore: () => Promise<void>;
|
|
31
|
+
isLoading: boolean;
|
|
32
|
+
empty: boolean;
|
|
33
|
+
};
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { useState, useEffect, useRef } from "react";
|
|
2
|
+
import { ClosedError, } from "@peerbit/document";
|
|
3
|
+
const logWithId = (options, ...args) => {
|
|
4
|
+
if (!options?.debug)
|
|
5
|
+
return;
|
|
6
|
+
if (typeof options.debug === "boolean") {
|
|
7
|
+
console.log(...args);
|
|
8
|
+
}
|
|
9
|
+
else if (typeof options.debug.id === "string") {
|
|
10
|
+
console.log(options.debug.id, ...args);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
export const useQuery = (db, options) => {
|
|
14
|
+
const [all, setAll] = useState([]);
|
|
15
|
+
const allRef = useRef([]);
|
|
16
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
17
|
+
const loadingMoreRef = useRef(false);
|
|
18
|
+
const iteratorRef = useRef(null);
|
|
19
|
+
const emptyResultsRef = useRef(false);
|
|
20
|
+
const updateAll = (combined) => {
|
|
21
|
+
logWithId(options, "Loading more items, new combined length", combined.length);
|
|
22
|
+
allRef.current = combined;
|
|
23
|
+
setAll(combined);
|
|
24
|
+
};
|
|
25
|
+
const reset = () => {
|
|
26
|
+
emptyResultsRef.current = false;
|
|
27
|
+
iteratorRef.current?.iterator.done() &&
|
|
28
|
+
iteratorRef.current?.iterator?.close();
|
|
29
|
+
iteratorRef.current = null;
|
|
30
|
+
setAll([]);
|
|
31
|
+
setIsLoading(false);
|
|
32
|
+
loadingMoreRef.current = false;
|
|
33
|
+
allRef.current = [];
|
|
34
|
+
};
|
|
35
|
+
// Initialize the iterator only once or when query changes
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (!db || db.closed || options?.query === null) {
|
|
38
|
+
reset();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const initIterator = () => {
|
|
42
|
+
// Don't make this async, it will cause issues with the iterator refs
|
|
43
|
+
try {
|
|
44
|
+
// Initialize the iterator and load initial batch.
|
|
45
|
+
emptyResultsRef.current = false;
|
|
46
|
+
iteratorRef.current?.iterator.close();
|
|
47
|
+
iteratorRef.current = {
|
|
48
|
+
id: options?.id,
|
|
49
|
+
iterator: db.index.iterate(options?.query ?? {}, {
|
|
50
|
+
local: options?.local ?? true,
|
|
51
|
+
remote: options?.remote ?? true,
|
|
52
|
+
resolve: options?.resolve,
|
|
53
|
+
}),
|
|
54
|
+
};
|
|
55
|
+
logWithId(options, "Initializing iterator", options?.id);
|
|
56
|
+
loadMore(); // initial load
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error("Error initializing iterator", error);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
// Reset state when the db or query changes.
|
|
63
|
+
reset();
|
|
64
|
+
initIterator();
|
|
65
|
+
let handleChange = undefined;
|
|
66
|
+
if (options?.onChange) {
|
|
67
|
+
let mergeFunction = typeof options.onChange.merge === "function"
|
|
68
|
+
? options.onChange.merge
|
|
69
|
+
: (change) => change;
|
|
70
|
+
handleChange = async (e) => {
|
|
71
|
+
// while we are iterating, we might get new documents.. so this method inserts them where they should be
|
|
72
|
+
let filteredChange = await mergeFunction(e.detail);
|
|
73
|
+
if (!filteredChange) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
let merged = [];
|
|
77
|
+
if (options.onChange?.update) {
|
|
78
|
+
merged = [
|
|
79
|
+
...options.onChange.update(allRef.current, filteredChange),
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
await db.index.updateResults(allRef.current, filteredChange, options?.query || {}, options?.resolve ?? true);
|
|
84
|
+
const expectedDiff = filteredChange.added.length -
|
|
85
|
+
filteredChange.removed.length;
|
|
86
|
+
if (merged === allRef.current ||
|
|
87
|
+
(expectedDiff !== 0 &&
|
|
88
|
+
merged.length === allRef.current.length)) {
|
|
89
|
+
// no change
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
logWithId(options, "handleChange", {
|
|
94
|
+
added: e.detail.added.length,
|
|
95
|
+
removed: e.detail.removed.length,
|
|
96
|
+
merged: merged.length,
|
|
97
|
+
allRef: allRef.current.length,
|
|
98
|
+
});
|
|
99
|
+
updateAll(options?.reverse ? merged.reverse() : merged);
|
|
100
|
+
};
|
|
101
|
+
db.events.addEventListener("change", handleChange);
|
|
102
|
+
}
|
|
103
|
+
return () => {
|
|
104
|
+
handleChange &&
|
|
105
|
+
db.events.removeEventListener("change", handleChange);
|
|
106
|
+
reset();
|
|
107
|
+
};
|
|
108
|
+
}, [
|
|
109
|
+
db?.closed ? undefined : db?.address,
|
|
110
|
+
options?.id ? options?.id : options?.query,
|
|
111
|
+
options?.resolve,
|
|
112
|
+
]);
|
|
113
|
+
// Define the loadMore function
|
|
114
|
+
const batchSize = options?.batchSize ?? 10;
|
|
115
|
+
const loadMore = async () => {
|
|
116
|
+
if (!iteratorRef.current ||
|
|
117
|
+
emptyResultsRef.current ||
|
|
118
|
+
iteratorRef.current.iterator.done() ||
|
|
119
|
+
loadingMoreRef.current) {
|
|
120
|
+
logWithId(options, "loadMore: already loading or no more items", {
|
|
121
|
+
isLoading,
|
|
122
|
+
emptyResultsRef: emptyResultsRef.current,
|
|
123
|
+
iteratorRef: !iteratorRef.current,
|
|
124
|
+
});
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const iterator = iteratorRef.current;
|
|
128
|
+
setIsLoading(true);
|
|
129
|
+
loadingMoreRef.current = true;
|
|
130
|
+
try {
|
|
131
|
+
// Fetch next batchSize number of items:
|
|
132
|
+
await db?.log.waitForReplicators({ timeout: 1e4 });
|
|
133
|
+
logWithId(options, "loadMore: loading more items for iterator" +
|
|
134
|
+
iteratorRef.current?.id);
|
|
135
|
+
let newItems = await iterator.iterator.next(batchSize);
|
|
136
|
+
if (options?.transform) {
|
|
137
|
+
newItems = await Promise.all(newItems.map((item) => options.transform(item)));
|
|
138
|
+
}
|
|
139
|
+
if (iteratorRef.current !== iterator) {
|
|
140
|
+
// If the iterator has changed, we should not update the state
|
|
141
|
+
// This can happen if the iterator was closed and a new one was created
|
|
142
|
+
logWithId(options, "Iterator ref changed, not updating state", {
|
|
143
|
+
refBefore: iterator.id,
|
|
144
|
+
currentRef: iteratorRef.current?.id,
|
|
145
|
+
});
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
emptyResultsRef.current = newItems.length === 0;
|
|
149
|
+
if (newItems.length > 0) {
|
|
150
|
+
let prev = allRef.current;
|
|
151
|
+
let prevHash = new Set(prev.map((x) => x.__context.head));
|
|
152
|
+
let newItemsNoHash = newItems.filter((x) => !prevHash.has(x.__context.head));
|
|
153
|
+
if (newItemsNoHash.length === 0) {
|
|
154
|
+
logWithId(options, "no new items after dedup, not updating state. Prev length", prev.length);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const combined = options?.reverse
|
|
158
|
+
? [...newItemsNoHash.reverse(), ...prev]
|
|
159
|
+
: [...prev, ...newItemsNoHash];
|
|
160
|
+
updateAll(combined);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
logWithId(options, "no new items, not updating state for iterator" +
|
|
164
|
+
iteratorRef.current?.id);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
if (error instanceof ClosedError) {
|
|
169
|
+
// Handle closed database gracefully
|
|
170
|
+
logWithId(options, "Database closed error");
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
setIsLoading(false);
|
|
178
|
+
loadingMoreRef.current = false;
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
return { items: all, loadMore, isLoading, empty: emptyResultsRef.current };
|
|
182
|
+
};
|
|
183
|
+
//# sourceMappingURL=useQuery.js.map
|
|
@@ -0,0 +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;AACpD,OAAO,EACH,WAAW,GAKd,MAAM,mBAAmB,CAAC;AAS3B,MAAM,SAAS,GAAG,CACd,OAAyD,EACzD,GAAG,IAAW,EAChB,EAAE;IACA,IAAI,CAAC,OAAO,EAAE,KAAK;QAAE,OAAO;IAE5B,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,CAAC;SAAM,IAAI,OAAO,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IAC3C,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAMpB,EAAoB,EACpB,OA2BgB,EAClB,EAAE;IACA,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAoB,EAAE,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAoB,EAAE,CAAC,CAAC;IAC7C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,WAAW,GAAG,MAAM,CAGhB,IAAI,CAAC,CAAC;IAChB,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEtC,MAAM,SAAS,GAAG,CAAC,QAA2B,EAAE,EAAE;QAC9C,SAAS,CACL,OAAO,EACP,yCAAyC,EACzC,QAAQ,CAAC,MAAM,CAClB,CAAC;QAEF,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC;QAE1B,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,GAAG,EAAE;QACf,eAAe,CAAC,OAAO,GAAG,KAAK,CAAC;QAChC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE;YAChC,WAAW,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC3C,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAC3B,MAAM,CAAC,EAAE,CAAC,CAAC;QACX,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,cAAc,CAAC,OAAO,GAAG,KAAK,CAAC;QAC/B,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC;IACxB,CAAC,CAAC;IAEF,0DAA0D;IAC1D,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,IAAI,OAAO,EAAE,KAAK,KAAK,IAAI,EAAE,CAAC;YAC9C,KAAK,EAAE,CAAC;YACR,OAAO;QACX,CAAC;QACD,MAAM,YAAY,GAAG,GAAG,EAAE;YACtB,qEAAqE;YACrE,IAAI,CAAC;gBACD,kDAAkD;gBAElD,eAAe,CAAC,OAAO,GAAG,KAAK,CAAC;gBAChC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACtC,WAAW,CAAC,OAAO,GAAG;oBAClB,EAAE,EAAE,OAAO,EAAE,EAAE;oBACf,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,EAAE;wBAC7C,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI;wBAC7B,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,IAAI;wBAC/B,OAAO,EAAE,OAAO,EAAE,OAAc;qBACnC,CAA4C;iBAChD,CAAC;gBAEF,SAAS,CAAC,OAAO,EAAE,uBAAuB,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;gBAEzD,QAAQ,EAAE,CAAC,CAAC,eAAe;YAC/B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;YACxD,CAAC;QACL,CAAC,CAAC;QAEF,4CAA4C;QAC5C,KAAK,EAAE,CAAC;QACR,YAAY,EAAE,CAAC;QAEf,IAAI,YAAY,GAGZ,SAAS,CAAC;QACd,IAAI,OAAO,EAAE,QAAQ,EAAE,CAAC;YACpB,IAAI,aAAa,GACb,OAAO,OAAO,CAAC,QAAQ,CAAC,KAAK,KAAK,UAAU;gBACxC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK;gBACxB,CAAC,CAAC,CAAC,MAA0B,EAAE,EAAE,CAAC,MAAM,CAAC;YACjD,YAAY,GAAG,KAAK,EAAE,CAAkC,EAAE,EAAE;gBACxD,wGAAwG;gBAExG,IAAI,cAAc,GAAG,MAAM,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBACnD,IAAI,CAAC,cAAc,EAAE,CAAC;oBAClB,OAAO;gBACX,CAAC;gBACD,IAAI,MAAM,GAAsB,EAAE,CAAC;gBACnC,IAAI,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;oBAC3B,MAAM,GAAG;wBACL,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CACtB,MAAM,CAAC,OAAO,EACd,cAAc,CACjB;qBACJ,CAAC;gBACN,CAAC;qBAAM,CAAC;oBACJ,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CACxB,MAAM,CAAC,OAAO,EACd,cAAc,EACd,OAAO,EAAE,KAAK,IAAI,EAAE,EACpB,OAAO,EAAE,OAAO,IAAI,IAAI,CAC3B,CAAC;oBACF,MAAM,YAAY,GACd,cAAc,CAAC,KAAK,CAAC,MAAM;wBAC3B,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;oBAElC,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,OAAO;oBACX,CAAC;gBACL,CAAC;gBAED,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE;oBAC/B,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM;oBAC5B,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM;oBAChC,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;iBAChC,CAAC,CAAC;gBAEH,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC5D,CAAC,CAAC;YACF,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,EAAE,CAAC;QACZ,CAAC,CAAC;IACN,CAAC,EAAE;QACC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO;QACpC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK;QAC1C,OAAO,EAAE,OAAO;KACnB,CAAC,CAAC;IAEH,+BAA+B;IAC/B,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QACxB,IACI,CAAC,WAAW,CAAC,OAAO;YACpB,eAAe,CAAC,OAAO;YACvB,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE;YACnC,cAAc,CAAC,OAAO,EACxB,CAAC;YACC,SAAS,CAAC,OAAO,EAAE,4CAA4C,EAAE;gBAC7D,SAAS;gBACT,eAAe,EAAE,eAAe,CAAC,OAAO;gBACxC,WAAW,EAAE,CAAC,WAAW,CAAC,OAAO;aACpC,CAAC,CAAC;YACH,OAAO;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC;QAErC,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC;YACD,wCAAwC;YACxC,MAAM,EAAE,EAAE,GAAG,CAAC,kBAAkB,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;YACnD,SAAS,CACL,OAAO,EACP,2CAA2C;gBACvC,WAAW,CAAC,OAAO,EAAE,EAAE,CAC9B,CAAC;YACF,IAAI,QAAQ,GAAsB,MAAM,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAC1D,SAAS,CACZ,CAAC;YAEF,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;gBACrB,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CACxB,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,SAAU,CAAC,IAAI,CAAC,CAAC,CACnD,CAAC;YACN,CAAC;YAED,IAAI,WAAW,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACnC,8DAA8D;gBAC9D,uEAAuE;gBACvE,SAAS,CAAC,OAAO,EAAE,0CAA0C,EAAE;oBAC3D,SAAS,EAAE,QAAQ,CAAC,EAAE;oBACtB,UAAU,EAAE,WAAW,CAAC,OAAO,EAAE,EAAE;iBACtC,CAAC,CAAC;gBACH,OAAO;YACX,CAAC;YAED,eAAe,CAAC,OAAO,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;YAEhD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,IAAI,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC;gBAC1B,IAAI,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC1D,IAAI,cAAc,GAAG,QAAQ,CAAC,MAAM,CAChC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CACzC,CAAC;gBACF,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC9B,SAAS,CACL,OAAO,EACP,2DAA2D,EAC3D,IAAI,CAAC,MAAM,CACd,CAAC;oBACF,OAAO;gBACX,CAAC;gBACD,MAAM,QAAQ,GAAG,OAAO,EAAE,OAAO;oBAC7B,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC;oBACxC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,cAAc,CAAC,CAAC;gBACnC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACJ,SAAS,CACL,OAAO,EACP,+CAA+C;oBAC3C,WAAW,CAAC,OAAO,EAAE,EAAE,CAC9B,CAAC;YACN,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;gBAC/B,oCAAoC;gBACpC,SAAS,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;YAChD,CAAC;iBAAM,CAAC;gBACJ,MAAM,KAAK,CAAC;YAChB,CAAC;QACL,CAAC;gBAAS,CAAC;YACP,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,cAAc,CAAC,OAAO,GAAG,KAAK,CAAC;QACnC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,EAAE,CAAC;AAC/E,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.17",
|
|
4
4
|
"homepage": "https://dao-xyz.github.io/peerbit-examples",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"peerbit": "^4",
|
|
35
35
|
"react": "^18.2.0",
|
|
36
36
|
"react-dom": "^18.2.0",
|
|
37
|
-
"react-router
|
|
37
|
+
"react-router": "^7.5.0",
|
|
38
38
|
"react-use": "^17.4.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"last 1 safari version"
|
|
71
71
|
]
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "c4149e8b5ca79dd06303ecb206878ab48b74e61e"
|
|
74
74
|
}
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./utils.js";
|
|
|
8
8
|
export { FastMutex } from "./lockstorage.js";
|
|
9
9
|
export { useProgram } from "./useProgram.js";
|
|
10
10
|
export { useLocal } from "./useLocal.js";
|
|
11
|
+
export { useQuery as useQuery } from "./useQuery.js";
|
|
11
12
|
export { useOnline } from "./useOnline.js";
|
|
12
13
|
export { useCount } from "./useCount.js";
|
|
13
14
|
export { debounceLeadingTrailing } from "./utils.js";
|
package/src/useLocal.tsx
CHANGED
|
@@ -12,6 +12,19 @@ type QueryOptons = {
|
|
|
12
12
|
id: string;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
const logWithId = (
|
|
16
|
+
options: { debug?: boolean | { id: string } } | undefined,
|
|
17
|
+
...args: any[]
|
|
18
|
+
) => {
|
|
19
|
+
if (!options?.debug) return;
|
|
20
|
+
|
|
21
|
+
if (typeof options.debug === "boolean") {
|
|
22
|
+
console.log(...args);
|
|
23
|
+
} else if (typeof options.debug.id === "string") {
|
|
24
|
+
console.log(options.debug.id, ...args);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
15
28
|
export const useLocal = <
|
|
16
29
|
T extends Record<string, any>,
|
|
17
30
|
I extends Record<string, any>,
|
|
@@ -24,17 +37,28 @@ export const useLocal = <
|
|
|
24
37
|
transform?: (result: RT) => Promise<RT>;
|
|
25
38
|
onChanges?: (all: RT[]) => void;
|
|
26
39
|
debounce?: number;
|
|
27
|
-
debug?: boolean
|
|
40
|
+
debug?: boolean | { id: string };
|
|
28
41
|
} & QueryOptons
|
|
29
42
|
) => {
|
|
30
43
|
const [all, setAll] = useState<RT[]>([]);
|
|
31
44
|
const emptyResultsRef = useRef(false);
|
|
32
45
|
|
|
33
46
|
useEffect(() => {
|
|
34
|
-
if (!db || db.closed) {
|
|
47
|
+
if (!db || db.closed || options?.query === null) {
|
|
48
|
+
// null query means no query at all
|
|
35
49
|
return;
|
|
36
50
|
}
|
|
37
51
|
|
|
52
|
+
logWithId(
|
|
53
|
+
options,
|
|
54
|
+
"reset local",
|
|
55
|
+
db?.closed ? undefined : db?.rootAddress,
|
|
56
|
+
options?.id,
|
|
57
|
+
options?.resolve,
|
|
58
|
+
options?.onChanges,
|
|
59
|
+
options?.transform
|
|
60
|
+
);
|
|
61
|
+
|
|
38
62
|
const _l = async (args?: any) => {
|
|
39
63
|
try {
|
|
40
64
|
const iterator = db.index.iterate(options?.query ?? {}, {
|
|
@@ -50,6 +74,14 @@ export const useLocal = <
|
|
|
50
74
|
results.map((x) => options.transform!(x))
|
|
51
75
|
);
|
|
52
76
|
}
|
|
77
|
+
logWithId(
|
|
78
|
+
options,
|
|
79
|
+
options?.id,
|
|
80
|
+
results,
|
|
81
|
+
"query",
|
|
82
|
+
options?.query
|
|
83
|
+
);
|
|
84
|
+
|
|
53
85
|
emptyResultsRef.current = results.length === 0;
|
|
54
86
|
setAll(() => {
|
|
55
87
|
options?.onChanges?.(results);
|
|
@@ -63,14 +95,7 @@ export const useLocal = <
|
|
|
63
95
|
}
|
|
64
96
|
};
|
|
65
97
|
|
|
66
|
-
const debounced = debounceLeadingTrailing(
|
|
67
|
-
_l,
|
|
68
|
-
options?.debounce ?? 1000
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
let ts = setTimeout(() => {
|
|
72
|
-
_l();
|
|
73
|
-
}, 3000);
|
|
98
|
+
const debounced = debounceLeadingTrailing(_l, options?.debounce ?? 123);
|
|
74
99
|
|
|
75
100
|
const handleChange = () => {
|
|
76
101
|
if (emptyResultsRef.current) {
|
|
@@ -87,7 +112,6 @@ export const useLocal = <
|
|
|
87
112
|
return () => {
|
|
88
113
|
db.events.removeEventListener("change", handleChange);
|
|
89
114
|
debounced.cancel();
|
|
90
|
-
clearTimeout(ts);
|
|
91
115
|
};
|
|
92
116
|
}, [
|
|
93
117
|
db?.closed ? undefined : db?.rootAddress,
|
package/src/usePeer.tsx
CHANGED
|
@@ -24,6 +24,11 @@ import { circuitRelayTransport } from "@libp2p/circuit-relay-v2";
|
|
|
24
24
|
import * as filters from "@libp2p/websockets/filters";
|
|
25
25
|
import { detectIncognito } from "detectincognitojs";
|
|
26
26
|
|
|
27
|
+
const isInStandaloneMode = () =>
|
|
28
|
+
window.matchMedia("(display-mode: standalone)").matches ||
|
|
29
|
+
window.navigator["standalone"] ||
|
|
30
|
+
document.referrer.includes("android-app://");
|
|
31
|
+
|
|
27
32
|
export class ClientBusyError extends Error {
|
|
28
33
|
constructor(message: string) {
|
|
29
34
|
super(message);
|
|
@@ -95,6 +100,11 @@ type WithChildren = {
|
|
|
95
100
|
};
|
|
96
101
|
type PeerOptions = (TopAndIframeOptions | TopOptions) & WithChildren;
|
|
97
102
|
|
|
103
|
+
const subscribeToUnload = (fn: () => any) => {
|
|
104
|
+
window.addEventListener("pagehide", fn);
|
|
105
|
+
window.addEventListener("beforeunload", fn);
|
|
106
|
+
};
|
|
107
|
+
|
|
98
108
|
export const PeerProvider = (options: PeerOptions) => {
|
|
99
109
|
const [peer, setPeer] = React.useState<ProgramClient | undefined>(
|
|
100
110
|
undefined
|
|
@@ -182,9 +192,13 @@ export const PeerProvider = (options: PeerOptions) => {
|
|
|
182
192
|
const localId = getClientId("local");
|
|
183
193
|
try {
|
|
184
194
|
const lockKey = localId + "-singleton";
|
|
185
|
-
|
|
195
|
+
subscribeToUnload(function () {
|
|
186
196
|
mutex.release(lockKey);
|
|
187
|
-
};
|
|
197
|
+
});
|
|
198
|
+
if (isInStandaloneMode()) {
|
|
199
|
+
// PWA issue fix (? TODO is this needed ?
|
|
200
|
+
mutex.release(lockKey);
|
|
201
|
+
}
|
|
188
202
|
await mutex.lock(lockKey, () => true, {
|
|
189
203
|
replaceIfSameClient: true,
|
|
190
204
|
});
|
|
@@ -204,9 +218,9 @@ export const PeerProvider = (options: PeerOptions) => {
|
|
|
204
218
|
releaseFirstLock,
|
|
205
219
|
releaseLockIfSameId: true,
|
|
206
220
|
});
|
|
207
|
-
|
|
221
|
+
subscribeToUnload(function () {
|
|
208
222
|
mutex.release(kp.path);
|
|
209
|
-
};
|
|
223
|
+
});
|
|
210
224
|
nodeId = kp.key;
|
|
211
225
|
setTabIndex(kp.index);
|
|
212
226
|
}
|
package/src/useQuery.tsx
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { useState, useEffect, useRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
ClosedError,
|
|
4
|
+
Documents,
|
|
5
|
+
DocumentsChange,
|
|
6
|
+
ResultsIterator,
|
|
7
|
+
WithContext,
|
|
8
|
+
} from "@peerbit/document";
|
|
9
|
+
import * as indexerTypes from "@peerbit/indexer-interface";
|
|
10
|
+
|
|
11
|
+
type QueryLike = {
|
|
12
|
+
query?: indexerTypes.Query[] | indexerTypes.QueryLike;
|
|
13
|
+
sort?: indexerTypes.Sort[] | indexerTypes.Sort | indexerTypes.SortLike;
|
|
14
|
+
};
|
|
15
|
+
type QueryOptions = { query: QueryLike; id: string };
|
|
16
|
+
|
|
17
|
+
const logWithId = (
|
|
18
|
+
options: { debug?: boolean | { id: string } } | undefined,
|
|
19
|
+
...args: any[]
|
|
20
|
+
) => {
|
|
21
|
+
if (!options?.debug) return;
|
|
22
|
+
|
|
23
|
+
if (typeof options.debug === "boolean") {
|
|
24
|
+
console.log(...args);
|
|
25
|
+
} else if (typeof options.debug.id === "string") {
|
|
26
|
+
console.log(options.debug.id, ...args);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const useQuery = <
|
|
31
|
+
T extends Record<string, any>,
|
|
32
|
+
I extends Record<string, any>,
|
|
33
|
+
R extends boolean | undefined = true,
|
|
34
|
+
RT = R extends false ? WithContext<I> : WithContext<T>
|
|
35
|
+
>(
|
|
36
|
+
db?: Documents<T, I>,
|
|
37
|
+
options?: {
|
|
38
|
+
resolve?: R;
|
|
39
|
+
transform?: (result: WithContext<RT>) => Promise<WithContext<RT>>;
|
|
40
|
+
debounce?: number;
|
|
41
|
+
debug?: boolean | { id: string };
|
|
42
|
+
reverse?: boolean;
|
|
43
|
+
batchSize?: number; // You can set a default batch size here
|
|
44
|
+
onChange?: {
|
|
45
|
+
merge?:
|
|
46
|
+
| boolean
|
|
47
|
+
| ((
|
|
48
|
+
change: DocumentsChange<T>
|
|
49
|
+
) =>
|
|
50
|
+
| DocumentsChange<T>
|
|
51
|
+
| Promise<DocumentsChange<T>>
|
|
52
|
+
| undefined); // if true, the iterator will be updated with new documents
|
|
53
|
+
update?: (
|
|
54
|
+
prev: WithContext<RT>[],
|
|
55
|
+
change: DocumentsChange<T>
|
|
56
|
+
) => WithContext<RT>[];
|
|
57
|
+
};
|
|
58
|
+
local?: boolean; // if true, (default is true) the iterator will only return local documents
|
|
59
|
+
remote?:
|
|
60
|
+
| boolean
|
|
61
|
+
| {
|
|
62
|
+
eager?: boolean;
|
|
63
|
+
};
|
|
64
|
+
} & QueryOptions
|
|
65
|
+
) => {
|
|
66
|
+
const [all, setAll] = useState<WithContext<RT>[]>([]);
|
|
67
|
+
const allRef = useRef<WithContext<RT>[]>([]);
|
|
68
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
69
|
+
const loadingMoreRef = useRef(false);
|
|
70
|
+
const iteratorRef = useRef<{
|
|
71
|
+
id?: string;
|
|
72
|
+
iterator: ResultsIterator<WithContext<RT>>;
|
|
73
|
+
} | null>(null);
|
|
74
|
+
const emptyResultsRef = useRef(false);
|
|
75
|
+
|
|
76
|
+
const updateAll = (combined: WithContext<RT>[]) => {
|
|
77
|
+
logWithId(
|
|
78
|
+
options,
|
|
79
|
+
"Loading more items, new combined length",
|
|
80
|
+
combined.length
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
allRef.current = combined;
|
|
84
|
+
|
|
85
|
+
setAll(combined);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const reset = () => {
|
|
89
|
+
emptyResultsRef.current = false;
|
|
90
|
+
iteratorRef.current?.iterator.done() &&
|
|
91
|
+
iteratorRef.current?.iterator?.close();
|
|
92
|
+
iteratorRef.current = null;
|
|
93
|
+
setAll([]);
|
|
94
|
+
setIsLoading(false);
|
|
95
|
+
loadingMoreRef.current = false;
|
|
96
|
+
allRef.current = [];
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Initialize the iterator only once or when query changes
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
if (!db || db.closed || options?.query === null) {
|
|
102
|
+
reset();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const initIterator = () => {
|
|
106
|
+
// Don't make this async, it will cause issues with the iterator refs
|
|
107
|
+
try {
|
|
108
|
+
// Initialize the iterator and load initial batch.
|
|
109
|
+
|
|
110
|
+
emptyResultsRef.current = false;
|
|
111
|
+
iteratorRef.current?.iterator.close();
|
|
112
|
+
iteratorRef.current = {
|
|
113
|
+
id: options?.id,
|
|
114
|
+
iterator: db.index.iterate(options?.query ?? {}, {
|
|
115
|
+
local: options?.local ?? true,
|
|
116
|
+
remote: options?.remote ?? true,
|
|
117
|
+
resolve: options?.resolve as any,
|
|
118
|
+
}) as any as ResultsIterator<WithContext<RT>>,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
logWithId(options, "Initializing iterator", options?.id);
|
|
122
|
+
|
|
123
|
+
loadMore(); // initial load
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error("Error initializing iterator", error);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// Reset state when the db or query changes.
|
|
130
|
+
reset();
|
|
131
|
+
initIterator();
|
|
132
|
+
|
|
133
|
+
let handleChange:
|
|
134
|
+
| undefined
|
|
135
|
+
| ((e: CustomEvent<DocumentsChange<T>>) => void | Promise<void>) =
|
|
136
|
+
undefined;
|
|
137
|
+
if (options?.onChange) {
|
|
138
|
+
let mergeFunction =
|
|
139
|
+
typeof options.onChange.merge === "function"
|
|
140
|
+
? options.onChange.merge
|
|
141
|
+
: (change: DocumentsChange<T>) => change;
|
|
142
|
+
handleChange = async (e: CustomEvent<DocumentsChange<T>>) => {
|
|
143
|
+
// while we are iterating, we might get new documents.. so this method inserts them where they should be
|
|
144
|
+
|
|
145
|
+
let filteredChange = await mergeFunction(e.detail);
|
|
146
|
+
if (!filteredChange) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
let merged: WithContext<RT>[] = [];
|
|
150
|
+
if (options.onChange?.update) {
|
|
151
|
+
merged = [
|
|
152
|
+
...options.onChange.update(
|
|
153
|
+
allRef.current,
|
|
154
|
+
filteredChange
|
|
155
|
+
),
|
|
156
|
+
];
|
|
157
|
+
} else {
|
|
158
|
+
await db.index.updateResults(
|
|
159
|
+
allRef.current,
|
|
160
|
+
filteredChange,
|
|
161
|
+
options?.query || {},
|
|
162
|
+
options?.resolve ?? true
|
|
163
|
+
);
|
|
164
|
+
const expectedDiff =
|
|
165
|
+
filteredChange.added.length -
|
|
166
|
+
filteredChange.removed.length;
|
|
167
|
+
|
|
168
|
+
if (
|
|
169
|
+
merged === allRef.current ||
|
|
170
|
+
(expectedDiff !== 0 &&
|
|
171
|
+
merged.length === allRef.current.length)
|
|
172
|
+
) {
|
|
173
|
+
// no change
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
logWithId(options, "handleChange", {
|
|
179
|
+
added: e.detail.added.length,
|
|
180
|
+
removed: e.detail.removed.length,
|
|
181
|
+
merged: merged.length,
|
|
182
|
+
allRef: allRef.current.length,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
updateAll(options?.reverse ? merged.reverse() : merged);
|
|
186
|
+
};
|
|
187
|
+
db.events.addEventListener("change", handleChange);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return () => {
|
|
191
|
+
handleChange &&
|
|
192
|
+
db.events.removeEventListener("change", handleChange);
|
|
193
|
+
reset();
|
|
194
|
+
};
|
|
195
|
+
}, [
|
|
196
|
+
db?.closed ? undefined : db?.address,
|
|
197
|
+
options?.id ? options?.id : options?.query,
|
|
198
|
+
options?.resolve,
|
|
199
|
+
]);
|
|
200
|
+
|
|
201
|
+
// Define the loadMore function
|
|
202
|
+
const batchSize = options?.batchSize ?? 10;
|
|
203
|
+
const loadMore = async () => {
|
|
204
|
+
if (
|
|
205
|
+
!iteratorRef.current ||
|
|
206
|
+
emptyResultsRef.current ||
|
|
207
|
+
iteratorRef.current.iterator.done() ||
|
|
208
|
+
loadingMoreRef.current
|
|
209
|
+
) {
|
|
210
|
+
logWithId(options, "loadMore: already loading or no more items", {
|
|
211
|
+
isLoading,
|
|
212
|
+
emptyResultsRef: emptyResultsRef.current,
|
|
213
|
+
iteratorRef: !iteratorRef.current,
|
|
214
|
+
});
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const iterator = iteratorRef.current;
|
|
218
|
+
|
|
219
|
+
setIsLoading(true);
|
|
220
|
+
loadingMoreRef.current = true;
|
|
221
|
+
try {
|
|
222
|
+
// Fetch next batchSize number of items:
|
|
223
|
+
await db?.log.waitForReplicators({ timeout: 1e4 });
|
|
224
|
+
logWithId(
|
|
225
|
+
options,
|
|
226
|
+
"loadMore: loading more items for iterator" +
|
|
227
|
+
iteratorRef.current?.id
|
|
228
|
+
);
|
|
229
|
+
let newItems: WithContext<RT>[] = await iterator.iterator.next(
|
|
230
|
+
batchSize
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
if (options?.transform) {
|
|
234
|
+
newItems = await Promise.all(
|
|
235
|
+
newItems.map((item) => options.transform!(item))
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (iteratorRef.current !== iterator) {
|
|
240
|
+
// If the iterator has changed, we should not update the state
|
|
241
|
+
// This can happen if the iterator was closed and a new one was created
|
|
242
|
+
logWithId(options, "Iterator ref changed, not updating state", {
|
|
243
|
+
refBefore: iterator.id,
|
|
244
|
+
currentRef: iteratorRef.current?.id,
|
|
245
|
+
});
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
emptyResultsRef.current = newItems.length === 0;
|
|
250
|
+
|
|
251
|
+
if (newItems.length > 0) {
|
|
252
|
+
let prev = allRef.current;
|
|
253
|
+
let prevHash = new Set(prev.map((x) => x.__context.head));
|
|
254
|
+
let newItemsNoHash = newItems.filter(
|
|
255
|
+
(x) => !prevHash.has(x.__context.head)
|
|
256
|
+
);
|
|
257
|
+
if (newItemsNoHash.length === 0) {
|
|
258
|
+
logWithId(
|
|
259
|
+
options,
|
|
260
|
+
"no new items after dedup, not updating state. Prev length",
|
|
261
|
+
prev.length
|
|
262
|
+
);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const combined = options?.reverse
|
|
266
|
+
? [...newItemsNoHash.reverse(), ...prev]
|
|
267
|
+
: [...prev, ...newItemsNoHash];
|
|
268
|
+
updateAll(combined);
|
|
269
|
+
} else {
|
|
270
|
+
logWithId(
|
|
271
|
+
options,
|
|
272
|
+
"no new items, not updating state for iterator" +
|
|
273
|
+
iteratorRef.current?.id
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
} catch (error) {
|
|
277
|
+
if (error instanceof ClosedError) {
|
|
278
|
+
// Handle closed database gracefully
|
|
279
|
+
logWithId(options, "Database closed error");
|
|
280
|
+
} else {
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
} finally {
|
|
284
|
+
setIsLoading(false);
|
|
285
|
+
loadingMoreRef.current = false;
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
return { items: all, loadMore, isLoading, empty: emptyResultsRef.current };
|
|
290
|
+
};
|