@convex-dev/agent 0.1.8-alpha.0 → 0.1.8-alpha.2
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/README.md +2 -0
- package/dist/commonjs/client/index.d.ts +65 -51
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +70 -4
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/component/_generated/api.d.ts +235 -0
- package/dist/commonjs/component/messages.d.ts +361 -155
- package/dist/commonjs/component/messages.d.ts.map +1 -1
- package/dist/commonjs/component/messages.js +25 -0
- package/dist/commonjs/component/messages.js.map +1 -1
- package/dist/commonjs/component/schema.d.ts +670 -670
- package/dist/commonjs/component/streams.d.ts +65 -18
- package/dist/commonjs/component/streams.d.ts.map +1 -1
- package/dist/commonjs/component/streams.js +120 -2
- package/dist/commonjs/component/streams.js.map +1 -1
- package/dist/commonjs/component/threads.d.ts +6 -6
- package/dist/commonjs/component/threads.d.ts.map +1 -1
- package/dist/commonjs/component/threads.js +9 -0
- package/dist/commonjs/component/threads.js.map +1 -1
- package/dist/commonjs/component/users.d.ts.map +1 -1
- package/dist/commonjs/component/users.js +1 -0
- package/dist/commonjs/component/users.js.map +1 -1
- package/dist/commonjs/component/vector/index.d.ts +12 -12
- package/dist/commonjs/component/vector/index.d.ts.map +1 -1
- package/dist/commonjs/component/vector/index.js +4 -0
- package/dist/commonjs/component/vector/index.js.map +1 -1
- package/dist/commonjs/component/vector/tables.d.ts +6 -6
- package/dist/commonjs/react/index.d.ts.map +1 -1
- package/dist/commonjs/react/index.js +1 -1
- package/dist/commonjs/react/index.js.map +1 -1
- package/dist/commonjs/validators.d.ts +161 -161
- package/dist/commonjs.tsbuildinfo +1 -1
- package/dist/esm/client/index.d.ts +31 -17
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +70 -4
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/component/_generated/api.d.ts +235 -0
- package/dist/esm/component/messages.d.ts +233 -27
- package/dist/esm/component/messages.d.ts.map +1 -1
- package/dist/esm/component/messages.js +25 -0
- package/dist/esm/component/messages.js.map +1 -1
- package/dist/esm/component/schema.d.ts +48 -48
- package/dist/esm/component/streams.d.ts +47 -0
- package/dist/esm/component/streams.d.ts.map +1 -1
- package/dist/esm/component/streams.js +120 -2
- package/dist/esm/component/streams.js.map +1 -1
- package/dist/esm/component/threads.d.ts +8 -8
- package/dist/esm/component/threads.d.ts.map +1 -1
- package/dist/esm/component/threads.js +9 -0
- package/dist/esm/component/threads.js.map +1 -1
- package/dist/esm/component/users.d.ts.map +1 -1
- package/dist/esm/component/users.js +1 -0
- package/dist/esm/component/users.js.map +1 -1
- package/dist/esm/component/vector/index.d.ts.map +1 -1
- package/dist/esm/component/vector/index.js +4 -0
- package/dist/esm/component/vector/index.js.map +1 -1
- package/dist/esm/react/index.d.ts.map +1 -1
- package/dist/esm/react/index.js +1 -1
- package/dist/esm/react/index.js.map +1 -1
- package/dist/esm/validators.d.ts +19 -19
- package/dist/esm.tsbuildinfo +1 -1
- package/package.json +4 -5
- package/src/client/index.ts +94 -4
- package/src/client/setup.test.ts +2 -2
- package/src/component/_generated/api.d.ts +235 -0
- package/src/component/messages.test.ts +140 -0
- package/src/component/messages.ts +30 -0
- package/src/component/streams.ts +148 -2
- package/src/component/threads.ts +8 -0
- package/src/component/users.ts +1 -0
- package/src/component/vector/index.ts +4 -0
- package/src/react/index.ts +1 -2
- package/dist/commonjs/react/usePaginatedQuery.d.ts +0 -241
- package/dist/commonjs/react/usePaginatedQuery.d.ts.map +0 -1
- package/dist/commonjs/react/usePaginatedQuery.js +0 -627
- package/dist/commonjs/react/usePaginatedQuery.js.map +0 -1
- package/dist/esm/react/usePaginatedQuery.d.ts +0 -241
- package/dist/esm/react/usePaginatedQuery.d.ts.map +0 -1
- package/dist/esm/react/usePaginatedQuery.js +0 -627
- package/dist/esm/react/usePaginatedQuery.js.map +0 -1
- package/react/package.json +0 -5
- package/src/react/usePaginatedQuery.ts +0 -901
|
@@ -1,627 +0,0 @@
|
|
|
1
|
-
import { useMemo, useState } from "react";
|
|
2
|
-
import { ConvexError, convexToJson, } from "convex/values";
|
|
3
|
-
import { useQueries } from "convex/react";
|
|
4
|
-
import { getFunctionName, } from "convex/server";
|
|
5
|
-
import { useConvex } from "convex/react";
|
|
6
|
-
import { compareValues } from "convex/values";
|
|
7
|
-
const splitQuery = (key, splitCursor, continueCursor) => (prevState) => {
|
|
8
|
-
const queries = { ...prevState.queries };
|
|
9
|
-
const splitKey1 = prevState.nextPageKey;
|
|
10
|
-
const splitKey2 = prevState.nextPageKey + 1;
|
|
11
|
-
const nextPageKey = prevState.nextPageKey + 2;
|
|
12
|
-
queries[splitKey1] = {
|
|
13
|
-
query: prevState.query,
|
|
14
|
-
args: {
|
|
15
|
-
...prevState.args,
|
|
16
|
-
paginationOpts: {
|
|
17
|
-
...prevState.queries[key].args.paginationOpts,
|
|
18
|
-
endCursor: splitCursor,
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
queries[splitKey2] = {
|
|
23
|
-
query: prevState.query,
|
|
24
|
-
args: {
|
|
25
|
-
...prevState.args,
|
|
26
|
-
paginationOpts: {
|
|
27
|
-
...prevState.queries[key].args.paginationOpts,
|
|
28
|
-
cursor: splitCursor,
|
|
29
|
-
endCursor: continueCursor,
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
const ongoingSplits = { ...prevState.ongoingSplits };
|
|
34
|
-
ongoingSplits[key] = [splitKey1, splitKey2];
|
|
35
|
-
return {
|
|
36
|
-
...prevState,
|
|
37
|
-
nextPageKey,
|
|
38
|
-
queries,
|
|
39
|
-
ongoingSplits,
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
const completeSplitQuery = (key) => (prevState) => {
|
|
43
|
-
const completedSplit = prevState.ongoingSplits[key];
|
|
44
|
-
if (completedSplit === undefined) {
|
|
45
|
-
return prevState;
|
|
46
|
-
}
|
|
47
|
-
const queries = { ...prevState.queries };
|
|
48
|
-
delete queries[key];
|
|
49
|
-
const ongoingSplits = { ...prevState.ongoingSplits };
|
|
50
|
-
delete ongoingSplits[key];
|
|
51
|
-
let pageKeys = prevState.pageKeys.slice();
|
|
52
|
-
const pageIndex = prevState.pageKeys.findIndex((v) => v === key);
|
|
53
|
-
if (pageIndex >= 0) {
|
|
54
|
-
pageKeys = [
|
|
55
|
-
...prevState.pageKeys.slice(0, pageIndex),
|
|
56
|
-
...completedSplit,
|
|
57
|
-
...prevState.pageKeys.slice(pageIndex + 1),
|
|
58
|
-
];
|
|
59
|
-
}
|
|
60
|
-
return {
|
|
61
|
-
...prevState,
|
|
62
|
-
queries,
|
|
63
|
-
pageKeys,
|
|
64
|
-
ongoingSplits,
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* This is a clone of the `usePaginatedQuery` hook from `convex-helpers`.
|
|
69
|
-
* The difference is that we lazily pin the end cursor on loading a new page.
|
|
70
|
-
* This will be standard behavior in a future version of `convex/react`, but
|
|
71
|
-
* for now it allows the agent to have correct behavior when loading a new page
|
|
72
|
-
* where new items are still coming in.
|
|
73
|
-
*/
|
|
74
|
-
export function usePaginatedQuery(query, args, options) {
|
|
75
|
-
if (typeof options?.initialNumItems !== "number" ||
|
|
76
|
-
options.initialNumItems < 0) {
|
|
77
|
-
throw new Error(`\`options.initialNumItems\` must be a positive number. Received \`${options?.initialNumItems}\`.`);
|
|
78
|
-
}
|
|
79
|
-
const skip = args === "skip";
|
|
80
|
-
const argsObject = skip ? {} : args;
|
|
81
|
-
const queryName = getFunctionName(query);
|
|
82
|
-
const createInitialState = useMemo(() => {
|
|
83
|
-
return () => {
|
|
84
|
-
const id = nextPaginationId();
|
|
85
|
-
return {
|
|
86
|
-
query,
|
|
87
|
-
args: argsObject,
|
|
88
|
-
id,
|
|
89
|
-
nextPageKey: 1,
|
|
90
|
-
pageKeys: skip ? [] : [0],
|
|
91
|
-
queries: skip
|
|
92
|
-
? {}
|
|
93
|
-
: {
|
|
94
|
-
0: {
|
|
95
|
-
query,
|
|
96
|
-
args: {
|
|
97
|
-
...argsObject,
|
|
98
|
-
paginationOpts: {
|
|
99
|
-
numItems: options.initialNumItems,
|
|
100
|
-
cursor: null,
|
|
101
|
-
id,
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
ongoingSplits: {},
|
|
107
|
-
skip,
|
|
108
|
-
};
|
|
109
|
-
};
|
|
110
|
-
// ESLint doesn't like that we're stringifying the args. We do this because
|
|
111
|
-
// we want to avoid rerendering if the args are a different
|
|
112
|
-
// object that serializes to the same result.
|
|
113
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
114
|
-
}, [
|
|
115
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
116
|
-
JSON.stringify(convexToJson(argsObject)),
|
|
117
|
-
queryName,
|
|
118
|
-
options.initialNumItems,
|
|
119
|
-
skip,
|
|
120
|
-
]);
|
|
121
|
-
const [state, setState] = useState(createInitialState);
|
|
122
|
-
// `currState` is the state that we'll render based on.
|
|
123
|
-
let currState = state;
|
|
124
|
-
if (getFunctionName(query) !== getFunctionName(state.query) ||
|
|
125
|
-
JSON.stringify(convexToJson(argsObject)) !==
|
|
126
|
-
JSON.stringify(convexToJson(state.args)) ||
|
|
127
|
-
skip !== state.skip) {
|
|
128
|
-
currState = createInitialState();
|
|
129
|
-
setState(currState);
|
|
130
|
-
}
|
|
131
|
-
const convexClient = useConvex();
|
|
132
|
-
const logger = convexClient.logger;
|
|
133
|
-
const resultsObject = useQueries(currState.queries);
|
|
134
|
-
const [results, maybeLastResult] = useMemo(() => {
|
|
135
|
-
let currResult = undefined;
|
|
136
|
-
const allItems = [];
|
|
137
|
-
for (const pageKey of currState.pageKeys) {
|
|
138
|
-
currResult = resultsObject[pageKey];
|
|
139
|
-
if (currResult === undefined) {
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
if (currResult instanceof Error) {
|
|
143
|
-
if (currResult.message.includes("InvalidCursor") ||
|
|
144
|
-
(currResult instanceof ConvexError &&
|
|
145
|
-
typeof currResult.data === "object" &&
|
|
146
|
-
currResult.data?.isConvexSystemError === true &&
|
|
147
|
-
currResult.data?.paginationError === "InvalidCursor")) {
|
|
148
|
-
// - InvalidCursor: If the cursor is invalid, probably the paginated
|
|
149
|
-
// database query was data-dependent and changed underneath us. The
|
|
150
|
-
// cursor in the params or journal no longer matches the current
|
|
151
|
-
// database query.
|
|
152
|
-
// In all cases, we want to restart pagination to throw away all our
|
|
153
|
-
// existing cursors.
|
|
154
|
-
logger.warn("usePaginatedQuery hit error, resetting pagination state: " +
|
|
155
|
-
currResult.message);
|
|
156
|
-
setState(createInitialState);
|
|
157
|
-
return [[], undefined];
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
throw currResult;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
const ongoingSplit = currState.ongoingSplits[pageKey];
|
|
164
|
-
if (ongoingSplit !== undefined) {
|
|
165
|
-
if (resultsObject[ongoingSplit[0]] !== undefined &&
|
|
166
|
-
resultsObject[ongoingSplit[1]] !== undefined) {
|
|
167
|
-
// Both pages of the split have results now. Swap them in.
|
|
168
|
-
setState(completeSplitQuery(pageKey));
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
else if (currResult.splitCursor &&
|
|
172
|
-
(currResult.pageStatus === "SplitRecommended" ||
|
|
173
|
-
currResult.pageStatus === "SplitRequired" ||
|
|
174
|
-
currResult.page.length > options.initialNumItems * 2)) {
|
|
175
|
-
// If a single page has more than double the expected number of items,
|
|
176
|
-
// or if the server requests a split, split the page into two.
|
|
177
|
-
setState(splitQuery(pageKey, currResult.splitCursor, currResult.continueCursor));
|
|
178
|
-
}
|
|
179
|
-
if (currResult.pageStatus === "SplitRequired") {
|
|
180
|
-
// If pageStatus is 'SplitRequired', it means the server was not able to
|
|
181
|
-
// fetch the full page. So we stop results before the incomplete
|
|
182
|
-
// page and return 'LoadingMore' while the page is splitting.
|
|
183
|
-
return [allItems, undefined];
|
|
184
|
-
}
|
|
185
|
-
allItems.push(...currResult.page);
|
|
186
|
-
}
|
|
187
|
-
return [allItems, currResult];
|
|
188
|
-
}, [
|
|
189
|
-
resultsObject,
|
|
190
|
-
currState.pageKeys,
|
|
191
|
-
currState.ongoingSplits,
|
|
192
|
-
options.initialNumItems,
|
|
193
|
-
createInitialState,
|
|
194
|
-
logger,
|
|
195
|
-
]);
|
|
196
|
-
const statusObject = useMemo(() => {
|
|
197
|
-
if (maybeLastResult === undefined) {
|
|
198
|
-
if (currState.nextPageKey === 1) {
|
|
199
|
-
return {
|
|
200
|
-
status: "LoadingFirstPage",
|
|
201
|
-
isLoading: true,
|
|
202
|
-
loadMore: (_numItems) => {
|
|
203
|
-
// Intentional noop.
|
|
204
|
-
},
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
return {
|
|
209
|
-
status: "LoadingMore",
|
|
210
|
-
isLoading: true,
|
|
211
|
-
loadMore: (_numItems) => {
|
|
212
|
-
// Intentional noop.
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
if (maybeLastResult.isDone) {
|
|
218
|
-
return {
|
|
219
|
-
status: "Exhausted",
|
|
220
|
-
isLoading: false,
|
|
221
|
-
loadMore: (_numItems) => {
|
|
222
|
-
// Intentional noop.
|
|
223
|
-
},
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
const continueCursor = maybeLastResult.continueCursor;
|
|
227
|
-
let alreadyLoadingMore = false;
|
|
228
|
-
return {
|
|
229
|
-
status: "CanLoadMore",
|
|
230
|
-
isLoading: false,
|
|
231
|
-
loadMore: (numItems) => {
|
|
232
|
-
if (!alreadyLoadingMore) {
|
|
233
|
-
alreadyLoadingMore = true;
|
|
234
|
-
setState((prevState) => {
|
|
235
|
-
const lastPageKey = prevState.pageKeys.at(-1);
|
|
236
|
-
const replaceKey = prevState.nextPageKey;
|
|
237
|
-
const newKey = prevState.nextPageKey + 1;
|
|
238
|
-
const nextPageKey = prevState.nextPageKey + 2;
|
|
239
|
-
const pageKeys = prevState.pageKeys; //[...prevState.pageKeys, prevState.nextPageKey];
|
|
240
|
-
const queries = { ...prevState.queries };
|
|
241
|
-
queries[replaceKey] = {
|
|
242
|
-
query: prevState.query,
|
|
243
|
-
args: {
|
|
244
|
-
...prevState.args,
|
|
245
|
-
paginationOpts: {
|
|
246
|
-
...queries[prevState.pageKeys.at(-1)].args
|
|
247
|
-
.paginationOpts,
|
|
248
|
-
endCursor: continueCursor,
|
|
249
|
-
},
|
|
250
|
-
},
|
|
251
|
-
};
|
|
252
|
-
queries[newKey] = {
|
|
253
|
-
query: prevState.query,
|
|
254
|
-
args: {
|
|
255
|
-
...prevState.args,
|
|
256
|
-
paginationOpts: {
|
|
257
|
-
numItems,
|
|
258
|
-
cursor: continueCursor,
|
|
259
|
-
id: prevState.id,
|
|
260
|
-
},
|
|
261
|
-
},
|
|
262
|
-
};
|
|
263
|
-
return {
|
|
264
|
-
...prevState,
|
|
265
|
-
nextPageKey,
|
|
266
|
-
pageKeys,
|
|
267
|
-
queries,
|
|
268
|
-
ongoingSplits: {
|
|
269
|
-
...prevState.ongoingSplits,
|
|
270
|
-
[lastPageKey]: [replaceKey, newKey],
|
|
271
|
-
},
|
|
272
|
-
};
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
},
|
|
276
|
-
};
|
|
277
|
-
}, [maybeLastResult, currState.nextPageKey]);
|
|
278
|
-
return {
|
|
279
|
-
results,
|
|
280
|
-
...statusObject,
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
let paginationId = 0;
|
|
284
|
-
/**
|
|
285
|
-
* Generate a new, unique ID for a pagination session.
|
|
286
|
-
*
|
|
287
|
-
* Every usage of {@link usePaginatedQuery} puts a unique ID into the
|
|
288
|
-
* query function arguments as a "cache-buster". This serves two purposes:
|
|
289
|
-
*
|
|
290
|
-
* 1. All calls to {@link usePaginatedQuery} have independent query
|
|
291
|
-
* journals.
|
|
292
|
-
*
|
|
293
|
-
* Every time we start a new pagination session, we'll load the first page of
|
|
294
|
-
* results and receive a fresh journal. Without the ID, we might instead reuse
|
|
295
|
-
* a query subscription already present in our client. This isn't desirable
|
|
296
|
-
* because the existing query function result may have grown or shrunk from the
|
|
297
|
-
* requested `initialNumItems`.
|
|
298
|
-
*
|
|
299
|
-
* 2. We can restart the pagination session on some types of errors.
|
|
300
|
-
*
|
|
301
|
-
* Sometimes we want to restart pagination from the beginning if we hit an error.
|
|
302
|
-
* Similar to (1), we'd like to ensure that this new session actually requests
|
|
303
|
-
* its first page from the server and doesn't reuse a query result already
|
|
304
|
-
* present in the client that may have hit the error.
|
|
305
|
-
*
|
|
306
|
-
* @returns The pagination ID.
|
|
307
|
-
*/
|
|
308
|
-
function nextPaginationId() {
|
|
309
|
-
paginationId++;
|
|
310
|
-
return paginationId;
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Reset pagination id for tests only, so tests know what it is.
|
|
314
|
-
*/
|
|
315
|
-
export function resetPaginationId() {
|
|
316
|
-
paginationId = 0;
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* Optimistically update the values in a paginated list.
|
|
320
|
-
*
|
|
321
|
-
* This optimistic update is designed to be used to update data loaded with
|
|
322
|
-
* {@link usePaginatedQuery}. It updates the list by applying
|
|
323
|
-
* `updateValue` to each element of the list across all of the loaded pages.
|
|
324
|
-
*
|
|
325
|
-
* This will only apply to queries with a matching names and arguments.
|
|
326
|
-
*
|
|
327
|
-
* Example usage:
|
|
328
|
-
* ```ts
|
|
329
|
-
* const myMutation = useMutation(api.myModule.myMutation)
|
|
330
|
-
* .withOptimisticUpdate((localStore, mutationArg) => {
|
|
331
|
-
*
|
|
332
|
-
* // Optimistically update the document with ID `mutationArg`
|
|
333
|
-
* // to have an additional property.
|
|
334
|
-
*
|
|
335
|
-
* optimisticallyUpdateValueInPaginatedQuery(
|
|
336
|
-
* localStore,
|
|
337
|
-
* api.myModule.paginatedQuery
|
|
338
|
-
* {},
|
|
339
|
-
* currentValue => {
|
|
340
|
-
* if (mutationArg === currentValue._id) {
|
|
341
|
-
* return {
|
|
342
|
-
* ...currentValue,
|
|
343
|
-
* "newProperty": "newValue",
|
|
344
|
-
* };
|
|
345
|
-
* }
|
|
346
|
-
* return currentValue;
|
|
347
|
-
* }
|
|
348
|
-
* );
|
|
349
|
-
*
|
|
350
|
-
* });
|
|
351
|
-
* ```
|
|
352
|
-
*
|
|
353
|
-
* @param localStore - An {@link OptimisticLocalStore} to update.
|
|
354
|
-
* @param query - A {@link FunctionReference} for the paginated query to update.
|
|
355
|
-
* @param args - The arguments object to the query function, excluding the
|
|
356
|
-
* `paginationOpts` property.
|
|
357
|
-
* @param updateValue - A function to produce the new values.
|
|
358
|
-
*
|
|
359
|
-
* @public
|
|
360
|
-
*/
|
|
361
|
-
export function optimisticallyUpdateValueInPaginatedQuery(localStore, query, args, updateValue) {
|
|
362
|
-
const expectedArgs = JSON.stringify(convexToJson(args));
|
|
363
|
-
for (const queryResult of localStore.getAllQueries(query)) {
|
|
364
|
-
if (queryResult.value !== undefined) {
|
|
365
|
-
const { paginationOpts: _, ...innerArgs } = queryResult.args;
|
|
366
|
-
if (JSON.stringify(convexToJson(innerArgs)) === expectedArgs) {
|
|
367
|
-
const value = queryResult.value;
|
|
368
|
-
if (typeof value === "object" &&
|
|
369
|
-
value !== null &&
|
|
370
|
-
Array.isArray(value.page)) {
|
|
371
|
-
localStore.setQuery(query, queryResult.args, {
|
|
372
|
-
...value,
|
|
373
|
-
page: value.page.map(updateValue),
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* Updates a paginated query to insert an element at the top of the list.
|
|
382
|
-
*
|
|
383
|
-
* This is regardless of the sort order, so if the list is in descending order,
|
|
384
|
-
* the inserted element will be treated as the "biggest" element, but if it's
|
|
385
|
-
* ascending, it'll be treated as the "smallest".
|
|
386
|
-
*
|
|
387
|
-
* Example:
|
|
388
|
-
* ```ts
|
|
389
|
-
* const createTask = useMutation(api.tasks.create)
|
|
390
|
-
* .withOptimisticUpdate((localStore, mutationArgs) => {
|
|
391
|
-
* insertAtTop({
|
|
392
|
-
* paginatedQuery: api.tasks.list,
|
|
393
|
-
* argsToMatch: { listId: mutationArgs.listId },
|
|
394
|
-
* localQueryStore: localStore,
|
|
395
|
-
* item: { _id: crypto.randomUUID() as Id<"tasks">, title: mutationArgs.title, completed: false },
|
|
396
|
-
* });
|
|
397
|
-
* });
|
|
398
|
-
* ```
|
|
399
|
-
*
|
|
400
|
-
* @param options.paginatedQuery - A function reference to the paginated query.
|
|
401
|
-
* @param options.argsToMatch - Optional arguments that must be in each relevant paginated query.
|
|
402
|
-
* This is useful if you use the same query function with different arguments to load
|
|
403
|
-
* different lists.
|
|
404
|
-
* @param options.localQueryStore
|
|
405
|
-
* @param options.item The item to insert.
|
|
406
|
-
* @returns
|
|
407
|
-
*/
|
|
408
|
-
export function insertAtTop(options) {
|
|
409
|
-
const { paginatedQuery, argsToMatch, localQueryStore, item } = options;
|
|
410
|
-
const queries = localQueryStore.getAllQueries(paginatedQuery);
|
|
411
|
-
const queriesThatMatch = queries.filter((q) => {
|
|
412
|
-
if (argsToMatch === undefined) {
|
|
413
|
-
return true;
|
|
414
|
-
}
|
|
415
|
-
return Object.keys(argsToMatch).every(
|
|
416
|
-
// @ts-expect-error -- This should be safe since both should be plain objects
|
|
417
|
-
(k) => compareValues(argsToMatch[k], q.args[k]) === 0);
|
|
418
|
-
});
|
|
419
|
-
const firstPage = queriesThatMatch.find((q) => q.args.paginationOpts.cursor === null);
|
|
420
|
-
if (firstPage === undefined || firstPage.value === undefined) {
|
|
421
|
-
// first page is not loaded, so don't update it until it loads
|
|
422
|
-
return;
|
|
423
|
-
}
|
|
424
|
-
localQueryStore.setQuery(paginatedQuery, firstPage.args, {
|
|
425
|
-
...firstPage.value,
|
|
426
|
-
page: [item, ...firstPage.value.page],
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
/**
|
|
430
|
-
* Updates a paginated query to insert an element at the bottom of the list.
|
|
431
|
-
*
|
|
432
|
-
* This is regardless of the sort order, so if the list is in descending order,
|
|
433
|
-
* the inserted element will be treated as the "smallest" element, but if it's
|
|
434
|
-
* ascending, it'll be treated as the "biggest".
|
|
435
|
-
*
|
|
436
|
-
* This only has an effect if the last page is loaded, since otherwise it would result
|
|
437
|
-
* in the element being inserted at the end of whatever is loaded (which is the middle of the list)
|
|
438
|
-
* and then popping out once the optimistic update is over.
|
|
439
|
-
*
|
|
440
|
-
* @param options.paginatedQuery - A function reference to the paginated query.
|
|
441
|
-
* @param options.argsToMatch - Optional arguments that must be in each relevant paginated query.
|
|
442
|
-
* This is useful if you use the same query function with different arguments to load
|
|
443
|
-
* different lists.
|
|
444
|
-
* @param options.localQueryStore
|
|
445
|
-
* @param options.element The element to insert.
|
|
446
|
-
* @returns
|
|
447
|
-
*/
|
|
448
|
-
export function insertAtBottomIfLoaded(options) {
|
|
449
|
-
const { paginatedQuery, localQueryStore, item, argsToMatch } = options;
|
|
450
|
-
const queries = localQueryStore.getAllQueries(paginatedQuery);
|
|
451
|
-
const queriesThatMatch = queries.filter((q) => {
|
|
452
|
-
if (argsToMatch === undefined) {
|
|
453
|
-
return true;
|
|
454
|
-
}
|
|
455
|
-
return Object.keys(argsToMatch).every(
|
|
456
|
-
// @ts-expect-error -- This should be safe since both should be plain objects
|
|
457
|
-
(k) => compareValues(argsToMatch[k], q.args[k]) === 0);
|
|
458
|
-
});
|
|
459
|
-
const lastPage = queriesThatMatch.find((q) => q.value !== undefined && q.value.isDone);
|
|
460
|
-
if (lastPage === undefined) {
|
|
461
|
-
// last page is not loaded, so don't update it since the item would immediately pop out
|
|
462
|
-
// when the server updates
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
localQueryStore.setQuery(paginatedQuery, lastPage.args, {
|
|
466
|
-
...lastPage.value,
|
|
467
|
-
page: [...lastPage.value.page, item],
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* This is a helper function for inserting an item at a specific position in a paginated query.
|
|
472
|
-
*
|
|
473
|
-
* You must provide the sortOrder and a function for deriving the sort key (an array of values) from an item in the list.
|
|
474
|
-
*
|
|
475
|
-
* This will only work if the server query uses the same sort order and sort key as the optimistic update.
|
|
476
|
-
*
|
|
477
|
-
* Example:
|
|
478
|
-
* ```ts
|
|
479
|
-
* const createTask = useMutation(api.tasks.create)
|
|
480
|
-
* .withOptimisticUpdate((localStore, mutationArgs) => {
|
|
481
|
-
* insertAtPosition({
|
|
482
|
-
* paginatedQuery: api.tasks.listByPriority,
|
|
483
|
-
* argsToMatch: { listId: mutationArgs.listId },
|
|
484
|
-
* sortOrder: "asc",
|
|
485
|
-
* sortKeyFromItem: (item) => [item.priority, item._creationTime],
|
|
486
|
-
* localQueryStore: localStore,
|
|
487
|
-
* item: {
|
|
488
|
-
* _id: crypto.randomUUID() as Id<"tasks">,
|
|
489
|
-
* _creationTime: Date.now(),
|
|
490
|
-
* title: mutationArgs.title,
|
|
491
|
-
* completed: false,
|
|
492
|
-
* priority: mutationArgs.priority,
|
|
493
|
-
* },
|
|
494
|
-
* });
|
|
495
|
-
* });
|
|
496
|
-
* ```
|
|
497
|
-
* @param options.paginatedQuery - A function reference to the paginated query.
|
|
498
|
-
* @param options.argsToMatch - Optional arguments that must be in each relevant paginated query.
|
|
499
|
-
* This is useful if you use the same query function with different arguments to load
|
|
500
|
-
* different lists.
|
|
501
|
-
* @param options.sortOrder - The sort order of the paginated query ("asc" or "desc").
|
|
502
|
-
* @param options.sortKeyFromItem - A function for deriving the sort key (an array of values) from an element in the list.
|
|
503
|
-
* Including a tie-breaker field like `_creationTime` is recommended.
|
|
504
|
-
* @param options.localQueryStore
|
|
505
|
-
* @param options.item - The item to insert.
|
|
506
|
-
* @returns
|
|
507
|
-
*/
|
|
508
|
-
export function insertAtPosition(options) {
|
|
509
|
-
const { paginatedQuery, sortOrder, sortKeyFromItem, localQueryStore, item, argsToMatch, } = options;
|
|
510
|
-
const queries = localQueryStore.getAllQueries(paginatedQuery);
|
|
511
|
-
// Group into sets of pages for the same usePaginatedQuery. Grouping is by all
|
|
512
|
-
// args except paginationOpts, but including paginationOpts.id.
|
|
513
|
-
const queryGroups = {};
|
|
514
|
-
for (const query of queries) {
|
|
515
|
-
if (argsToMatch !== undefined &&
|
|
516
|
-
!Object.keys(argsToMatch).every((k) =>
|
|
517
|
-
// @ts-expect-error why is this not working?
|
|
518
|
-
argsToMatch[k] === query.args[k])) {
|
|
519
|
-
continue;
|
|
520
|
-
}
|
|
521
|
-
const key = JSON.stringify(Object.fromEntries(Object.entries(query.args).map(([k, v]) => [
|
|
522
|
-
k,
|
|
523
|
-
k === "paginationOpts" ? v.id : v,
|
|
524
|
-
])));
|
|
525
|
-
queryGroups[key] ??= [];
|
|
526
|
-
queryGroups[key].push(query);
|
|
527
|
-
}
|
|
528
|
-
for (const pageQueries of Object.values(queryGroups)) {
|
|
529
|
-
insertAtPositionInPages({
|
|
530
|
-
pageQueries,
|
|
531
|
-
paginatedQuery,
|
|
532
|
-
sortOrder,
|
|
533
|
-
sortKeyFromItem,
|
|
534
|
-
localQueryStore,
|
|
535
|
-
item,
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
function insertAtPositionInPages(options) {
|
|
540
|
-
const { pageQueries, sortOrder, sortKeyFromItem, localQueryStore, item, paginatedQuery, } = options;
|
|
541
|
-
const insertedKey = sortKeyFromItem(item);
|
|
542
|
-
const loadedPages = pageQueries.filter((q) => q.value !== undefined && q.value.page.length > 0);
|
|
543
|
-
const sortedPages = loadedPages.sort((a, b) => {
|
|
544
|
-
const aKey = sortKeyFromItem(a.value.page[0]);
|
|
545
|
-
const bKey = sortKeyFromItem(b.value.page[0]);
|
|
546
|
-
if (sortOrder === "asc") {
|
|
547
|
-
return compareValues(aKey, bKey);
|
|
548
|
-
}
|
|
549
|
-
else {
|
|
550
|
-
return compareValues(bKey, aKey);
|
|
551
|
-
}
|
|
552
|
-
});
|
|
553
|
-
// check if the inserted element is before the first page
|
|
554
|
-
const firstLoadedPage = sortedPages[0];
|
|
555
|
-
if (firstLoadedPage === undefined) {
|
|
556
|
-
// no pages, so don't update until they load
|
|
557
|
-
return;
|
|
558
|
-
}
|
|
559
|
-
const firstPageKey = sortKeyFromItem(firstLoadedPage.value.page[0]);
|
|
560
|
-
const isBeforeFirstPage = sortOrder === "asc"
|
|
561
|
-
? compareValues(insertedKey, firstPageKey) <= 0
|
|
562
|
-
: compareValues(insertedKey, firstPageKey) >= 0;
|
|
563
|
-
if (isBeforeFirstPage) {
|
|
564
|
-
if (firstLoadedPage.args.paginationOpts.cursor === null) {
|
|
565
|
-
localQueryStore.setQuery(paginatedQuery, firstLoadedPage.args, {
|
|
566
|
-
...firstLoadedPage.value,
|
|
567
|
-
page: [item, ...firstLoadedPage.value.page],
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
else {
|
|
571
|
-
// if the very first page is not loaded
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
return;
|
|
575
|
-
}
|
|
576
|
-
const lastLoadedPage = sortedPages[sortedPages.length - 1];
|
|
577
|
-
if (lastLoadedPage === undefined) {
|
|
578
|
-
// no pages, so don't update until they load
|
|
579
|
-
return;
|
|
580
|
-
}
|
|
581
|
-
const lastPageKey = sortKeyFromItem(lastLoadedPage.value.page[lastLoadedPage.value.page.length - 1]);
|
|
582
|
-
const isAfterLastPage = sortOrder === "asc"
|
|
583
|
-
? compareValues(insertedKey, lastPageKey) >= 0
|
|
584
|
-
: compareValues(insertedKey, lastPageKey) <= 0;
|
|
585
|
-
if (isAfterLastPage) {
|
|
586
|
-
// Only update if the last page is done loading, otherwise it will pop out
|
|
587
|
-
// when the server updates the query
|
|
588
|
-
if (lastLoadedPage.value.isDone) {
|
|
589
|
-
localQueryStore.setQuery(paginatedQuery, lastLoadedPage.args, {
|
|
590
|
-
...lastLoadedPage.value,
|
|
591
|
-
page: [...lastLoadedPage.value.page, item],
|
|
592
|
-
});
|
|
593
|
-
}
|
|
594
|
-
return;
|
|
595
|
-
}
|
|
596
|
-
// if sorted in ascending order, find the first page that starts with a key greater than the inserted element,
|
|
597
|
-
// and update the page before it
|
|
598
|
-
// if sorted in descending order, find the first page that starts with a key less than the inserted element,
|
|
599
|
-
// and update the page before it
|
|
600
|
-
const successorPageIndex = sortedPages.findIndex((p) => sortOrder === "asc"
|
|
601
|
-
? compareValues(sortKeyFromItem(p.value.page[0]), insertedKey) > 0
|
|
602
|
-
: compareValues(sortKeyFromItem(p.value.page[0]), insertedKey) < 0);
|
|
603
|
-
const pageToUpdate = successorPageIndex === -1
|
|
604
|
-
? sortedPages[sortedPages.length - 1]
|
|
605
|
-
: sortedPages[successorPageIndex - 1];
|
|
606
|
-
if (pageToUpdate === undefined) {
|
|
607
|
-
// no pages, so don't update until they load
|
|
608
|
-
return;
|
|
609
|
-
}
|
|
610
|
-
// If ascending, find the first element that is greater than or equal to the inserted element
|
|
611
|
-
// If descending, find the first element that is less than or equal to the inserted element
|
|
612
|
-
const indexWithinPage = pageToUpdate.value.page.findIndex((e) => sortOrder === "asc"
|
|
613
|
-
? compareValues(sortKeyFromItem(e), insertedKey) >= 0
|
|
614
|
-
: compareValues(sortKeyFromItem(e), insertedKey) <= 0);
|
|
615
|
-
const newPage = indexWithinPage === -1
|
|
616
|
-
? [...pageToUpdate.value.page, item]
|
|
617
|
-
: [
|
|
618
|
-
...pageToUpdate.value.page.slice(0, indexWithinPage),
|
|
619
|
-
item,
|
|
620
|
-
...pageToUpdate.value.page.slice(indexWithinPage),
|
|
621
|
-
];
|
|
622
|
-
localQueryStore.setQuery(paginatedQuery, pageToUpdate.args, {
|
|
623
|
-
...pageToUpdate.value,
|
|
624
|
-
page: newPage,
|
|
625
|
-
});
|
|
626
|
-
}
|
|
627
|
-
//# sourceMappingURL=usePaginatedQuery.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usePaginatedQuery.js","sourceRoot":"","sources":["../../../src/react/usePaginatedQuery.ts"],"names":[],"mappings":"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"}
|