convex 1.27.3 → 1.27.4-alpha.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/browser.bundle.js +499 -19
- package/dist/browser.bundle.js.map +4 -4
- package/dist/cjs/browser/index.js.map +2 -2
- package/dist/cjs/browser/simple_client.js +115 -15
- package/dist/cjs/browser/simple_client.js.map +3 -3
- package/dist/cjs/browser/sync/client.js +2 -2
- package/dist/cjs/browser/sync/client.js.map +2 -2
- package/dist/cjs/browser/sync/local_state.js.map +2 -2
- package/dist/cjs/browser/sync/optimistic_updates_impl.js +8 -1
- package/dist/cjs/browser/sync/optimistic_updates_impl.js.map +2 -2
- package/dist/cjs/browser/sync/paginated_query_client.js +381 -0
- package/dist/cjs/browser/sync/paginated_query_client.js.map +7 -0
- package/dist/cjs/browser/sync/pagination.js +37 -0
- package/dist/cjs/browser/sync/pagination.js.map +7 -0
- package/dist/cjs/browser/sync/udf_path_utils.js +16 -1
- package/dist/cjs/browser/sync/udf_path_utils.js.map +2 -2
- package/dist/cjs/cli/lib/components/definition/bundle.js +51 -8
- package/dist/cjs/cli/lib/components/definition/bundle.js.map +2 -2
- package/dist/cjs/cli/lib/components/definition/directoryStructure.js +12 -12
- package/dist/cjs/cli/lib/components/definition/directoryStructure.js.map +2 -2
- package/dist/cjs/cli/lib/components.js +1 -1
- package/dist/cjs/cli/lib/components.js.map +2 -2
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react/client.js +89 -1
- package/dist/cjs/react/client.js.map +2 -2
- package/dist/cjs/react/index.js +4 -0
- package/dist/cjs/react/index.js.map +2 -2
- package/dist/cjs/react/queries_observer.js +36 -11
- package/dist/cjs/react/queries_observer.js.map +2 -2
- package/dist/cjs/react/use_paginated_query2.js +124 -0
- package/dist/cjs/react/use_paginated_query2.js.map +7 -0
- package/dist/cjs/react/use_queries.js +9 -2
- package/dist/cjs/react/use_queries.js.map +2 -2
- package/dist/cjs/react-clerk/ConvexProviderWithClerk.js +1 -1
- package/dist/cjs/react-clerk/ConvexProviderWithClerk.js.map +2 -2
- package/dist/cjs/values/validators.js +1 -1
- package/dist/cjs/values/validators.js.map +2 -2
- package/dist/cjs-types/browser/index.d.ts +2 -1
- package/dist/cjs-types/browser/index.d.ts.map +1 -1
- package/dist/cjs-types/browser/simple_client.d.ts +20 -1
- package/dist/cjs-types/browser/simple_client.d.ts.map +1 -1
- package/dist/cjs-types/browser/sync/client.d.ts.map +1 -1
- package/dist/cjs-types/browser/sync/client_node_test_helpers.d.ts +5 -4
- package/dist/cjs-types/browser/sync/client_node_test_helpers.d.ts.map +1 -1
- package/dist/cjs-types/browser/sync/local_state.d.ts +12 -1
- package/dist/cjs-types/browser/sync/local_state.d.ts.map +1 -1
- package/dist/cjs-types/browser/sync/optimistic_updates_impl.d.ts.map +1 -1
- package/dist/cjs-types/browser/sync/paginated_query_client.d.ts +71 -0
- package/dist/cjs-types/browser/sync/paginated_query_client.d.ts.map +1 -0
- package/dist/cjs-types/browser/sync/paginated_query_client.test.d.ts +2 -0
- package/dist/cjs-types/browser/sync/paginated_query_client.test.d.ts.map +1 -0
- package/dist/cjs-types/browser/sync/pagination.d.ts +23 -0
- package/dist/cjs-types/browser/sync/pagination.d.ts.map +1 -0
- package/dist/cjs-types/browser/sync/udf_path_utils.d.ts +22 -1
- package/dist/cjs-types/browser/sync/udf_path_utils.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/components/definition/bundle.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/components/definition/directoryStructure.d.ts +4 -0
- package/dist/cjs-types/cli/lib/components/definition/directoryStructure.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/components.d.ts.map +1 -1
- package/dist/cjs-types/index.d.ts +1 -1
- package/dist/cjs-types/index.d.ts.map +1 -1
- package/dist/cjs-types/react/client.d.ts +65 -1
- package/dist/cjs-types/react/client.d.ts.map +1 -1
- package/dist/cjs-types/react/index.d.ts +2 -0
- package/dist/cjs-types/react/index.d.ts.map +1 -1
- package/dist/cjs-types/react/queries_observer.d.ts +12 -6
- package/dist/cjs-types/react/queries_observer.d.ts.map +1 -1
- package/dist/cjs-types/react/use_paginated_query2.d.ts +51 -0
- package/dist/cjs-types/react/use_paginated_query2.d.ts.map +1 -0
- package/dist/cjs-types/react/use_queries.d.ts +2 -0
- package/dist/cjs-types/react/use_queries.d.ts.map +1 -1
- package/dist/cli.bundle.cjs +75 -25
- package/dist/cli.bundle.cjs.map +3 -3
- package/dist/esm/browser/index.js.map +2 -2
- package/dist/esm/browser/simple_client.js +117 -15
- package/dist/esm/browser/simple_client.js.map +3 -3
- package/dist/esm/browser/sync/client.js +2 -2
- package/dist/esm/browser/sync/client.js.map +2 -2
- package/dist/esm/browser/sync/local_state.js.map +2 -2
- package/dist/esm/browser/sync/optimistic_updates_impl.js +8 -1
- package/dist/esm/browser/sync/optimistic_updates_impl.js.map +2 -2
- package/dist/esm/browser/sync/paginated_query_client.js +365 -0
- package/dist/esm/browser/sync/paginated_query_client.js.map +7 -0
- package/dist/esm/browser/sync/pagination.js +14 -0
- package/dist/esm/browser/sync/pagination.js.map +7 -0
- package/dist/esm/browser/sync/udf_path_utils.js +13 -0
- package/dist/esm/browser/sync/udf_path_utils.js.map +2 -2
- package/dist/esm/cli/lib/components/definition/bundle.js +51 -8
- package/dist/esm/cli/lib/components/definition/bundle.js.map +2 -2
- package/dist/esm/cli/lib/components/definition/directoryStructure.js +12 -12
- package/dist/esm/cli/lib/components/definition/directoryStructure.js.map +2 -2
- package/dist/esm/cli/lib/components.js +1 -1
- package/dist/esm/cli/lib/components.js.map +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react/client.js +91 -1
- package/dist/esm/react/client.js.map +2 -2
- package/dist/esm/react/index.js +2 -0
- package/dist/esm/react/index.js.map +2 -2
- package/dist/esm/react/queries_observer.js +36 -11
- package/dist/esm/react/queries_observer.js.map +2 -2
- package/dist/esm/react/use_paginated_query2.js +101 -0
- package/dist/esm/react/use_paginated_query2.js.map +7 -0
- package/dist/esm/react/use_queries.js +9 -2
- package/dist/esm/react/use_queries.js.map +2 -2
- package/dist/esm/react-clerk/ConvexProviderWithClerk.js +1 -1
- package/dist/esm/react-clerk/ConvexProviderWithClerk.js.map +2 -2
- package/dist/esm/values/validators.js +1 -1
- package/dist/esm/values/validators.js.map +2 -2
- package/dist/esm-types/browser/index.d.ts +2 -1
- package/dist/esm-types/browser/index.d.ts.map +1 -1
- package/dist/esm-types/browser/simple_client.d.ts +20 -1
- package/dist/esm-types/browser/simple_client.d.ts.map +1 -1
- package/dist/esm-types/browser/sync/client.d.ts.map +1 -1
- package/dist/esm-types/browser/sync/client_node_test_helpers.d.ts +5 -4
- package/dist/esm-types/browser/sync/client_node_test_helpers.d.ts.map +1 -1
- package/dist/esm-types/browser/sync/local_state.d.ts +12 -1
- package/dist/esm-types/browser/sync/local_state.d.ts.map +1 -1
- package/dist/esm-types/browser/sync/optimistic_updates_impl.d.ts.map +1 -1
- package/dist/esm-types/browser/sync/paginated_query_client.d.ts +71 -0
- package/dist/esm-types/browser/sync/paginated_query_client.d.ts.map +1 -0
- package/dist/esm-types/browser/sync/paginated_query_client.test.d.ts +2 -0
- package/dist/esm-types/browser/sync/paginated_query_client.test.d.ts.map +1 -0
- package/dist/esm-types/browser/sync/pagination.d.ts +23 -0
- package/dist/esm-types/browser/sync/pagination.d.ts.map +1 -0
- package/dist/esm-types/browser/sync/udf_path_utils.d.ts +22 -1
- package/dist/esm-types/browser/sync/udf_path_utils.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/components/definition/bundle.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/components/definition/directoryStructure.d.ts +4 -0
- package/dist/esm-types/cli/lib/components/definition/directoryStructure.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/components.d.ts.map +1 -1
- package/dist/esm-types/index.d.ts +1 -1
- package/dist/esm-types/index.d.ts.map +1 -1
- package/dist/esm-types/react/client.d.ts +65 -1
- package/dist/esm-types/react/client.d.ts.map +1 -1
- package/dist/esm-types/react/index.d.ts +2 -0
- package/dist/esm-types/react/index.d.ts.map +1 -1
- package/dist/esm-types/react/queries_observer.d.ts +12 -6
- package/dist/esm-types/react/queries_observer.d.ts.map +1 -1
- package/dist/esm-types/react/use_paginated_query2.d.ts +51 -0
- package/dist/esm-types/react/use_paginated_query2.d.ts.map +1 -0
- package/dist/esm-types/react/use_queries.d.ts +2 -0
- package/dist/esm-types/react/use_queries.d.ts.map +1 -1
- package/dist/react.bundle.js +627 -35
- package/dist/react.bundle.js.map +4 -4
- package/package.json +1 -1
- package/src/browser/index.ts +2 -1
- package/src/browser/simple_client.ts +161 -21
- package/src/browser/sync/client.ts +12 -3
- package/src/browser/sync/client_node_test_helpers.ts +30 -8
- package/src/browser/sync/local_state.ts +13 -1
- package/src/browser/sync/optimistic_updates_impl.ts +9 -2
- package/src/browser/sync/paginated_query_client.test.ts +389 -0
- package/src/browser/sync/paginated_query_client.ts +564 -0
- package/src/browser/sync/pagination.ts +50 -0
- package/src/browser/sync/udf_path_utils.ts +36 -2
- package/src/cli/lib/components/definition/bundle.ts +63 -8
- package/src/cli/lib/components/definition/directoryStructure.ts +16 -11
- package/src/cli/lib/components.ts +4 -1
- package/src/index.ts +1 -1
- package/src/react/client.ts +169 -4
- package/src/react/index.ts +2 -0
- package/src/react/queries_observer.test.ts +1 -1
- package/src/react/queries_observer.ts +75 -24
- package/src/react/use_paginated_query.test.tsx +979 -912
- package/src/react/use_paginated_query2.ts +232 -0
- package/src/react/use_queries.ts +14 -2
- package/src/react-clerk/ConvexProviderWithClerk.tsx +1 -1
- package/src/values/validators.ts +1 -1
- package/src/browser/.claude/settings.local.json +0 -11
package/dist/browser.bundle.js
CHANGED
|
@@ -28,7 +28,7 @@ var convex = (() => {
|
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
// src/index.ts
|
|
31
|
-
var version = "1.27.
|
|
31
|
+
var version = "1.27.4-alpha.0";
|
|
32
32
|
|
|
33
33
|
// src/values/base64.ts
|
|
34
34
|
var base64_exports = {};
|
|
@@ -613,6 +613,19 @@ var convex = (() => {
|
|
|
613
613
|
args: convexToJson(args)
|
|
614
614
|
});
|
|
615
615
|
}
|
|
616
|
+
function serializePaginatedPathAndArgs(udfPath, args, options) {
|
|
617
|
+
const { initialNumItems, id } = options;
|
|
618
|
+
const result = JSON.stringify({
|
|
619
|
+
type: "paginated",
|
|
620
|
+
udfPath: canonicalizeUdfPath(udfPath),
|
|
621
|
+
args: convexToJson(args),
|
|
622
|
+
options: convexToJson({ initialNumItems, id })
|
|
623
|
+
});
|
|
624
|
+
return result;
|
|
625
|
+
}
|
|
626
|
+
function serializedQueryTokenIsPaginated(token) {
|
|
627
|
+
return JSON.parse(token).type === "paginated";
|
|
628
|
+
}
|
|
616
629
|
|
|
617
630
|
// src/browser/sync/local_state.ts
|
|
618
631
|
var LocalSyncState = class {
|
|
@@ -1295,10 +1308,17 @@ var convex = (() => {
|
|
|
1295
1308
|
return localStore.modifiedQueries;
|
|
1296
1309
|
}
|
|
1297
1310
|
/**
|
|
1311
|
+
* "Raw" with respect to errors vs values, but query results still have
|
|
1312
|
+
* optimistic updates applied.
|
|
1313
|
+
*
|
|
1298
1314
|
* @internal
|
|
1299
1315
|
*/
|
|
1300
1316
|
rawQueryResult(queryToken) {
|
|
1301
|
-
|
|
1317
|
+
const query = this.queryResults.get(queryToken);
|
|
1318
|
+
if (query === void 0) {
|
|
1319
|
+
return void 0;
|
|
1320
|
+
}
|
|
1321
|
+
return query.result;
|
|
1302
1322
|
}
|
|
1303
1323
|
queryResult(queryToken) {
|
|
1304
1324
|
const query = this.queryResults.get(queryToken);
|
|
@@ -2744,7 +2764,7 @@ var convex = (() => {
|
|
|
2744
2764
|
token,
|
|
2745
2765
|
modification: {
|
|
2746
2766
|
kind: "Updated",
|
|
2747
|
-
result: optimisticResult
|
|
2767
|
+
result: optimisticResult
|
|
2748
2768
|
}
|
|
2749
2769
|
};
|
|
2750
2770
|
}),
|
|
@@ -2857,7 +2877,7 @@ var convex = (() => {
|
|
|
2857
2877
|
return this.optimisticQueryResults.queryResult(queryToken);
|
|
2858
2878
|
}
|
|
2859
2879
|
/**
|
|
2860
|
-
* Whether local query result is available for a
|
|
2880
|
+
* Whether local query result is available for a token.
|
|
2861
2881
|
*
|
|
2862
2882
|
* This method does not throw if the result is an error.
|
|
2863
2883
|
*
|
|
@@ -3158,11 +3178,374 @@ var convex = (() => {
|
|
|
3158
3178
|
}
|
|
3159
3179
|
};
|
|
3160
3180
|
|
|
3181
|
+
// src/browser/sync/pagination.ts
|
|
3182
|
+
function asPaginationResult(value) {
|
|
3183
|
+
if (typeof value !== "object" || value === null || !Array.isArray(value.page) || typeof value.isDone !== "boolean" || typeof value.continueCursor !== "string") {
|
|
3184
|
+
throw new Error(`Not a valid paginated query result: ${value?.toString()}`);
|
|
3185
|
+
}
|
|
3186
|
+
return value;
|
|
3187
|
+
}
|
|
3188
|
+
|
|
3189
|
+
// src/browser/sync/paginated_query_client.ts
|
|
3190
|
+
var PaginatedQueryClient = class {
|
|
3191
|
+
constructor(client, onTransition) {
|
|
3192
|
+
this.client = client;
|
|
3193
|
+
this.onTransition = onTransition;
|
|
3194
|
+
this.lastTransitionTs = Long.fromNumber(0);
|
|
3195
|
+
this.client.addOnTransitionHandler(
|
|
3196
|
+
(transition) => this.onBaseTransition(transition)
|
|
3197
|
+
);
|
|
3198
|
+
}
|
|
3199
|
+
paginatedQuerySet = /* @__PURE__ */ new Map();
|
|
3200
|
+
// hold onto a real Transition so we can construct synthetic ones with that timestamp
|
|
3201
|
+
lastTransitionTs;
|
|
3202
|
+
/**
|
|
3203
|
+
* Subscribe to a paginated query.
|
|
3204
|
+
*
|
|
3205
|
+
* @param name - The name of the paginated query function
|
|
3206
|
+
* @param args - Arguments for the query (excluding paginationOpts)
|
|
3207
|
+
* @param options - Pagination options including initialNumItems
|
|
3208
|
+
* @returns Object with paginatedQueryToken and unsubscribe function
|
|
3209
|
+
*/
|
|
3210
|
+
subscribe(name, args, options) {
|
|
3211
|
+
const canonicalizedUdfPath = canonicalizeUdfPath(name);
|
|
3212
|
+
const token = serializePaginatedPathAndArgs(
|
|
3213
|
+
canonicalizedUdfPath,
|
|
3214
|
+
args,
|
|
3215
|
+
options
|
|
3216
|
+
);
|
|
3217
|
+
const unsubscribe = () => this.removePaginatedQuerySubscriber(token);
|
|
3218
|
+
const existingEntry = this.paginatedQuerySet.get(token);
|
|
3219
|
+
if (existingEntry) {
|
|
3220
|
+
existingEntry.numSubscribers += 1;
|
|
3221
|
+
return {
|
|
3222
|
+
paginatedQueryToken: token,
|
|
3223
|
+
unsubscribe
|
|
3224
|
+
};
|
|
3225
|
+
}
|
|
3226
|
+
this.paginatedQuerySet.set(token, {
|
|
3227
|
+
token,
|
|
3228
|
+
canonicalizedUdfPath,
|
|
3229
|
+
args,
|
|
3230
|
+
numSubscribers: 1,
|
|
3231
|
+
options: { initialNumItems: options.initialNumItems },
|
|
3232
|
+
nextPageKey: 0,
|
|
3233
|
+
pageKeys: [],
|
|
3234
|
+
pageKeyToQuery: /* @__PURE__ */ new Map(),
|
|
3235
|
+
ongoingSplits: /* @__PURE__ */ new Map(),
|
|
3236
|
+
skip: false,
|
|
3237
|
+
id: options.id
|
|
3238
|
+
});
|
|
3239
|
+
this.addPageToPaginatedQuery(token, null, options.initialNumItems);
|
|
3240
|
+
return {
|
|
3241
|
+
paginatedQueryToken: token,
|
|
3242
|
+
unsubscribe
|
|
3243
|
+
};
|
|
3244
|
+
}
|
|
3245
|
+
/**
|
|
3246
|
+
* Get current results for a paginated query based on local state.
|
|
3247
|
+
*
|
|
3248
|
+
* Throws an error when one of the pages has errored.
|
|
3249
|
+
*/
|
|
3250
|
+
localPaginatedQueryResult(name, args, options) {
|
|
3251
|
+
const canonicalizedUdfPath = canonicalizeUdfPath(name);
|
|
3252
|
+
const token = serializePaginatedPathAndArgs(
|
|
3253
|
+
canonicalizedUdfPath,
|
|
3254
|
+
args,
|
|
3255
|
+
options
|
|
3256
|
+
);
|
|
3257
|
+
return this.localPaginatedQueryResultByToken(token);
|
|
3258
|
+
}
|
|
3259
|
+
/**
|
|
3260
|
+
* @internal
|
|
3261
|
+
*/
|
|
3262
|
+
localPaginatedQueryResultByToken(token) {
|
|
3263
|
+
const paginatedQuery = this.paginatedQuerySet.get(token);
|
|
3264
|
+
if (!paginatedQuery) {
|
|
3265
|
+
return void 0;
|
|
3266
|
+
}
|
|
3267
|
+
const activePages = this.activePageQueryTokens(paginatedQuery);
|
|
3268
|
+
if (activePages.length === 0) {
|
|
3269
|
+
return {
|
|
3270
|
+
results: [],
|
|
3271
|
+
status: "LoadingFirstPage",
|
|
3272
|
+
loadMore: (numItems) => {
|
|
3273
|
+
return this.loadMoreOfPaginatedQuery(token, numItems);
|
|
3274
|
+
}
|
|
3275
|
+
};
|
|
3276
|
+
}
|
|
3277
|
+
let allResults = [];
|
|
3278
|
+
let hasUndefined = false;
|
|
3279
|
+
let isDone = false;
|
|
3280
|
+
for (const pageToken of activePages) {
|
|
3281
|
+
const result = this.client.localQueryResultByToken(pageToken);
|
|
3282
|
+
if (result === void 0) {
|
|
3283
|
+
hasUndefined = true;
|
|
3284
|
+
isDone = false;
|
|
3285
|
+
continue;
|
|
3286
|
+
}
|
|
3287
|
+
const paginationResult = asPaginationResult(result);
|
|
3288
|
+
allResults = allResults.concat(paginationResult.page);
|
|
3289
|
+
isDone = !!paginationResult.isDone;
|
|
3290
|
+
}
|
|
3291
|
+
let status;
|
|
3292
|
+
if (hasUndefined) {
|
|
3293
|
+
status = allResults.length === 0 ? "LoadingFirstPage" : "LoadingMore";
|
|
3294
|
+
} else if (isDone) {
|
|
3295
|
+
status = "Exhausted";
|
|
3296
|
+
} else {
|
|
3297
|
+
status = "CanLoadMore";
|
|
3298
|
+
}
|
|
3299
|
+
return {
|
|
3300
|
+
results: allResults,
|
|
3301
|
+
status,
|
|
3302
|
+
loadMore: (numItems) => {
|
|
3303
|
+
return this.loadMoreOfPaginatedQuery(token, numItems);
|
|
3304
|
+
}
|
|
3305
|
+
};
|
|
3306
|
+
}
|
|
3307
|
+
onBaseTransition(transition) {
|
|
3308
|
+
const changedBaseTokens = transition.queries.map((q) => q.token);
|
|
3309
|
+
const changed = this.queriesContainingTokens(changedBaseTokens);
|
|
3310
|
+
let paginatedQueries = [];
|
|
3311
|
+
if (changed.length > 0) {
|
|
3312
|
+
this.processPaginatedQuerySplits(
|
|
3313
|
+
changed,
|
|
3314
|
+
(token) => this.client.localQueryResultByToken(token)
|
|
3315
|
+
);
|
|
3316
|
+
paginatedQueries = changed.map((token) => ({
|
|
3317
|
+
token,
|
|
3318
|
+
modification: {
|
|
3319
|
+
kind: "Updated",
|
|
3320
|
+
result: this.localPaginatedQueryResultByToken(token)
|
|
3321
|
+
}
|
|
3322
|
+
}));
|
|
3323
|
+
}
|
|
3324
|
+
const extendedTransition = {
|
|
3325
|
+
...transition,
|
|
3326
|
+
paginatedQueries
|
|
3327
|
+
};
|
|
3328
|
+
this.onTransition(extendedTransition);
|
|
3329
|
+
}
|
|
3330
|
+
/**
|
|
3331
|
+
* Load more items for a paginated query.
|
|
3332
|
+
*
|
|
3333
|
+
* This *always* causes a transition, the status of the query
|
|
3334
|
+
* has probably changed from "CanLoadMore" to "LoadingMore".
|
|
3335
|
+
* Data might have changed too: maybe a subscription to this page
|
|
3336
|
+
* query already exists (unlikely but possible) or this page query
|
|
3337
|
+
* has an optimistic update providing some initial data.
|
|
3338
|
+
*
|
|
3339
|
+
* @internal
|
|
3340
|
+
*/
|
|
3341
|
+
loadMoreOfPaginatedQuery(token, numItems) {
|
|
3342
|
+
this.mustGetPaginatedQuery(token);
|
|
3343
|
+
const lastPageToken = this.queryTokenForLastPageOfPaginatedQuery(token);
|
|
3344
|
+
const lastPageResult = this.client.localQueryResultByToken(lastPageToken);
|
|
3345
|
+
if (!lastPageResult) {
|
|
3346
|
+
return false;
|
|
3347
|
+
}
|
|
3348
|
+
const paginationResult = asPaginationResult(lastPageResult);
|
|
3349
|
+
if (paginationResult.isDone) {
|
|
3350
|
+
return false;
|
|
3351
|
+
}
|
|
3352
|
+
this.addPageToPaginatedQuery(
|
|
3353
|
+
token,
|
|
3354
|
+
paginationResult.continueCursor,
|
|
3355
|
+
numItems
|
|
3356
|
+
);
|
|
3357
|
+
const loadMoreTransition = {
|
|
3358
|
+
timestamp: this.lastTransitionTs,
|
|
3359
|
+
reflectedMutations: [],
|
|
3360
|
+
queries: [],
|
|
3361
|
+
paginatedQueries: [
|
|
3362
|
+
{
|
|
3363
|
+
token,
|
|
3364
|
+
modification: {
|
|
3365
|
+
kind: "Updated",
|
|
3366
|
+
result: this.localPaginatedQueryResultByToken(token)
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
]
|
|
3370
|
+
};
|
|
3371
|
+
this.onTransition(loadMoreTransition);
|
|
3372
|
+
return true;
|
|
3373
|
+
}
|
|
3374
|
+
/**
|
|
3375
|
+
* @internal
|
|
3376
|
+
*/
|
|
3377
|
+
queriesContainingTokens(queryTokens) {
|
|
3378
|
+
if (queryTokens.length === 0) {
|
|
3379
|
+
return [];
|
|
3380
|
+
}
|
|
3381
|
+
const changed = [];
|
|
3382
|
+
const queryTokenSet = new Set(queryTokens);
|
|
3383
|
+
for (const [paginatedToken, paginatedQuery] of this.paginatedQuerySet) {
|
|
3384
|
+
for (const pageToken of this.allQueryTokens(paginatedQuery)) {
|
|
3385
|
+
if (queryTokenSet.has(pageToken)) {
|
|
3386
|
+
changed.push(paginatedToken);
|
|
3387
|
+
break;
|
|
3388
|
+
}
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3391
|
+
return changed;
|
|
3392
|
+
}
|
|
3393
|
+
/**
|
|
3394
|
+
* @internal
|
|
3395
|
+
*/
|
|
3396
|
+
processPaginatedQuerySplits(changed, getResult) {
|
|
3397
|
+
for (const paginatedQueryToken of changed) {
|
|
3398
|
+
const paginatedQuery = this.mustGetPaginatedQuery(paginatedQueryToken);
|
|
3399
|
+
const { ongoingSplits, pageKeyToQuery, pageKeys } = paginatedQuery;
|
|
3400
|
+
for (const [pageKey, [splitKey1, splitKey2]] of ongoingSplits) {
|
|
3401
|
+
const bothNewPagesLoaded = getResult(pageKeyToQuery.get(splitKey1).queryToken) !== void 0 && getResult(pageKeyToQuery.get(splitKey2).queryToken) !== void 0;
|
|
3402
|
+
if (bothNewPagesLoaded) {
|
|
3403
|
+
this.completePaginatedQuerySplit(
|
|
3404
|
+
paginatedQuery,
|
|
3405
|
+
pageKey,
|
|
3406
|
+
splitKey1,
|
|
3407
|
+
splitKey2
|
|
3408
|
+
);
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
for (const pageKey of pageKeys) {
|
|
3412
|
+
if (ongoingSplits.has(pageKey)) {
|
|
3413
|
+
continue;
|
|
3414
|
+
}
|
|
3415
|
+
const pageToken = pageKeyToQuery.get(pageKey).queryToken;
|
|
3416
|
+
const pageResult = getResult(pageToken);
|
|
3417
|
+
if (!pageResult) {
|
|
3418
|
+
continue;
|
|
3419
|
+
}
|
|
3420
|
+
const result = asPaginationResult(pageResult);
|
|
3421
|
+
const shouldSplit = result.splitCursor && (result.pageStatus === "SplitRecommended" || result.pageStatus === "SplitRequired" || // This client-driven page splitting condition will change in the future.
|
|
3422
|
+
result.page.length > paginatedQuery.options.initialNumItems * 2);
|
|
3423
|
+
if (shouldSplit) {
|
|
3424
|
+
this.splitPaginatedQueryPage(
|
|
3425
|
+
paginatedQuery,
|
|
3426
|
+
pageKey,
|
|
3427
|
+
result.splitCursor,
|
|
3428
|
+
// we just checked
|
|
3429
|
+
result.continueCursor
|
|
3430
|
+
);
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
3435
|
+
splitPaginatedQueryPage(paginatedQuery, pageKey, splitCursor, continueCursor) {
|
|
3436
|
+
const splitKey1 = paginatedQuery.nextPageKey++;
|
|
3437
|
+
const splitKey2 = paginatedQuery.nextPageKey++;
|
|
3438
|
+
const paginationOpts = {
|
|
3439
|
+
cursor: continueCursor,
|
|
3440
|
+
numItems: paginatedQuery.options.initialNumItems,
|
|
3441
|
+
id: paginatedQuery.id
|
|
3442
|
+
};
|
|
3443
|
+
const firstSubscription = this.client.subscribe(
|
|
3444
|
+
paginatedQuery.canonicalizedUdfPath,
|
|
3445
|
+
{
|
|
3446
|
+
...paginatedQuery.args,
|
|
3447
|
+
paginationOpts: {
|
|
3448
|
+
...paginationOpts,
|
|
3449
|
+
cursor: null,
|
|
3450
|
+
// Start from beginning for first split
|
|
3451
|
+
endCursor: splitCursor
|
|
3452
|
+
}
|
|
3453
|
+
}
|
|
3454
|
+
);
|
|
3455
|
+
paginatedQuery.pageKeyToQuery.set(splitKey1, firstSubscription);
|
|
3456
|
+
const secondSubscription = this.client.subscribe(
|
|
3457
|
+
paginatedQuery.canonicalizedUdfPath,
|
|
3458
|
+
{
|
|
3459
|
+
...paginatedQuery.args,
|
|
3460
|
+
paginationOpts: {
|
|
3461
|
+
...paginationOpts,
|
|
3462
|
+
cursor: splitCursor,
|
|
3463
|
+
endCursor: continueCursor
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
);
|
|
3467
|
+
paginatedQuery.pageKeyToQuery.set(splitKey2, secondSubscription);
|
|
3468
|
+
paginatedQuery.ongoingSplits.set(pageKey, [splitKey1, splitKey2]);
|
|
3469
|
+
}
|
|
3470
|
+
/**
|
|
3471
|
+
* @internal
|
|
3472
|
+
*/
|
|
3473
|
+
addPageToPaginatedQuery(token, continueCursor, numItems) {
|
|
3474
|
+
const paginatedQuery = this.mustGetPaginatedQuery(token);
|
|
3475
|
+
const pageKey = paginatedQuery.nextPageKey++;
|
|
3476
|
+
const paginationOpts = {
|
|
3477
|
+
cursor: continueCursor,
|
|
3478
|
+
numItems,
|
|
3479
|
+
id: paginatedQuery.id
|
|
3480
|
+
};
|
|
3481
|
+
const pageArgs = {
|
|
3482
|
+
...paginatedQuery.args,
|
|
3483
|
+
paginationOpts
|
|
3484
|
+
};
|
|
3485
|
+
const subscription = this.client.subscribe(
|
|
3486
|
+
paginatedQuery.canonicalizedUdfPath,
|
|
3487
|
+
pageArgs
|
|
3488
|
+
);
|
|
3489
|
+
paginatedQuery.pageKeys.push(pageKey);
|
|
3490
|
+
paginatedQuery.pageKeyToQuery.set(pageKey, subscription);
|
|
3491
|
+
return subscription;
|
|
3492
|
+
}
|
|
3493
|
+
removePaginatedQuerySubscriber(token) {
|
|
3494
|
+
const paginatedQuery = this.paginatedQuerySet.get(token);
|
|
3495
|
+
if (!paginatedQuery) {
|
|
3496
|
+
return;
|
|
3497
|
+
}
|
|
3498
|
+
paginatedQuery.numSubscribers -= 1;
|
|
3499
|
+
if (paginatedQuery.numSubscribers > 0) {
|
|
3500
|
+
return;
|
|
3501
|
+
}
|
|
3502
|
+
for (const subscription of paginatedQuery.pageKeyToQuery.values()) {
|
|
3503
|
+
subscription.unsubscribe();
|
|
3504
|
+
}
|
|
3505
|
+
this.paginatedQuerySet.delete(token);
|
|
3506
|
+
}
|
|
3507
|
+
completePaginatedQuerySplit(paginatedQuery, pageKey, splitKey1, splitKey2) {
|
|
3508
|
+
const originalQuery = paginatedQuery.pageKeyToQuery.get(pageKey);
|
|
3509
|
+
paginatedQuery.pageKeyToQuery.delete(pageKey);
|
|
3510
|
+
const pageIndex = paginatedQuery.pageKeys.indexOf(pageKey);
|
|
3511
|
+
paginatedQuery.pageKeys.splice(pageIndex, 1, splitKey1, splitKey2);
|
|
3512
|
+
paginatedQuery.ongoingSplits.delete(pageKey);
|
|
3513
|
+
originalQuery.unsubscribe();
|
|
3514
|
+
}
|
|
3515
|
+
/** The query tokens for all active pages, in result order */
|
|
3516
|
+
activePageQueryTokens(paginatedQuery) {
|
|
3517
|
+
return paginatedQuery.pageKeys.map(
|
|
3518
|
+
(pageKey) => paginatedQuery.pageKeyToQuery.get(pageKey).queryToken
|
|
3519
|
+
);
|
|
3520
|
+
}
|
|
3521
|
+
allQueryTokens(paginatedQuery) {
|
|
3522
|
+
return Array.from(paginatedQuery.pageKeyToQuery.values()).map(
|
|
3523
|
+
(sub) => sub.queryToken
|
|
3524
|
+
);
|
|
3525
|
+
}
|
|
3526
|
+
queryTokenForLastPageOfPaginatedQuery(token) {
|
|
3527
|
+
const paginatedQuery = this.mustGetPaginatedQuery(token);
|
|
3528
|
+
const lastPageKey = paginatedQuery.pageKeys[paginatedQuery.pageKeys.length - 1];
|
|
3529
|
+
if (lastPageKey === void 0) {
|
|
3530
|
+
throw new Error(`No pages for paginated query ${token}`);
|
|
3531
|
+
}
|
|
3532
|
+
return paginatedQuery.pageKeyToQuery.get(lastPageKey).queryToken;
|
|
3533
|
+
}
|
|
3534
|
+
mustGetPaginatedQuery(token) {
|
|
3535
|
+
const paginatedQuery = this.paginatedQuerySet.get(token);
|
|
3536
|
+
if (!paginatedQuery) {
|
|
3537
|
+
throw new Error("paginated query no longer exists for token " + token);
|
|
3538
|
+
}
|
|
3539
|
+
return paginatedQuery;
|
|
3540
|
+
}
|
|
3541
|
+
};
|
|
3542
|
+
|
|
3161
3543
|
// src/browser/simple_client.ts
|
|
3162
3544
|
var defaultWebSocketConstructor;
|
|
3163
3545
|
var ConvexClient = class {
|
|
3164
3546
|
listeners;
|
|
3165
3547
|
_client;
|
|
3548
|
+
_paginatedClient;
|
|
3166
3549
|
// A synthetic server event to run callbacks the first time
|
|
3167
3550
|
callNewListenersWithCurrentValuesTimer;
|
|
3168
3551
|
_closed;
|
|
@@ -3177,6 +3560,10 @@ var convex = (() => {
|
|
|
3177
3560
|
if (this._client) return this._client;
|
|
3178
3561
|
throw new Error("ConvexClient is disabled");
|
|
3179
3562
|
}
|
|
3563
|
+
get paginatedClient() {
|
|
3564
|
+
if (this._paginatedClient) return this._paginatedClient;
|
|
3565
|
+
throw new Error("ConvexClient is disabled");
|
|
3566
|
+
}
|
|
3180
3567
|
get disabled() {
|
|
3181
3568
|
return this._disabled;
|
|
3182
3569
|
}
|
|
@@ -3201,9 +3588,15 @@ var convex = (() => {
|
|
|
3201
3588
|
if (!this.disabled) {
|
|
3202
3589
|
this._client = new BaseConvexClient(
|
|
3203
3590
|
address,
|
|
3204
|
-
(
|
|
3591
|
+
() => {
|
|
3592
|
+
},
|
|
3593
|
+
// NOP, let the paginated query client do it all
|
|
3205
3594
|
baseOptions
|
|
3206
3595
|
);
|
|
3596
|
+
this._paginatedClient = new PaginatedQueryClient(
|
|
3597
|
+
this._client,
|
|
3598
|
+
(transition) => this._transition(transition)
|
|
3599
|
+
);
|
|
3207
3600
|
}
|
|
3208
3601
|
this.listeners = /* @__PURE__ */ new Set();
|
|
3209
3602
|
}
|
|
@@ -3241,15 +3634,7 @@ var convex = (() => {
|
|
|
3241
3634
|
*/
|
|
3242
3635
|
onUpdate(query, args, callback, onError) {
|
|
3243
3636
|
if (this.disabled) {
|
|
3244
|
-
|
|
3245
|
-
};
|
|
3246
|
-
const unsubscribeProps2 = {
|
|
3247
|
-
unsubscribe: disabledUnsubscribe,
|
|
3248
|
-
getCurrentValue: () => void 0,
|
|
3249
|
-
getQueryLogs: () => void 0
|
|
3250
|
-
};
|
|
3251
|
-
Object.assign(disabledUnsubscribe, unsubscribeProps2);
|
|
3252
|
-
return disabledUnsubscribe;
|
|
3637
|
+
return this.createDisabledUnsubscribe();
|
|
3253
3638
|
}
|
|
3254
3639
|
const { queryToken, unsubscribe } = this.client.subscribe(
|
|
3255
3640
|
getFunctionName(query),
|
|
@@ -3262,7 +3647,8 @@ var convex = (() => {
|
|
|
3262
3647
|
unsubscribe,
|
|
3263
3648
|
hasEverRun: false,
|
|
3264
3649
|
query,
|
|
3265
|
-
args
|
|
3650
|
+
args,
|
|
3651
|
+
paginationOptions: void 0
|
|
3266
3652
|
};
|
|
3267
3653
|
this.listeners.add(queryInfo);
|
|
3268
3654
|
if (this.queryResultReady(queryToken) && this.callNewListenersWithCurrentValuesTimer === void 0) {
|
|
@@ -3286,19 +3672,100 @@ var convex = (() => {
|
|
|
3286
3672
|
Object.assign(ret, unsubscribeProps);
|
|
3287
3673
|
return ret;
|
|
3288
3674
|
}
|
|
3675
|
+
/**
|
|
3676
|
+
* Call a callback whenever a new result for a paginated query is received.
|
|
3677
|
+
*
|
|
3678
|
+
* @param query - A {@link server.FunctionReference} for the public query to run.
|
|
3679
|
+
* @param args - The arguments to run the query with.
|
|
3680
|
+
* @param options - Options for the paginated query including initialNumItems and id.
|
|
3681
|
+
* @param callback - Function to call when the query result updates.
|
|
3682
|
+
* @param onError - Function to call when the query result updates with an error.
|
|
3683
|
+
*
|
|
3684
|
+
* @return an {@link Unsubscribe} function to stop calling the callback.
|
|
3685
|
+
*/
|
|
3686
|
+
onPaginatedUpdate(query, args, options, callback, onError) {
|
|
3687
|
+
if (this.disabled) {
|
|
3688
|
+
return this.createDisabledUnsubscribe();
|
|
3689
|
+
}
|
|
3690
|
+
const paginationOptions = {
|
|
3691
|
+
initialNumItems: options.initialNumItems,
|
|
3692
|
+
id: -1
|
|
3693
|
+
};
|
|
3694
|
+
const { paginatedQueryToken, unsubscribe } = this.paginatedClient.subscribe(
|
|
3695
|
+
getFunctionName(query),
|
|
3696
|
+
args,
|
|
3697
|
+
// Simple client doesn't use IDs, there's no expectation that these queries remain separate.
|
|
3698
|
+
paginationOptions
|
|
3699
|
+
);
|
|
3700
|
+
const queryInfo = {
|
|
3701
|
+
queryToken: paginatedQueryToken,
|
|
3702
|
+
callback,
|
|
3703
|
+
onError,
|
|
3704
|
+
unsubscribe,
|
|
3705
|
+
hasEverRun: false,
|
|
3706
|
+
query,
|
|
3707
|
+
args,
|
|
3708
|
+
paginationOptions
|
|
3709
|
+
};
|
|
3710
|
+
this.listeners.add(queryInfo);
|
|
3711
|
+
if (!!this.paginatedClient.localPaginatedQueryResultByToken(
|
|
3712
|
+
paginatedQueryToken
|
|
3713
|
+
) && this.callNewListenersWithCurrentValuesTimer === void 0) {
|
|
3714
|
+
this.callNewListenersWithCurrentValuesTimer = setTimeout(
|
|
3715
|
+
() => this.callNewListenersWithCurrentValues(),
|
|
3716
|
+
0
|
|
3717
|
+
);
|
|
3718
|
+
}
|
|
3719
|
+
const unsubscribeProps = {
|
|
3720
|
+
unsubscribe: () => {
|
|
3721
|
+
if (this.closed) {
|
|
3722
|
+
return;
|
|
3723
|
+
}
|
|
3724
|
+
this.listeners.delete(queryInfo);
|
|
3725
|
+
unsubscribe();
|
|
3726
|
+
},
|
|
3727
|
+
getCurrentValue: () => {
|
|
3728
|
+
const result = this.paginatedClient.localPaginatedQueryResult(
|
|
3729
|
+
getFunctionName(query),
|
|
3730
|
+
args,
|
|
3731
|
+
paginationOptions
|
|
3732
|
+
);
|
|
3733
|
+
return result;
|
|
3734
|
+
},
|
|
3735
|
+
getQueryLogs: () => []
|
|
3736
|
+
// Paginated queries don't aggregate their logs
|
|
3737
|
+
};
|
|
3738
|
+
const ret = unsubscribeProps.unsubscribe;
|
|
3739
|
+
Object.assign(ret, unsubscribeProps);
|
|
3740
|
+
return ret;
|
|
3741
|
+
}
|
|
3289
3742
|
// Run all callbacks that have never been run before if they have a query
|
|
3290
3743
|
// result available now.
|
|
3291
3744
|
callNewListenersWithCurrentValues() {
|
|
3292
3745
|
this.callNewListenersWithCurrentValuesTimer = void 0;
|
|
3293
|
-
this._transition([], true);
|
|
3746
|
+
this._transition({ queries: [], paginatedQueries: [] }, true);
|
|
3294
3747
|
}
|
|
3295
3748
|
queryResultReady(queryToken) {
|
|
3296
3749
|
return this.client.hasLocalQueryResultByToken(queryToken);
|
|
3297
3750
|
}
|
|
3751
|
+
createDisabledUnsubscribe() {
|
|
3752
|
+
const disabledUnsubscribe = () => {
|
|
3753
|
+
};
|
|
3754
|
+
const unsubscribeProps = {
|
|
3755
|
+
unsubscribe: disabledUnsubscribe,
|
|
3756
|
+
getCurrentValue: () => void 0,
|
|
3757
|
+
getQueryLogs: () => void 0
|
|
3758
|
+
};
|
|
3759
|
+
Object.assign(disabledUnsubscribe, unsubscribeProps);
|
|
3760
|
+
return disabledUnsubscribe;
|
|
3761
|
+
}
|
|
3298
3762
|
async close() {
|
|
3299
3763
|
if (this.disabled) return;
|
|
3300
3764
|
this.listeners.clear();
|
|
3301
3765
|
this._closed = true;
|
|
3766
|
+
if (this._paginatedClient) {
|
|
3767
|
+
this._paginatedClient = void 0;
|
|
3768
|
+
}
|
|
3302
3769
|
return this.client.close();
|
|
3303
3770
|
}
|
|
3304
3771
|
/**
|
|
@@ -3330,14 +3797,27 @@ var convex = (() => {
|
|
|
3330
3797
|
/**
|
|
3331
3798
|
* @internal
|
|
3332
3799
|
*/
|
|
3333
|
-
_transition(
|
|
3800
|
+
_transition({
|
|
3801
|
+
queries,
|
|
3802
|
+
paginatedQueries
|
|
3803
|
+
}, callNewListeners = false) {
|
|
3804
|
+
const updatedQueries = [
|
|
3805
|
+
...queries.map((q) => q.token),
|
|
3806
|
+
...paginatedQueries.map((q) => q.token)
|
|
3807
|
+
];
|
|
3334
3808
|
for (const queryInfo of this.listeners) {
|
|
3335
3809
|
const { callback, queryToken, onError, hasEverRun } = queryInfo;
|
|
3336
|
-
|
|
3810
|
+
const isPaginatedQuery = serializedQueryTokenIsPaginated(queryToken);
|
|
3811
|
+
const hasResultReady = isPaginatedQuery ? !!this.paginatedClient.localPaginatedQueryResultByToken(queryToken) : this.client.hasLocalQueryResultByToken(queryToken);
|
|
3812
|
+
if (updatedQueries.includes(queryToken) || callNewListeners && !hasEverRun && hasResultReady) {
|
|
3337
3813
|
queryInfo.hasEverRun = true;
|
|
3338
3814
|
let newValue;
|
|
3339
3815
|
try {
|
|
3340
|
-
|
|
3816
|
+
if (isPaginatedQuery) {
|
|
3817
|
+
newValue = this.paginatedClient.localPaginatedQueryResultByToken(queryToken);
|
|
3818
|
+
} else {
|
|
3819
|
+
newValue = this.client.localQueryResultByToken(queryToken);
|
|
3820
|
+
}
|
|
3341
3821
|
} catch (error) {
|
|
3342
3822
|
if (!(error instanceof Error)) throw error;
|
|
3343
3823
|
if (onError) {
|