@rpcbase/client 0.381.0 → 0.383.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 +21 -17
- package/dist/index.js.map +1 -1
- package/dist/initWithRoutes.d.ts.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 -7
- package/dist/rts/queryKey.d.ts.map +1 -1
- package/dist/rts/ssrHydration.d.ts +6 -6
- 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 +13 -0
- package/dist/rts/wsClient.d.ts.map +1 -1
- package/dist/{useQuery-n0OatV-X.js → useQuery-Ce_EmI2F.js} +369 -62
- package/dist/useQuery-Ce_EmI2F.js.map +1 -0
- package/package.json +1 -1
- package/dist/useQuery-n0OatV-X.js.map +0 -1
|
@@ -1,14 +1,28 @@
|
|
|
1
|
-
import { createContext, useContext, useId, useState, useRef, useEffect
|
|
1
|
+
import { createContext, useContext, useId, useMemo, useState, useRef, useEffect } from "react";
|
|
2
2
|
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 {
|
|
@@ -35,58 +51,34 @@ const parseHydrationData = (value) => {
|
|
|
35
51
|
queries
|
|
36
52
|
};
|
|
37
53
|
};
|
|
38
|
-
const hydrateRtsFromWindow = (
|
|
54
|
+
const hydrateRtsFromWindow = () => {
|
|
39
55
|
if (typeof window === "undefined") return;
|
|
40
56
|
const browserWindow = window;
|
|
41
57
|
const raw = browserWindow[STATIC_RPCBASE_RTS_HYDRATION_DATA_KEY];
|
|
42
58
|
delete browserWindow[STATIC_RPCBASE_RTS_HYDRATION_DATA_KEY];
|
|
43
59
|
const parsed = parseHydrationData(raw);
|
|
44
60
|
if (!parsed) return;
|
|
45
|
-
if (parsed.tenantId !== identity.tenantId || parsed.uid !== identity.uid) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
61
|
hydrationDataStore.clear();
|
|
62
|
+
hydrationPageInfoStore.clear();
|
|
49
63
|
for (const query of parsed.queries) {
|
|
50
64
|
hydrationDataStore.set(makeStoreKey(query.modelName, query.queryKey), query.data);
|
|
65
|
+
hydrationPageInfoStore.set(makeStoreKey(query.modelName, query.queryKey), query.pageInfo);
|
|
51
66
|
}
|
|
52
67
|
};
|
|
53
68
|
const peekHydratedRtsQueryData = (modelName, queryKey) => {
|
|
54
69
|
return hydrationDataStore.get(makeStoreKey(modelName, queryKey));
|
|
55
70
|
};
|
|
71
|
+
const peekHydratedRtsQueryPageInfo = (modelName, queryKey) => {
|
|
72
|
+
return hydrationPageInfoStore.get(makeStoreKey(modelName, queryKey));
|
|
73
|
+
};
|
|
74
|
+
const consumeHydratedRtsQueryData = (modelName, queryKey) => {
|
|
75
|
+
const key = makeStoreKey(modelName, queryKey);
|
|
76
|
+
hydrationDataStore.delete(key);
|
|
77
|
+
hydrationPageInfoStore.delete(key);
|
|
78
|
+
};
|
|
56
79
|
const clearHydratedRtsQueryData = () => {
|
|
57
80
|
hydrationDataStore.clear();
|
|
58
|
-
|
|
59
|
-
const readRootLikeLoaderData = () => {
|
|
60
|
-
if (typeof window === "undefined") return null;
|
|
61
|
-
const hydration = window.__staticRouterHydrationData;
|
|
62
|
-
if (!hydration || typeof hydration !== "object") return null;
|
|
63
|
-
const loaderData = hydration.loaderData;
|
|
64
|
-
if (!loaderData || typeof loaderData !== "object") return null;
|
|
65
|
-
const entries = Object.entries(loaderData);
|
|
66
|
-
let fallback = null;
|
|
67
|
-
for (const [routeId, data] of entries) {
|
|
68
|
-
if (!data || typeof data !== "object" || Array.isArray(data)) continue;
|
|
69
|
-
const obj = data;
|
|
70
|
-
const hasTenantId = Object.prototype.hasOwnProperty.call(obj, "tenantId");
|
|
71
|
-
const hasUser = Object.prototype.hasOwnProperty.call(obj, "user");
|
|
72
|
-
if (!hasTenantId && !hasUser) continue;
|
|
73
|
-
if (routeId === "root") return obj;
|
|
74
|
-
if (!fallback) fallback = obj;
|
|
75
|
-
}
|
|
76
|
-
return fallback;
|
|
77
|
-
};
|
|
78
|
-
const resolveRtsHydrationIdentityFromStaticRouterData = () => {
|
|
79
|
-
const rootData = readRootLikeLoaderData();
|
|
80
|
-
if (!rootData) {
|
|
81
|
-
return { tenantId: null, uid: null };
|
|
82
|
-
}
|
|
83
|
-
const tenantId = normalizeStringOrNull(rootData.tenantId);
|
|
84
|
-
const user = rootData.user;
|
|
85
|
-
const userId = user && typeof user === "object" ? normalizeStringOrNull(user.id) : null;
|
|
86
|
-
return {
|
|
87
|
-
tenantId,
|
|
88
|
-
uid: userId
|
|
89
|
-
};
|
|
81
|
+
hydrationPageInfoStore.clear();
|
|
90
82
|
};
|
|
91
83
|
const RtsSsrRuntimeProvider = ({
|
|
92
84
|
value,
|
|
@@ -426,7 +418,8 @@ const computeRtsQueryKey = (query, options) => {
|
|
|
426
418
|
const sort = options.sort ? JSON.stringify(options.sort) : "";
|
|
427
419
|
const limit = typeof options.limit === "number" ? String(options.limit) : "";
|
|
428
420
|
const populate = options.populate ? JSON.stringify(options.populate) : "";
|
|
429
|
-
|
|
421
|
+
const pagination = options.pagination ? JSON.stringify(options.pagination) : "";
|
|
422
|
+
return `${key}${JSON.stringify(query)}${projection}${sort}${limit}${populate}${pagination}`;
|
|
430
423
|
};
|
|
431
424
|
const TENANT_ID_QUERY_PARAM = "rb-tenant-id";
|
|
432
425
|
const RTS_CHANGES_ROUTE = "/api/rb/rts/changes";
|
|
@@ -520,15 +513,31 @@ const isDocWithId = (doc) => {
|
|
|
520
513
|
if (!doc || typeof doc !== "object") return false;
|
|
521
514
|
return typeof doc._id === "string";
|
|
522
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
|
+
};
|
|
523
530
|
const handleQueryPayload = (payload) => {
|
|
524
531
|
const { modelName, queryKey, data, error, txnId } = payload;
|
|
525
532
|
const cbKey = `${modelName}.${queryKey}`;
|
|
526
533
|
const callbacks = queryCallbacks.get(cbKey);
|
|
527
534
|
if (!callbacks || !callbacks.size) return;
|
|
528
535
|
const subscription = subscriptions.get(cbKey);
|
|
536
|
+
const pageInfo = normalizePageInfo$1(payload.pageInfo);
|
|
529
537
|
const hasPopulate = Boolean(subscription?.options?.populate);
|
|
538
|
+
const hasPagination = Boolean(subscription?.options?.pagination || pageInfo);
|
|
530
539
|
const isLocal = !!(txnId && localTxnBuf.includes(txnId));
|
|
531
|
-
const context = { source: "network", isLocal, txnId };
|
|
540
|
+
const context = { source: "network", isLocal, txnId, ...pageInfo ? { pageInfo } : {} };
|
|
532
541
|
if (error) {
|
|
533
542
|
for (const cb of callbacks) cb(error, void 0, context);
|
|
534
543
|
return;
|
|
@@ -538,6 +547,7 @@ const handleQueryPayload = (payload) => {
|
|
|
538
547
|
const docs = Array.isArray(data) ? data.filter(isDocWithId) : [];
|
|
539
548
|
if (!docs.length) return;
|
|
540
549
|
if (hasPopulate) return;
|
|
550
|
+
if (hasPagination) return;
|
|
541
551
|
void updateDocs(modelName, docs, currentUid).catch(() => {
|
|
542
552
|
});
|
|
543
553
|
};
|
|
@@ -780,11 +790,14 @@ const registerQuery = (modelName, query, optionsOrCallback, callbackMaybe, behav
|
|
|
780
790
|
const queryKey = computeRtsQueryKey(query, options);
|
|
781
791
|
const cbKey = `${modelName}.${queryKey}`;
|
|
782
792
|
const runInitialNetworkQuery = behavior?.runInitialNetworkQuery !== false;
|
|
793
|
+
const runInitialLocalQuery = behavior?.runInitialLocalQuery !== false;
|
|
794
|
+
const hasPopulate = Boolean(options.populate);
|
|
795
|
+
const hasPagination = Boolean(options.pagination);
|
|
783
796
|
const set = queryCallbacks.get(cbKey) ?? /* @__PURE__ */ new Set();
|
|
784
797
|
set.add(callback);
|
|
785
798
|
queryCallbacks.set(cbKey, set);
|
|
786
799
|
subscriptions.set(cbKey, { modelName, query, options, queryKey, runInitialNetworkQuery });
|
|
787
|
-
if (currentUid) {
|
|
800
|
+
if (currentUid && runInitialLocalQuery && !hasPopulate && !hasPagination) {
|
|
788
801
|
void runQuery({
|
|
789
802
|
modelName,
|
|
790
803
|
query,
|
|
@@ -810,6 +823,57 @@ const registerQuery = (modelName, query, optionsOrCallback, callbackMaybe, behav
|
|
|
810
823
|
}
|
|
811
824
|
};
|
|
812
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
|
+
};
|
|
813
877
|
const sendMessage = (event, payload) => {
|
|
814
878
|
sendToServer({ type: "event", event, payload });
|
|
815
879
|
};
|
|
@@ -823,6 +887,43 @@ const onMessage = (event, callback) => {
|
|
|
823
887
|
if (callbacks && callbacks.size === 0) messageCallbacks.delete(event);
|
|
824
888
|
};
|
|
825
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
|
+
};
|
|
826
927
|
const useQuery = (modelName, query = {}, options = {}) => {
|
|
827
928
|
if (typeof modelName !== "string" || modelName.trim().length === 0) {
|
|
828
929
|
throw new Error("useQuery: modelName must be a non-empty string");
|
|
@@ -837,12 +938,16 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
837
938
|
const sortJson = options.sort ? JSON.stringify(options.sort) : "";
|
|
838
939
|
const limitStr = typeof options.limit === "number" ? String(options.limit) : "";
|
|
839
940
|
const populateJson = options.populate ? JSON.stringify(options.populate) : "";
|
|
941
|
+
const paginationJson = options.pagination ? JSON.stringify(options.pagination) : "";
|
|
942
|
+
const hasPopulate = Boolean(options.populate);
|
|
943
|
+
const isPaginated = Boolean(options.pagination);
|
|
840
944
|
const queryKey = computeRtsQueryKey(query, {
|
|
841
945
|
key,
|
|
842
946
|
projection: options.projection,
|
|
843
947
|
sort: options.sort,
|
|
844
948
|
limit: options.limit,
|
|
845
|
-
populate: options.populate
|
|
949
|
+
populate: options.populate,
|
|
950
|
+
pagination: options.pagination
|
|
846
951
|
});
|
|
847
952
|
const ssrRuntime = useRtsSsrRuntime();
|
|
848
953
|
if (enabled && ssrEnabled && ssrRuntime) {
|
|
@@ -854,14 +959,23 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
854
959
|
projection: options.projection,
|
|
855
960
|
sort: options.sort,
|
|
856
961
|
limit: options.limit,
|
|
857
|
-
populate: options.populate
|
|
962
|
+
populate: options.populate,
|
|
963
|
+
pagination: options.pagination
|
|
858
964
|
},
|
|
859
965
|
queryKey
|
|
860
966
|
});
|
|
861
967
|
}
|
|
862
|
-
const seedDataRaw =
|
|
968
|
+
const seedDataRaw = useMemo(
|
|
969
|
+
() => enabled && ssrEnabled ? ssrRuntime ? ssrRuntime.getQueryData(modelName, queryKey) : peekHydratedRtsQueryData(modelName, queryKey) : void 0,
|
|
970
|
+
[enabled, ssrEnabled, ssrRuntime, modelName, queryKey]
|
|
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
|
+
);
|
|
863
976
|
const hasSeedData = Array.isArray(seedDataRaw);
|
|
864
977
|
const seedData = hasSeedData ? seedDataRaw : void 0;
|
|
978
|
+
const seedPageInfo = normalizePageInfo(seedPageInfoRaw);
|
|
865
979
|
const seedJson = (() => {
|
|
866
980
|
if (!hasSeedData) return "";
|
|
867
981
|
try {
|
|
@@ -870,35 +984,74 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
870
984
|
return "";
|
|
871
985
|
}
|
|
872
986
|
})();
|
|
873
|
-
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([]);
|
|
874
991
|
const [source, setSource] = useState(() => hasSeedData ? "cache" : void 0);
|
|
875
992
|
const [error, setError] = useState(void 0);
|
|
876
993
|
const [loading, setLoading] = useState(enabled && !hasSeedData);
|
|
994
|
+
const [pagingDirection, setPagingDirection] = useState(null);
|
|
877
995
|
const hasFirstReply = useRef(false);
|
|
878
996
|
const hasNetworkReply = useRef(false);
|
|
879
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]);
|
|
880
1008
|
useEffect(() => {
|
|
1009
|
+
headPageRef.current = headPage;
|
|
1010
|
+
}, [headPage]);
|
|
1011
|
+
useEffect(() => {
|
|
1012
|
+
pagingDirectionRef.current = pagingDirection;
|
|
1013
|
+
}, [pagingDirection]);
|
|
1014
|
+
useEffect(() => {
|
|
1015
|
+
if (!ssrRuntime && enabled && ssrEnabled && hasSeedData) {
|
|
1016
|
+
consumeHydratedRtsQueryData(modelName, queryKey);
|
|
1017
|
+
}
|
|
881
1018
|
hasFirstReply.current = hasSeedData;
|
|
882
1019
|
hasNetworkReply.current = false;
|
|
883
1020
|
lastDataJsonRef.current = seedJson;
|
|
884
1021
|
setError(void 0);
|
|
1022
|
+
setPreviousPages([]);
|
|
1023
|
+
setNextPages([]);
|
|
885
1024
|
if (!enabled) {
|
|
886
1025
|
setLoading(false);
|
|
887
1026
|
setData(void 0);
|
|
1027
|
+
setHeadPage(null);
|
|
888
1028
|
setSource(void 0);
|
|
889
1029
|
return;
|
|
890
1030
|
}
|
|
891
1031
|
if (hasSeedData) {
|
|
1032
|
+
const nextSeedData = seedData;
|
|
892
1033
|
setLoading(false);
|
|
893
|
-
setData(seedData);
|
|
894
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
|
+
}
|
|
895
1045
|
return;
|
|
896
1046
|
}
|
|
1047
|
+
setData(void 0);
|
|
1048
|
+
setHeadPage(null);
|
|
897
1049
|
setLoading(true);
|
|
898
|
-
}, [enabled, modelName, queryKey, hasSeedData, seedData, seedJson]);
|
|
1050
|
+
}, [enabled, ssrEnabled, ssrRuntime, modelName, queryKey, hasSeedData, seedData, seedJson, isPaginated, seedPageInfo]);
|
|
899
1051
|
useEffect(() => {
|
|
900
1052
|
if (!enabled) return;
|
|
901
1053
|
const runInitialNetworkQuery = refreshOnMount || !hasSeedData;
|
|
1054
|
+
const runInitialLocalQuery = !hasSeedData && !hasPopulate && !isPaginated;
|
|
902
1055
|
const unsubscribe = registerQuery(
|
|
903
1056
|
modelName,
|
|
904
1057
|
query,
|
|
@@ -907,7 +1060,8 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
907
1060
|
projection: options.projection,
|
|
908
1061
|
sort: options.sort,
|
|
909
1062
|
limit: options.limit,
|
|
910
|
-
populate: options.populate
|
|
1063
|
+
populate: options.populate,
|
|
1064
|
+
pagination: options.pagination
|
|
911
1065
|
},
|
|
912
1066
|
(err, result, context) => {
|
|
913
1067
|
if (context.source === "cache" && hasNetworkReply.current) return;
|
|
@@ -924,9 +1078,11 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
924
1078
|
return;
|
|
925
1079
|
}
|
|
926
1080
|
hasFirstReply.current = true;
|
|
1081
|
+
const networkPageInfo = context.source === "network" ? context.pageInfo : void 0;
|
|
1082
|
+
const payloadForHash = isPaginated ? { result, pageInfo: networkPageInfo } : result;
|
|
927
1083
|
let nextJson = "";
|
|
928
1084
|
try {
|
|
929
|
-
nextJson = JSON.stringify(
|
|
1085
|
+
nextJson = JSON.stringify(payloadForHash);
|
|
930
1086
|
} catch {
|
|
931
1087
|
nextJson = "";
|
|
932
1088
|
}
|
|
@@ -936,24 +1092,174 @@ const useQuery = (modelName, query = {}, options = {}) => {
|
|
|
936
1092
|
}
|
|
937
1093
|
lastDataJsonRef.current = nextJson;
|
|
938
1094
|
setSource(context.source);
|
|
1095
|
+
setError(void 0);
|
|
1096
|
+
if (isPaginated) {
|
|
1097
|
+
setHeadPage({
|
|
1098
|
+
nodes: result,
|
|
1099
|
+
...networkPageInfo ? { pageInfo: networkPageInfo } : {}
|
|
1100
|
+
});
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
939
1103
|
setData(result);
|
|
940
1104
|
},
|
|
941
1105
|
{
|
|
942
|
-
runInitialNetworkQuery
|
|
1106
|
+
runInitialNetworkQuery,
|
|
1107
|
+
runInitialLocalQuery
|
|
943
1108
|
}
|
|
944
1109
|
);
|
|
945
1110
|
return () => {
|
|
946
1111
|
unsubscribe?.();
|
|
947
1112
|
};
|
|
948
|
-
}, [
|
|
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
|
+
};
|
|
949
1241
|
return useMemo(
|
|
950
1242
|
() => ({
|
|
951
|
-
data,
|
|
1243
|
+
data: isPaginated ? mergedPaginatedData : data,
|
|
1244
|
+
pageInfo: effectivePageInfo,
|
|
952
1245
|
source,
|
|
953
1246
|
error,
|
|
954
|
-
loading
|
|
1247
|
+
loading,
|
|
1248
|
+
fetchNext,
|
|
1249
|
+
fetchPrevious,
|
|
1250
|
+
resetPagination
|
|
955
1251
|
}),
|
|
956
|
-
[
|
|
1252
|
+
[
|
|
1253
|
+
data,
|
|
1254
|
+
effectivePageInfo,
|
|
1255
|
+
error,
|
|
1256
|
+
fetchNext,
|
|
1257
|
+
fetchPrevious,
|
|
1258
|
+
isPaginated,
|
|
1259
|
+
loading,
|
|
1260
|
+
mergedPaginatedData,
|
|
1261
|
+
source
|
|
1262
|
+
]
|
|
957
1263
|
);
|
|
958
1264
|
};
|
|
959
1265
|
export {
|
|
@@ -970,15 +1276,16 @@ export {
|
|
|
970
1276
|
disconnect as i,
|
|
971
1277
|
reconnect as j,
|
|
972
1278
|
registerQuery as k,
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1279
|
+
runNetworkQuery as l,
|
|
1280
|
+
syncRtsChanges as m,
|
|
1281
|
+
hydrateRtsFromWindow as n,
|
|
976
1282
|
onMessage as o,
|
|
977
|
-
|
|
978
|
-
|
|
1283
|
+
clearHydratedRtsQueryData as p,
|
|
1284
|
+
peekHydratedRtsQueryData as q,
|
|
979
1285
|
resetRtsPouchStore as r,
|
|
980
1286
|
sendMessage as s,
|
|
981
|
-
|
|
982
|
-
updateDocs as u
|
|
1287
|
+
peekHydratedRtsQueryPageInfo as t,
|
|
1288
|
+
updateDocs as u,
|
|
1289
|
+
useQuery as v
|
|
983
1290
|
};
|
|
984
|
-
//# sourceMappingURL=useQuery-
|
|
1291
|
+
//# sourceMappingURL=useQuery-Ce_EmI2F.js.map
|