@rpcbase/client 0.382.0 → 0.384.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -15
- package/dist/index.js.map +1 -1
- package/dist/rts/index.d.ts +2 -2
- package/dist/rts/index.d.ts.map +1 -1
- package/dist/rts/index.js +8 -6
- package/dist/rts/queryKey.d.ts.map +1 -1
- package/dist/rts/ssrHydration.d.ts +4 -0
- package/dist/rts/ssrHydration.d.ts.map +1 -1
- package/dist/rts/useQuery.d.ts +5 -0
- package/dist/rts/useQuery.d.ts.map +1 -1
- package/dist/rts/wsClient.d.ts +12 -0
- package/dist/rts/wsClient.d.ts.map +1 -1
- package/dist/{useQuery-CalZ2p2a.js → useQuery-Ce_EmI2F.js} +353 -24
- package/dist/useQuery-Ce_EmI2F.js.map +1 -0
- package/package.json +2 -2
- package/dist/useQuery-CalZ2p2a.js.map +0 -1
|
@@ -3,12 +3,26 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
const STATIC_RPCBASE_RTS_HYDRATION_DATA_KEY = "__staticRpcbaseRtsHydrationData";
|
|
4
4
|
const RtsSsrRuntimeContext = createContext(null);
|
|
5
5
|
const hydrationDataStore = /* @__PURE__ */ new Map();
|
|
6
|
+
const hydrationPageInfoStore = /* @__PURE__ */ new Map();
|
|
6
7
|
const makeStoreKey = (modelName, queryKey) => `${modelName}.${queryKey}`;
|
|
7
8
|
const normalizeStringOrNull = (value) => {
|
|
8
9
|
if (typeof value !== "string") return null;
|
|
9
10
|
const normalized = value.trim();
|
|
10
11
|
return normalized ? normalized : null;
|
|
11
12
|
};
|
|
13
|
+
const normalizePageInfo$2 = (value) => {
|
|
14
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
15
|
+
const raw = value;
|
|
16
|
+
if (typeof raw.hasNextPage !== "boolean" || typeof raw.hasPrevPage !== "boolean") return void 0;
|
|
17
|
+
const nextCursor = typeof raw.nextCursor === "string" && raw.nextCursor ? raw.nextCursor : void 0;
|
|
18
|
+
const prevCursor = typeof raw.prevCursor === "string" && raw.prevCursor ? raw.prevCursor : void 0;
|
|
19
|
+
return {
|
|
20
|
+
hasNextPage: raw.hasNextPage,
|
|
21
|
+
hasPrevPage: raw.hasPrevPage,
|
|
22
|
+
...nextCursor ? { nextCursor } : {},
|
|
23
|
+
...prevCursor ? { prevCursor } : {}
|
|
24
|
+
};
|
|
25
|
+
};
|
|
12
26
|
const parseHydrationData = (value) => {
|
|
13
27
|
if (!value || typeof value !== "object") return null;
|
|
14
28
|
const raw = value;
|
|
@@ -22,10 +36,12 @@ const parseHydrationData = (value) => {
|
|
|
22
36
|
const queryKey = normalizeStringOrNull(query.queryKey);
|
|
23
37
|
if (!modelName || !queryKey) continue;
|
|
24
38
|
if (!Array.isArray(query.data)) continue;
|
|
39
|
+
const pageInfo = normalizePageInfo$2(query.pageInfo);
|
|
25
40
|
queries.push({
|
|
26
41
|
modelName,
|
|
27
42
|
queryKey,
|
|
28
|
-
data: query.data
|
|
43
|
+
data: query.data,
|
|
44
|
+
...pageInfo ? { pageInfo } : {}
|
|
29
45
|
});
|
|
30
46
|
}
|
|
31
47
|
return {
|
|
@@ -43,18 +59,26 @@ const hydrateRtsFromWindow = () => {
|
|
|
43
59
|
const parsed = parseHydrationData(raw);
|
|
44
60
|
if (!parsed) return;
|
|
45
61
|
hydrationDataStore.clear();
|
|
62
|
+
hydrationPageInfoStore.clear();
|
|
46
63
|
for (const query of parsed.queries) {
|
|
47
64
|
hydrationDataStore.set(makeStoreKey(query.modelName, query.queryKey), query.data);
|
|
65
|
+
hydrationPageInfoStore.set(makeStoreKey(query.modelName, query.queryKey), query.pageInfo);
|
|
48
66
|
}
|
|
49
67
|
};
|
|
50
68
|
const peekHydratedRtsQueryData = (modelName, queryKey) => {
|
|
51
69
|
return hydrationDataStore.get(makeStoreKey(modelName, queryKey));
|
|
52
70
|
};
|
|
71
|
+
const peekHydratedRtsQueryPageInfo = (modelName, queryKey) => {
|
|
72
|
+
return hydrationPageInfoStore.get(makeStoreKey(modelName, queryKey));
|
|
73
|
+
};
|
|
53
74
|
const consumeHydratedRtsQueryData = (modelName, queryKey) => {
|
|
54
|
-
|
|
75
|
+
const key = makeStoreKey(modelName, queryKey);
|
|
76
|
+
hydrationDataStore.delete(key);
|
|
77
|
+
hydrationPageInfoStore.delete(key);
|
|
55
78
|
};
|
|
56
79
|
const clearHydratedRtsQueryData = () => {
|
|
57
80
|
hydrationDataStore.clear();
|
|
81
|
+
hydrationPageInfoStore.clear();
|
|
58
82
|
};
|
|
59
83
|
const RtsSsrRuntimeProvider = ({
|
|
60
84
|
value,
|
|
@@ -394,7 +418,8 @@ const computeRtsQueryKey = (query, options) => {
|
|
|
394
418
|
const sort = options.sort ? JSON.stringify(options.sort) : "";
|
|
395
419
|
const limit = typeof options.limit === "number" ? String(options.limit) : "";
|
|
396
420
|
const populate = options.populate ? JSON.stringify(options.populate) : "";
|
|
397
|
-
|
|
421
|
+
const pagination = options.pagination ? JSON.stringify(options.pagination) : "";
|
|
422
|
+
return `${key}${JSON.stringify(query)}${projection}${sort}${limit}${populate}${pagination}`;
|
|
398
423
|
};
|
|
399
424
|
const TENANT_ID_QUERY_PARAM = "rb-tenant-id";
|
|
400
425
|
const RTS_CHANGES_ROUTE = "/api/rb/rts/changes";
|
|
@@ -488,15 +513,31 @@ const isDocWithId = (doc) => {
|
|
|
488
513
|
if (!doc || typeof doc !== "object") return false;
|
|
489
514
|
return typeof doc._id === "string";
|
|
490
515
|
};
|
|
516
|
+
const normalizePageInfo$1 = (value) => {
|
|
517
|
+
if (!value || typeof value !== "object") return void 0;
|
|
518
|
+
if (Array.isArray(value)) return void 0;
|
|
519
|
+
const raw = value;
|
|
520
|
+
if (typeof raw.hasNextPage !== "boolean" || typeof raw.hasPrevPage !== "boolean") return void 0;
|
|
521
|
+
const nextCursor = typeof raw.nextCursor === "string" && raw.nextCursor ? raw.nextCursor : void 0;
|
|
522
|
+
const prevCursor = typeof raw.prevCursor === "string" && raw.prevCursor ? raw.prevCursor : void 0;
|
|
523
|
+
return {
|
|
524
|
+
hasNextPage: raw.hasNextPage,
|
|
525
|
+
hasPrevPage: raw.hasPrevPage,
|
|
526
|
+
...nextCursor ? { nextCursor } : {},
|
|
527
|
+
...prevCursor ? { prevCursor } : {}
|
|
528
|
+
};
|
|
529
|
+
};
|
|
491
530
|
const handleQueryPayload = (payload) => {
|
|
492
531
|
const { modelName, queryKey, data, error, txnId } = payload;
|
|
493
532
|
const cbKey = `${modelName}.${queryKey}`;
|
|
494
533
|
const callbacks = queryCallbacks.get(cbKey);
|
|
495
534
|
if (!callbacks || !callbacks.size) return;
|
|
496
535
|
const subscription = subscriptions.get(cbKey);
|
|
536
|
+
const pageInfo = normalizePageInfo$1(payload.pageInfo);
|
|
497
537
|
const hasPopulate = Boolean(subscription?.options?.populate);
|
|
538
|
+
const hasPagination = Boolean(subscription?.options?.pagination || pageInfo);
|
|
498
539
|
const isLocal = !!(txnId && localTxnBuf.includes(txnId));
|
|
499
|
-
const context = { source: "network", isLocal, txnId };
|
|
540
|
+
const context = { source: "network", isLocal, txnId, ...pageInfo ? { pageInfo } : {} };
|
|
500
541
|
if (error) {
|
|
501
542
|
for (const cb of callbacks) cb(error, void 0, context);
|
|
502
543
|
return;
|
|
@@ -506,6 +547,7 @@ const handleQueryPayload = (payload) => {
|
|
|
506
547
|
const docs = Array.isArray(data) ? data.filter(isDocWithId) : [];
|
|
507
548
|
if (!docs.length) return;
|
|
508
549
|
if (hasPopulate) return;
|
|
550
|
+
if (hasPagination) return;
|
|
509
551
|
void updateDocs(modelName, docs, currentUid).catch(() => {
|
|
510
552
|
});
|
|
511
553
|
};
|
|
@@ -750,11 +792,12 @@ const registerQuery = (modelName, query, optionsOrCallback, callbackMaybe, behav
|
|
|
750
792
|
const runInitialNetworkQuery = behavior?.runInitialNetworkQuery !== false;
|
|
751
793
|
const runInitialLocalQuery = behavior?.runInitialLocalQuery !== false;
|
|
752
794
|
const hasPopulate = Boolean(options.populate);
|
|
795
|
+
const hasPagination = Boolean(options.pagination);
|
|
753
796
|
const set = queryCallbacks.get(cbKey) ?? /* @__PURE__ */ new Set();
|
|
754
797
|
set.add(callback);
|
|
755
798
|
queryCallbacks.set(cbKey, set);
|
|
756
799
|
subscriptions.set(cbKey, { modelName, query, options, queryKey, runInitialNetworkQuery });
|
|
757
|
-
if (currentUid && runInitialLocalQuery && !hasPopulate) {
|
|
800
|
+
if (currentUid && runInitialLocalQuery && !hasPopulate && !hasPagination) {
|
|
758
801
|
void runQuery({
|
|
759
802
|
modelName,
|
|
760
803
|
query,
|
|
@@ -780,6 +823,57 @@ const registerQuery = (modelName, query, optionsOrCallback, callbackMaybe, behav
|
|
|
780
823
|
}
|
|
781
824
|
};
|
|
782
825
|
};
|
|
826
|
+
const makeRunQueryKey = () => `run-query.${Date.now().toString(36)}.${Math.random().toString(36).slice(2, 10)}`;
|
|
827
|
+
const runNetworkQuery = async ({
|
|
828
|
+
modelName,
|
|
829
|
+
query,
|
|
830
|
+
options = {},
|
|
831
|
+
timeoutMs = 1e4
|
|
832
|
+
}) => {
|
|
833
|
+
if (typeof modelName !== "string" || modelName.trim().length === 0) {
|
|
834
|
+
throw new Error("runNetworkQuery: modelName must be a non-empty string");
|
|
835
|
+
}
|
|
836
|
+
if (!socket || socket.readyState !== WebSocket.OPEN) {
|
|
837
|
+
throw new Error("runNetworkQuery: RTS socket is not connected");
|
|
838
|
+
}
|
|
839
|
+
const resolvedOptions = options.key ? options : { ...options, key: makeRunQueryKey() };
|
|
840
|
+
const queryKey = computeRtsQueryKey(query, resolvedOptions);
|
|
841
|
+
const cbKey = `${modelName}.${queryKey}`;
|
|
842
|
+
return await new Promise((resolve, reject) => {
|
|
843
|
+
let settled = false;
|
|
844
|
+
let timeoutId = null;
|
|
845
|
+
const cleanup = () => {
|
|
846
|
+
const callbacks2 = queryCallbacks.get(cbKey);
|
|
847
|
+
callbacks2?.delete(callback);
|
|
848
|
+
if (callbacks2 && callbacks2.size === 0) queryCallbacks.delete(cbKey);
|
|
849
|
+
if (timeoutId !== null && typeof window !== "undefined") {
|
|
850
|
+
window.clearTimeout(timeoutId);
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
const settle = (next) => {
|
|
854
|
+
if (settled) return;
|
|
855
|
+
settled = true;
|
|
856
|
+
cleanup();
|
|
857
|
+
next();
|
|
858
|
+
};
|
|
859
|
+
const callback = (error, data, context) => {
|
|
860
|
+
if (error) {
|
|
861
|
+
settle(() => reject(error));
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
settle(() => resolve({ data, context }));
|
|
865
|
+
};
|
|
866
|
+
const callbacks = queryCallbacks.get(cbKey) ?? /* @__PURE__ */ new Set();
|
|
867
|
+
callbacks.add(callback);
|
|
868
|
+
queryCallbacks.set(cbKey, callbacks);
|
|
869
|
+
if (typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0) {
|
|
870
|
+
timeoutId = window.setTimeout(() => {
|
|
871
|
+
settle(() => reject(new Error("runNetworkQuery: request timed out")));
|
|
872
|
+
}, timeoutMs);
|
|
873
|
+
}
|
|
874
|
+
sendToServer({ type: "run-query", modelName, queryKey, query, options: resolvedOptions });
|
|
875
|
+
});
|
|
876
|
+
};
|
|
783
877
|
const sendMessage = (event, payload) => {
|
|
784
878
|
sendToServer({ type: "event", event, payload });
|
|
785
879
|
};
|
|
@@ -793,6 +887,43 @@ const onMessage = (event, callback) => {
|
|
|
793
887
|
if (callbacks && callbacks.size === 0) messageCallbacks.delete(event);
|
|
794
888
|
};
|
|
795
889
|
};
|
|
890
|
+
const normalizePageInfo = (value) => {
|
|
891
|
+
if (!value || typeof value !== "object") return void 0;
|
|
892
|
+
if (Array.isArray(value)) return void 0;
|
|
893
|
+
const raw = value;
|
|
894
|
+
if (typeof raw.hasNextPage !== "boolean" || typeof raw.hasPrevPage !== "boolean") return void 0;
|
|
895
|
+
const nextCursor = typeof raw.nextCursor === "string" && raw.nextCursor ? raw.nextCursor : void 0;
|
|
896
|
+
const prevCursor = typeof raw.prevCursor === "string" && raw.prevCursor ? raw.prevCursor : void 0;
|
|
897
|
+
return {
|
|
898
|
+
hasNextPage: raw.hasNextPage,
|
|
899
|
+
hasPrevPage: raw.hasPrevPage,
|
|
900
|
+
...nextCursor ? { nextCursor } : {},
|
|
901
|
+
...prevCursor ? { prevCursor } : {}
|
|
902
|
+
};
|
|
903
|
+
};
|
|
904
|
+
const getDocId = (doc) => {
|
|
905
|
+
if (!doc || typeof doc !== "object") return "";
|
|
906
|
+
const id = doc._id;
|
|
907
|
+
return typeof id === "string" ? id.trim() : "";
|
|
908
|
+
};
|
|
909
|
+
const dedupeById = (docs) => {
|
|
910
|
+
const seen = /* @__PURE__ */ new Set();
|
|
911
|
+
const merged = [];
|
|
912
|
+
for (const doc of docs) {
|
|
913
|
+
const id = getDocId(doc);
|
|
914
|
+
if (id && seen.has(id)) continue;
|
|
915
|
+
if (id) seen.add(id);
|
|
916
|
+
merged.push(doc);
|
|
917
|
+
}
|
|
918
|
+
return merged;
|
|
919
|
+
};
|
|
920
|
+
const flattenLoadedPages = (previousPages, headPage, nextPages) => {
|
|
921
|
+
const merged = [];
|
|
922
|
+
for (const page of previousPages) merged.push(...page.nodes);
|
|
923
|
+
if (headPage) merged.push(...headPage.nodes);
|
|
924
|
+
for (const page of nextPages) merged.push(...page.nodes);
|
|
925
|
+
return dedupeById(merged);
|
|
926
|
+
};
|
|
796
927
|
const useQuery = (modelName, query = {}, options = {}) => {
|
|
797
928
|
if (typeof modelName !== "string" || modelName.trim().length === 0) {
|
|
798
929
|
throw new Error("useQuery: modelName must be a non-empty string");
|
|
@@ -807,13 +938,16 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
807
938
|
const sortJson = options.sort ? JSON.stringify(options.sort) : "";
|
|
808
939
|
const limitStr = typeof options.limit === "number" ? String(options.limit) : "";
|
|
809
940
|
const populateJson = options.populate ? JSON.stringify(options.populate) : "";
|
|
941
|
+
const paginationJson = options.pagination ? JSON.stringify(options.pagination) : "";
|
|
810
942
|
const hasPopulate = Boolean(options.populate);
|
|
943
|
+
const isPaginated = Boolean(options.pagination);
|
|
811
944
|
const queryKey = computeRtsQueryKey(query, {
|
|
812
945
|
key,
|
|
813
946
|
projection: options.projection,
|
|
814
947
|
sort: options.sort,
|
|
815
948
|
limit: options.limit,
|
|
816
|
-
populate: options.populate
|
|
949
|
+
populate: options.populate,
|
|
950
|
+
pagination: options.pagination
|
|
817
951
|
});
|
|
818
952
|
const ssrRuntime = useRtsSsrRuntime();
|
|
819
953
|
if (enabled && ssrEnabled && ssrRuntime) {
|
|
@@ -825,7 +959,8 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
825
959
|
projection: options.projection,
|
|
826
960
|
sort: options.sort,
|
|
827
961
|
limit: options.limit,
|
|
828
|
-
populate: options.populate
|
|
962
|
+
populate: options.populate,
|
|
963
|
+
pagination: options.pagination
|
|
829
964
|
},
|
|
830
965
|
queryKey
|
|
831
966
|
});
|
|
@@ -834,8 +969,13 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
834
969
|
() => enabled && ssrEnabled ? ssrRuntime ? ssrRuntime.getQueryData(modelName, queryKey) : peekHydratedRtsQueryData(modelName, queryKey) : void 0,
|
|
835
970
|
[enabled, ssrEnabled, ssrRuntime, modelName, queryKey]
|
|
836
971
|
);
|
|
972
|
+
const seedPageInfoRaw = useMemo(
|
|
973
|
+
() => enabled && ssrEnabled ? ssrRuntime ? ssrRuntime.getQueryPageInfo(modelName, queryKey) : peekHydratedRtsQueryPageInfo(modelName, queryKey) : void 0,
|
|
974
|
+
[enabled, ssrEnabled, ssrRuntime, modelName, queryKey]
|
|
975
|
+
);
|
|
837
976
|
const hasSeedData = Array.isArray(seedDataRaw);
|
|
838
977
|
const seedData = hasSeedData ? seedDataRaw : void 0;
|
|
978
|
+
const seedPageInfo = normalizePageInfo(seedPageInfoRaw);
|
|
839
979
|
const seedJson = (() => {
|
|
840
980
|
if (!hasSeedData) return "";
|
|
841
981
|
try {
|
|
@@ -844,13 +984,33 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
844
984
|
return "";
|
|
845
985
|
}
|
|
846
986
|
})();
|
|
847
|
-
const [data, setData] = useState(() => seedData);
|
|
987
|
+
const [data, setData] = useState(() => isPaginated ? void 0 : seedData);
|
|
988
|
+
const [headPage, setHeadPage] = useState(() => isPaginated && seedData ? { nodes: seedData, ...seedPageInfo ? { pageInfo: seedPageInfo } : {} } : null);
|
|
989
|
+
const [previousPages, setPreviousPages] = useState([]);
|
|
990
|
+
const [nextPages, setNextPages] = useState([]);
|
|
848
991
|
const [source, setSource] = useState(() => hasSeedData ? "cache" : void 0);
|
|
849
992
|
const [error, setError] = useState(void 0);
|
|
850
993
|
const [loading, setLoading] = useState(enabled && !hasSeedData);
|
|
994
|
+
const [pagingDirection, setPagingDirection] = useState(null);
|
|
851
995
|
const hasFirstReply = useRef(false);
|
|
852
996
|
const hasNetworkReply = useRef(false);
|
|
853
997
|
const lastDataJsonRef = useRef("");
|
|
998
|
+
const previousPagesRef = useRef([]);
|
|
999
|
+
const nextPagesRef = useRef([]);
|
|
1000
|
+
const headPageRef = useRef(null);
|
|
1001
|
+
const pagingDirectionRef = useRef(null);
|
|
1002
|
+
useEffect(() => {
|
|
1003
|
+
previousPagesRef.current = previousPages;
|
|
1004
|
+
}, [previousPages]);
|
|
1005
|
+
useEffect(() => {
|
|
1006
|
+
nextPagesRef.current = nextPages;
|
|
1007
|
+
}, [nextPages]);
|
|
1008
|
+
useEffect(() => {
|
|
1009
|
+
headPageRef.current = headPage;
|
|
1010
|
+
}, [headPage]);
|
|
1011
|
+
useEffect(() => {
|
|
1012
|
+
pagingDirectionRef.current = pagingDirection;
|
|
1013
|
+
}, [pagingDirection]);
|
|
854
1014
|
useEffect(() => {
|
|
855
1015
|
if (!ssrRuntime && enabled && ssrEnabled && hasSeedData) {
|
|
856
1016
|
consumeHydratedRtsQueryData(modelName, queryKey);
|
|
@@ -859,24 +1019,39 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
859
1019
|
hasNetworkReply.current = false;
|
|
860
1020
|
lastDataJsonRef.current = seedJson;
|
|
861
1021
|
setError(void 0);
|
|
1022
|
+
setPreviousPages([]);
|
|
1023
|
+
setNextPages([]);
|
|
862
1024
|
if (!enabled) {
|
|
863
1025
|
setLoading(false);
|
|
864
1026
|
setData(void 0);
|
|
1027
|
+
setHeadPage(null);
|
|
865
1028
|
setSource(void 0);
|
|
866
1029
|
return;
|
|
867
1030
|
}
|
|
868
1031
|
if (hasSeedData) {
|
|
1032
|
+
const nextSeedData = seedData;
|
|
869
1033
|
setLoading(false);
|
|
870
|
-
setData(seedData);
|
|
871
1034
|
setSource("cache");
|
|
1035
|
+
if (isPaginated) {
|
|
1036
|
+
setHeadPage({
|
|
1037
|
+
nodes: nextSeedData,
|
|
1038
|
+
...seedPageInfo ? { pageInfo: seedPageInfo } : {}
|
|
1039
|
+
});
|
|
1040
|
+
setData(void 0);
|
|
1041
|
+
} else {
|
|
1042
|
+
setData(nextSeedData);
|
|
1043
|
+
setHeadPage(null);
|
|
1044
|
+
}
|
|
872
1045
|
return;
|
|
873
1046
|
}
|
|
1047
|
+
setData(void 0);
|
|
1048
|
+
setHeadPage(null);
|
|
874
1049
|
setLoading(true);
|
|
875
|
-
}, [enabled, ssrEnabled, ssrRuntime, modelName, queryKey, hasSeedData, seedData, seedJson]);
|
|
1050
|
+
}, [enabled, ssrEnabled, ssrRuntime, modelName, queryKey, hasSeedData, seedData, seedJson, isPaginated, seedPageInfo]);
|
|
876
1051
|
useEffect(() => {
|
|
877
1052
|
if (!enabled) return;
|
|
878
1053
|
const runInitialNetworkQuery = refreshOnMount || !hasSeedData;
|
|
879
|
-
const runInitialLocalQuery = !hasSeedData && !hasPopulate;
|
|
1054
|
+
const runInitialLocalQuery = !hasSeedData && !hasPopulate && !isPaginated;
|
|
880
1055
|
const unsubscribe = registerQuery(
|
|
881
1056
|
modelName,
|
|
882
1057
|
query,
|
|
@@ -885,7 +1060,8 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
885
1060
|
projection: options.projection,
|
|
886
1061
|
sort: options.sort,
|
|
887
1062
|
limit: options.limit,
|
|
888
|
-
populate: options.populate
|
|
1063
|
+
populate: options.populate,
|
|
1064
|
+
pagination: options.pagination
|
|
889
1065
|
},
|
|
890
1066
|
(err, result, context) => {
|
|
891
1067
|
if (context.source === "cache" && hasNetworkReply.current) return;
|
|
@@ -902,9 +1078,11 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
902
1078
|
return;
|
|
903
1079
|
}
|
|
904
1080
|
hasFirstReply.current = true;
|
|
1081
|
+
const networkPageInfo = context.source === "network" ? context.pageInfo : void 0;
|
|
1082
|
+
const payloadForHash = isPaginated ? { result, pageInfo: networkPageInfo } : result;
|
|
905
1083
|
let nextJson = "";
|
|
906
1084
|
try {
|
|
907
|
-
nextJson = JSON.stringify(
|
|
1085
|
+
nextJson = JSON.stringify(payloadForHash);
|
|
908
1086
|
} catch {
|
|
909
1087
|
nextJson = "";
|
|
910
1088
|
}
|
|
@@ -914,6 +1092,14 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
914
1092
|
}
|
|
915
1093
|
lastDataJsonRef.current = nextJson;
|
|
916
1094
|
setSource(context.source);
|
|
1095
|
+
setError(void 0);
|
|
1096
|
+
if (isPaginated) {
|
|
1097
|
+
setHeadPage({
|
|
1098
|
+
nodes: result,
|
|
1099
|
+
...networkPageInfo ? { pageInfo: networkPageInfo } : {}
|
|
1100
|
+
});
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
917
1103
|
setData(result);
|
|
918
1104
|
},
|
|
919
1105
|
{
|
|
@@ -924,15 +1110,156 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
924
1110
|
return () => {
|
|
925
1111
|
unsubscribe?.();
|
|
926
1112
|
};
|
|
927
|
-
}, [
|
|
1113
|
+
}, [
|
|
1114
|
+
enabled,
|
|
1115
|
+
modelName,
|
|
1116
|
+
queryKey,
|
|
1117
|
+
queryJson,
|
|
1118
|
+
projectionJson,
|
|
1119
|
+
sortJson,
|
|
1120
|
+
limitStr,
|
|
1121
|
+
populateJson,
|
|
1122
|
+
paginationJson,
|
|
1123
|
+
hasSeedData,
|
|
1124
|
+
refreshOnMount,
|
|
1125
|
+
isPaginated
|
|
1126
|
+
]);
|
|
1127
|
+
const effectivePageInfo = useMemo(() => {
|
|
1128
|
+
if (!isPaginated) return void 0;
|
|
1129
|
+
const firstPageInfo = previousPages.length > 0 ? previousPages[0]?.pageInfo : headPage?.pageInfo;
|
|
1130
|
+
const lastPageInfo = nextPages.length > 0 ? nextPages[nextPages.length - 1]?.pageInfo : headPage?.pageInfo;
|
|
1131
|
+
if (!firstPageInfo && !lastPageInfo) return void 0;
|
|
1132
|
+
const hasPrevPage = Boolean(firstPageInfo?.hasPrevPage);
|
|
1133
|
+
const hasNextPage = Boolean(lastPageInfo?.hasNextPage);
|
|
1134
|
+
const prevCursor = firstPageInfo?.prevCursor;
|
|
1135
|
+
const nextCursor = lastPageInfo?.nextCursor;
|
|
1136
|
+
return {
|
|
1137
|
+
hasPrevPage,
|
|
1138
|
+
hasNextPage,
|
|
1139
|
+
...prevCursor ? { prevCursor } : {},
|
|
1140
|
+
...nextCursor ? { nextCursor } : {}
|
|
1141
|
+
};
|
|
1142
|
+
}, [headPage, isPaginated, nextPages, previousPages]);
|
|
1143
|
+
const mergedPaginatedData = useMemo(() => {
|
|
1144
|
+
if (!isPaginated) return void 0;
|
|
1145
|
+
if (!headPage && previousPages.length === 0 && nextPages.length === 0) return void 0;
|
|
1146
|
+
return flattenLoadedPages(previousPages, headPage, nextPages);
|
|
1147
|
+
}, [headPage, isPaginated, nextPages, previousPages]);
|
|
1148
|
+
const fetchNext = async () => {
|
|
1149
|
+
if (!enabled || !isPaginated || !options.pagination) return false;
|
|
1150
|
+
if (pagingDirectionRef.current) return false;
|
|
1151
|
+
const currentHead = headPageRef.current;
|
|
1152
|
+
const currentNextPages = nextPagesRef.current;
|
|
1153
|
+
const cursor = currentNextPages.length > 0 ? currentNextPages[currentNextPages.length - 1]?.pageInfo?.nextCursor : currentHead?.pageInfo?.nextCursor;
|
|
1154
|
+
const hasNextPage = currentNextPages.length > 0 ? Boolean(currentNextPages[currentNextPages.length - 1]?.pageInfo?.hasNextPage) : Boolean(currentHead?.pageInfo?.hasNextPage);
|
|
1155
|
+
if (!cursor || !hasNextPage) return false;
|
|
1156
|
+
setPagingDirection("next");
|
|
1157
|
+
setLoading(true);
|
|
1158
|
+
setError(void 0);
|
|
1159
|
+
try {
|
|
1160
|
+
const response = await runNetworkQuery({
|
|
1161
|
+
modelName,
|
|
1162
|
+
query,
|
|
1163
|
+
options: {
|
|
1164
|
+
key,
|
|
1165
|
+
projection: options.projection,
|
|
1166
|
+
sort: options.sort,
|
|
1167
|
+
limit: options.limit,
|
|
1168
|
+
populate: options.populate,
|
|
1169
|
+
pagination: {
|
|
1170
|
+
...options.pagination,
|
|
1171
|
+
direction: "next",
|
|
1172
|
+
cursor
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
});
|
|
1176
|
+
if (!Array.isArray(response.data)) return false;
|
|
1177
|
+
const page = {
|
|
1178
|
+
nodes: response.data,
|
|
1179
|
+
...response.context.source === "network" && response.context.pageInfo ? { pageInfo: response.context.pageInfo } : {}
|
|
1180
|
+
};
|
|
1181
|
+
setSource("network");
|
|
1182
|
+
setNextPages((current) => [...current, page]);
|
|
1183
|
+
return true;
|
|
1184
|
+
} catch (err) {
|
|
1185
|
+
setError(err);
|
|
1186
|
+
return false;
|
|
1187
|
+
} finally {
|
|
1188
|
+
setPagingDirection(null);
|
|
1189
|
+
setLoading(false);
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
const fetchPrevious = async () => {
|
|
1193
|
+
if (!enabled || !isPaginated || !options.pagination) return false;
|
|
1194
|
+
if (pagingDirectionRef.current) return false;
|
|
1195
|
+
const currentHead = headPageRef.current;
|
|
1196
|
+
const currentPreviousPages = previousPagesRef.current;
|
|
1197
|
+
const cursor = currentPreviousPages.length > 0 ? currentPreviousPages[0]?.pageInfo?.prevCursor : currentHead?.pageInfo?.prevCursor;
|
|
1198
|
+
const hasPrevPage = currentPreviousPages.length > 0 ? Boolean(currentPreviousPages[0]?.pageInfo?.hasPrevPage) : Boolean(currentHead?.pageInfo?.hasPrevPage);
|
|
1199
|
+
if (!cursor || !hasPrevPage) return false;
|
|
1200
|
+
setPagingDirection("prev");
|
|
1201
|
+
setLoading(true);
|
|
1202
|
+
setError(void 0);
|
|
1203
|
+
try {
|
|
1204
|
+
const response = await runNetworkQuery({
|
|
1205
|
+
modelName,
|
|
1206
|
+
query,
|
|
1207
|
+
options: {
|
|
1208
|
+
key,
|
|
1209
|
+
projection: options.projection,
|
|
1210
|
+
sort: options.sort,
|
|
1211
|
+
limit: options.limit,
|
|
1212
|
+
populate: options.populate,
|
|
1213
|
+
pagination: {
|
|
1214
|
+
...options.pagination,
|
|
1215
|
+
direction: "prev",
|
|
1216
|
+
cursor
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
});
|
|
1220
|
+
if (!Array.isArray(response.data)) return false;
|
|
1221
|
+
const page = {
|
|
1222
|
+
nodes: response.data,
|
|
1223
|
+
...response.context.source === "network" && response.context.pageInfo ? { pageInfo: response.context.pageInfo } : {}
|
|
1224
|
+
};
|
|
1225
|
+
setSource("network");
|
|
1226
|
+
setPreviousPages((current) => [page, ...current]);
|
|
1227
|
+
return true;
|
|
1228
|
+
} catch (err) {
|
|
1229
|
+
setError(err);
|
|
1230
|
+
return false;
|
|
1231
|
+
} finally {
|
|
1232
|
+
setPagingDirection(null);
|
|
1233
|
+
setLoading(false);
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1236
|
+
const resetPagination = () => {
|
|
1237
|
+
if (!isPaginated) return;
|
|
1238
|
+
setPreviousPages([]);
|
|
1239
|
+
setNextPages([]);
|
|
1240
|
+
};
|
|
928
1241
|
return useMemo(
|
|
929
1242
|
() => ({
|
|
930
|
-
data,
|
|
1243
|
+
data: isPaginated ? mergedPaginatedData : data,
|
|
1244
|
+
pageInfo: effectivePageInfo,
|
|
931
1245
|
source,
|
|
932
1246
|
error,
|
|
933
|
-
loading
|
|
1247
|
+
loading,
|
|
1248
|
+
fetchNext,
|
|
1249
|
+
fetchPrevious,
|
|
1250
|
+
resetPagination
|
|
934
1251
|
}),
|
|
935
|
-
[
|
|
1252
|
+
[
|
|
1253
|
+
data,
|
|
1254
|
+
effectivePageInfo,
|
|
1255
|
+
error,
|
|
1256
|
+
fetchNext,
|
|
1257
|
+
fetchPrevious,
|
|
1258
|
+
isPaginated,
|
|
1259
|
+
loading,
|
|
1260
|
+
mergedPaginatedData,
|
|
1261
|
+
source
|
|
1262
|
+
]
|
|
936
1263
|
);
|
|
937
1264
|
};
|
|
938
1265
|
export {
|
|
@@ -949,14 +1276,16 @@ export {
|
|
|
949
1276
|
disconnect as i,
|
|
950
1277
|
reconnect as j,
|
|
951
1278
|
registerQuery as k,
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1279
|
+
runNetworkQuery as l,
|
|
1280
|
+
syncRtsChanges as m,
|
|
1281
|
+
hydrateRtsFromWindow as n,
|
|
955
1282
|
onMessage as o,
|
|
956
|
-
|
|
957
|
-
|
|
1283
|
+
clearHydratedRtsQueryData as p,
|
|
1284
|
+
peekHydratedRtsQueryData as q,
|
|
958
1285
|
resetRtsPouchStore as r,
|
|
959
1286
|
sendMessage as s,
|
|
960
|
-
|
|
1287
|
+
peekHydratedRtsQueryPageInfo as t,
|
|
1288
|
+
updateDocs as u,
|
|
1289
|
+
useQuery as v
|
|
961
1290
|
};
|
|
962
|
-
//# sourceMappingURL=useQuery-
|
|
1291
|
+
//# sourceMappingURL=useQuery-Ce_EmI2F.js.map
|