convex 1.27.2 → 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.
Files changed (232) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/browser.bundle.js +503 -27
  3. package/dist/browser.bundle.js.map +4 -4
  4. package/dist/cjs/browser/index.js.map +2 -2
  5. package/dist/cjs/browser/simple_client.js +115 -15
  6. package/dist/cjs/browser/simple_client.js.map +3 -3
  7. package/dist/cjs/browser/sync/client.js +2 -2
  8. package/dist/cjs/browser/sync/client.js.map +2 -2
  9. package/dist/cjs/browser/sync/local_state.js.map +2 -2
  10. package/dist/cjs/browser/sync/optimistic_updates_impl.js +8 -1
  11. package/dist/cjs/browser/sync/optimistic_updates_impl.js.map +2 -2
  12. package/dist/cjs/browser/sync/paginated_query_client.js +381 -0
  13. package/dist/cjs/browser/sync/paginated_query_client.js.map +7 -0
  14. package/dist/cjs/browser/sync/pagination.js +37 -0
  15. package/dist/cjs/browser/sync/pagination.js.map +7 -0
  16. package/dist/cjs/browser/sync/udf_path_utils.js +16 -1
  17. package/dist/cjs/browser/sync/udf_path_utils.js.map +2 -2
  18. package/dist/cjs/browser/sync/web_socket_manager.js +4 -8
  19. package/dist/cjs/browser/sync/web_socket_manager.js.map +2 -2
  20. package/dist/cjs/cli/index.js +7 -0
  21. package/dist/cjs/cli/index.js.map +2 -2
  22. package/dist/cjs/cli/integration.js +6 -1
  23. package/dist/cjs/cli/integration.js.map +2 -2
  24. package/dist/cjs/cli/lib/components/definition/bundle.js +51 -8
  25. package/dist/cjs/cli/lib/components/definition/bundle.js.map +2 -2
  26. package/dist/cjs/cli/lib/components/definition/directoryStructure.js +12 -12
  27. package/dist/cjs/cli/lib/components/definition/directoryStructure.js.map +2 -2
  28. package/dist/cjs/cli/lib/components.js +1 -1
  29. package/dist/cjs/cli/lib/components.js.map +2 -2
  30. package/dist/cjs/cli/lib/config.js +14 -1
  31. package/dist/cjs/cli/lib/config.js.map +2 -2
  32. package/dist/cjs/cli/lib/envvars.js +10 -5
  33. package/dist/cjs/cli/lib/envvars.js.map +2 -2
  34. package/dist/cjs/cli/lib/utils/utils.js +20 -0
  35. package/dist/cjs/cli/lib/utils/utils.js.map +2 -2
  36. package/dist/cjs/cli/lib/workos/platformApi.js.map +2 -2
  37. package/dist/cjs/cli/lib/workos/workos.js +88 -40
  38. package/dist/cjs/cli/lib/workos/workos.js.map +3 -3
  39. package/dist/cjs/index.js +1 -1
  40. package/dist/cjs/index.js.map +1 -1
  41. package/dist/cjs/react/client.js +89 -1
  42. package/dist/cjs/react/client.js.map +2 -2
  43. package/dist/cjs/react/index.js +4 -0
  44. package/dist/cjs/react/index.js.map +2 -2
  45. package/dist/cjs/react/queries_observer.js +36 -11
  46. package/dist/cjs/react/queries_observer.js.map +2 -2
  47. package/dist/cjs/react/use_paginated_query2.js +124 -0
  48. package/dist/cjs/react/use_paginated_query2.js.map +7 -0
  49. package/dist/cjs/react/use_queries.js +9 -2
  50. package/dist/cjs/react/use_queries.js.map +2 -2
  51. package/dist/cjs/react-clerk/ConvexProviderWithClerk.js +1 -1
  52. package/dist/cjs/react-clerk/ConvexProviderWithClerk.js.map +2 -2
  53. package/dist/cjs/values/validators.js +1 -1
  54. package/dist/cjs/values/validators.js.map +2 -2
  55. package/dist/cjs-types/browser/index.d.ts +2 -1
  56. package/dist/cjs-types/browser/index.d.ts.map +1 -1
  57. package/dist/cjs-types/browser/simple_client.d.ts +20 -1
  58. package/dist/cjs-types/browser/simple_client.d.ts.map +1 -1
  59. package/dist/cjs-types/browser/sync/client.d.ts.map +1 -1
  60. package/dist/cjs-types/browser/sync/client_node_test_helpers.d.ts +5 -4
  61. package/dist/cjs-types/browser/sync/client_node_test_helpers.d.ts.map +1 -1
  62. package/dist/cjs-types/browser/sync/local_state.d.ts +12 -1
  63. package/dist/cjs-types/browser/sync/local_state.d.ts.map +1 -1
  64. package/dist/cjs-types/browser/sync/optimistic_updates_impl.d.ts.map +1 -1
  65. package/dist/cjs-types/browser/sync/paginated_query_client.d.ts +71 -0
  66. package/dist/cjs-types/browser/sync/paginated_query_client.d.ts.map +1 -0
  67. package/dist/cjs-types/browser/sync/paginated_query_client.test.d.ts +2 -0
  68. package/dist/cjs-types/browser/sync/paginated_query_client.test.d.ts.map +1 -0
  69. package/dist/cjs-types/browser/sync/pagination.d.ts +23 -0
  70. package/dist/cjs-types/browser/sync/pagination.d.ts.map +1 -0
  71. package/dist/cjs-types/browser/sync/udf_path_utils.d.ts +22 -1
  72. package/dist/cjs-types/browser/sync/udf_path_utils.d.ts.map +1 -1
  73. package/dist/cjs-types/browser/sync/web_socket_manager.d.ts.map +1 -1
  74. package/dist/cjs-types/cli/integration.d.ts.map +1 -1
  75. package/dist/cjs-types/cli/lib/components/definition/bundle.d.ts.map +1 -1
  76. package/dist/cjs-types/cli/lib/components/definition/directoryStructure.d.ts +4 -0
  77. package/dist/cjs-types/cli/lib/components/definition/directoryStructure.d.ts.map +1 -1
  78. package/dist/cjs-types/cli/lib/components.d.ts.map +1 -1
  79. package/dist/cjs-types/cli/lib/config.d.ts.map +1 -1
  80. package/dist/cjs-types/cli/lib/envvars.d.ts +1 -0
  81. package/dist/cjs-types/cli/lib/envvars.d.ts.map +1 -1
  82. package/dist/cjs-types/cli/lib/utils/utils.d.ts +1 -0
  83. package/dist/cjs-types/cli/lib/utils/utils.d.ts.map +1 -1
  84. package/dist/cjs-types/cli/lib/workos/platformApi.d.ts +1 -0
  85. package/dist/cjs-types/cli/lib/workos/platformApi.d.ts.map +1 -1
  86. package/dist/cjs-types/cli/lib/workos/workos.d.ts +4 -9
  87. package/dist/cjs-types/cli/lib/workos/workos.d.ts.map +1 -1
  88. package/dist/cjs-types/index.d.ts +1 -1
  89. package/dist/cjs-types/index.d.ts.map +1 -1
  90. package/dist/cjs-types/react/client.d.ts +65 -1
  91. package/dist/cjs-types/react/client.d.ts.map +1 -1
  92. package/dist/cjs-types/react/index.d.ts +2 -0
  93. package/dist/cjs-types/react/index.d.ts.map +1 -1
  94. package/dist/cjs-types/react/queries_observer.d.ts +12 -6
  95. package/dist/cjs-types/react/queries_observer.d.ts.map +1 -1
  96. package/dist/cjs-types/react/use_paginated_query2.d.ts +51 -0
  97. package/dist/cjs-types/react/use_paginated_query2.d.ts.map +1 -0
  98. package/dist/cjs-types/react/use_queries.d.ts +2 -0
  99. package/dist/cjs-types/react/use_queries.d.ts.map +1 -1
  100. package/dist/cli.bundle.cjs +21187 -130
  101. package/dist/cli.bundle.cjs.map +4 -4
  102. package/dist/esm/browser/index.js.map +2 -2
  103. package/dist/esm/browser/simple_client.js +117 -15
  104. package/dist/esm/browser/simple_client.js.map +3 -3
  105. package/dist/esm/browser/sync/client.js +2 -2
  106. package/dist/esm/browser/sync/client.js.map +2 -2
  107. package/dist/esm/browser/sync/local_state.js.map +2 -2
  108. package/dist/esm/browser/sync/optimistic_updates_impl.js +8 -1
  109. package/dist/esm/browser/sync/optimistic_updates_impl.js.map +2 -2
  110. package/dist/esm/browser/sync/paginated_query_client.js +365 -0
  111. package/dist/esm/browser/sync/paginated_query_client.js.map +7 -0
  112. package/dist/esm/browser/sync/pagination.js +14 -0
  113. package/dist/esm/browser/sync/pagination.js.map +7 -0
  114. package/dist/esm/browser/sync/udf_path_utils.js +13 -0
  115. package/dist/esm/browser/sync/udf_path_utils.js.map +2 -2
  116. package/dist/esm/browser/sync/web_socket_manager.js +4 -8
  117. package/dist/esm/browser/sync/web_socket_manager.js.map +2 -2
  118. package/dist/esm/cli/index.js +7 -0
  119. package/dist/esm/cli/index.js.map +2 -2
  120. package/dist/esm/cli/integration.js +6 -1
  121. package/dist/esm/cli/integration.js.map +2 -2
  122. package/dist/esm/cli/lib/components/definition/bundle.js +51 -8
  123. package/dist/esm/cli/lib/components/definition/bundle.js.map +2 -2
  124. package/dist/esm/cli/lib/components/definition/directoryStructure.js +12 -12
  125. package/dist/esm/cli/lib/components/definition/directoryStructure.js.map +2 -2
  126. package/dist/esm/cli/lib/components.js +1 -1
  127. package/dist/esm/cli/lib/components.js.map +2 -2
  128. package/dist/esm/cli/lib/config.js +16 -2
  129. package/dist/esm/cli/lib/config.js.map +2 -2
  130. package/dist/esm/cli/lib/envvars.js +10 -5
  131. package/dist/esm/cli/lib/envvars.js.map +2 -2
  132. package/dist/esm/cli/lib/utils/utils.js +19 -0
  133. package/dist/esm/cli/lib/utils/utils.js.map +2 -2
  134. package/dist/esm/cli/lib/workos/platformApi.js.map +2 -2
  135. package/dist/esm/cli/lib/workos/workos.js +79 -41
  136. package/dist/esm/cli/lib/workos/workos.js.map +2 -2
  137. package/dist/esm/index.js +1 -1
  138. package/dist/esm/index.js.map +1 -1
  139. package/dist/esm/react/client.js +91 -1
  140. package/dist/esm/react/client.js.map +2 -2
  141. package/dist/esm/react/index.js +2 -0
  142. package/dist/esm/react/index.js.map +2 -2
  143. package/dist/esm/react/queries_observer.js +36 -11
  144. package/dist/esm/react/queries_observer.js.map +2 -2
  145. package/dist/esm/react/use_paginated_query2.js +101 -0
  146. package/dist/esm/react/use_paginated_query2.js.map +7 -0
  147. package/dist/esm/react/use_queries.js +9 -2
  148. package/dist/esm/react/use_queries.js.map +2 -2
  149. package/dist/esm/react-clerk/ConvexProviderWithClerk.js +1 -1
  150. package/dist/esm/react-clerk/ConvexProviderWithClerk.js.map +2 -2
  151. package/dist/esm/values/validators.js +1 -1
  152. package/dist/esm/values/validators.js.map +2 -2
  153. package/dist/esm-types/browser/index.d.ts +2 -1
  154. package/dist/esm-types/browser/index.d.ts.map +1 -1
  155. package/dist/esm-types/browser/simple_client.d.ts +20 -1
  156. package/dist/esm-types/browser/simple_client.d.ts.map +1 -1
  157. package/dist/esm-types/browser/sync/client.d.ts.map +1 -1
  158. package/dist/esm-types/browser/sync/client_node_test_helpers.d.ts +5 -4
  159. package/dist/esm-types/browser/sync/client_node_test_helpers.d.ts.map +1 -1
  160. package/dist/esm-types/browser/sync/local_state.d.ts +12 -1
  161. package/dist/esm-types/browser/sync/local_state.d.ts.map +1 -1
  162. package/dist/esm-types/browser/sync/optimistic_updates_impl.d.ts.map +1 -1
  163. package/dist/esm-types/browser/sync/paginated_query_client.d.ts +71 -0
  164. package/dist/esm-types/browser/sync/paginated_query_client.d.ts.map +1 -0
  165. package/dist/esm-types/browser/sync/paginated_query_client.test.d.ts +2 -0
  166. package/dist/esm-types/browser/sync/paginated_query_client.test.d.ts.map +1 -0
  167. package/dist/esm-types/browser/sync/pagination.d.ts +23 -0
  168. package/dist/esm-types/browser/sync/pagination.d.ts.map +1 -0
  169. package/dist/esm-types/browser/sync/udf_path_utils.d.ts +22 -1
  170. package/dist/esm-types/browser/sync/udf_path_utils.d.ts.map +1 -1
  171. package/dist/esm-types/browser/sync/web_socket_manager.d.ts.map +1 -1
  172. package/dist/esm-types/cli/integration.d.ts.map +1 -1
  173. package/dist/esm-types/cli/lib/components/definition/bundle.d.ts.map +1 -1
  174. package/dist/esm-types/cli/lib/components/definition/directoryStructure.d.ts +4 -0
  175. package/dist/esm-types/cli/lib/components/definition/directoryStructure.d.ts.map +1 -1
  176. package/dist/esm-types/cli/lib/components.d.ts.map +1 -1
  177. package/dist/esm-types/cli/lib/config.d.ts.map +1 -1
  178. package/dist/esm-types/cli/lib/envvars.d.ts +1 -0
  179. package/dist/esm-types/cli/lib/envvars.d.ts.map +1 -1
  180. package/dist/esm-types/cli/lib/utils/utils.d.ts +1 -0
  181. package/dist/esm-types/cli/lib/utils/utils.d.ts.map +1 -1
  182. package/dist/esm-types/cli/lib/workos/platformApi.d.ts +1 -0
  183. package/dist/esm-types/cli/lib/workos/platformApi.d.ts.map +1 -1
  184. package/dist/esm-types/cli/lib/workos/workos.d.ts +4 -9
  185. package/dist/esm-types/cli/lib/workos/workos.d.ts.map +1 -1
  186. package/dist/esm-types/index.d.ts +1 -1
  187. package/dist/esm-types/index.d.ts.map +1 -1
  188. package/dist/esm-types/react/client.d.ts +65 -1
  189. package/dist/esm-types/react/client.d.ts.map +1 -1
  190. package/dist/esm-types/react/index.d.ts +2 -0
  191. package/dist/esm-types/react/index.d.ts.map +1 -1
  192. package/dist/esm-types/react/queries_observer.d.ts +12 -6
  193. package/dist/esm-types/react/queries_observer.d.ts.map +1 -1
  194. package/dist/esm-types/react/use_paginated_query2.d.ts +51 -0
  195. package/dist/esm-types/react/use_paginated_query2.d.ts.map +1 -0
  196. package/dist/esm-types/react/use_queries.d.ts +2 -0
  197. package/dist/esm-types/react/use_queries.d.ts.map +1 -1
  198. package/dist/react.bundle.js +631 -43
  199. package/dist/react.bundle.js.map +4 -4
  200. package/package.json +2 -1
  201. package/src/browser/index.ts +2 -1
  202. package/src/browser/simple_client.ts +161 -21
  203. package/src/browser/sync/client.ts +12 -3
  204. package/src/browser/sync/client_node_test_helpers.ts +30 -8
  205. package/src/browser/sync/local_state.ts +13 -1
  206. package/src/browser/sync/optimistic_updates_impl.ts +9 -2
  207. package/src/browser/sync/paginated_query_client.test.ts +389 -0
  208. package/src/browser/sync/paginated_query_client.ts +564 -0
  209. package/src/browser/sync/pagination.ts +50 -0
  210. package/src/browser/sync/udf_path_utils.ts +36 -2
  211. package/src/browser/sync/web_socket_manager.ts +11 -9
  212. package/src/cli/index.ts +8 -0
  213. package/src/cli/integration.ts +5 -0
  214. package/src/cli/lib/components/definition/bundle.ts +63 -8
  215. package/src/cli/lib/components/definition/directoryStructure.ts +16 -11
  216. package/src/cli/lib/components.ts +4 -1
  217. package/src/cli/lib/config.ts +25 -0
  218. package/src/cli/lib/envvars.ts +6 -0
  219. package/src/cli/lib/utils/utils.ts +24 -0
  220. package/src/cli/lib/workos/platformApi.ts +1 -0
  221. package/src/cli/lib/workos/workos.ts +123 -44
  222. package/src/index.ts +1 -1
  223. package/src/react/client.ts +169 -4
  224. package/src/react/index.ts +2 -0
  225. package/src/react/queries_observer.test.ts +1 -1
  226. package/src/react/queries_observer.ts +75 -24
  227. package/src/react/use_paginated_query.test.tsx +979 -912
  228. package/src/react/use_paginated_query2.ts +232 -0
  229. package/src/react/use_queries.ts +14 -2
  230. package/src/react-clerk/ConvexProviderWithClerk.tsx +1 -1
  231. package/src/values/validators.ts +1 -1
  232. package/src/browser/.claude/settings.local.json +0 -11
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.27.3
4
+
5
+ - Convex CLI now respects `HTTPS_PROXY` / `HTTP_PROXY` environment variables.
6
+ This is generally useful but was motivated by making Convex run in remote
7
+ asynchronous agent environemnts like Codex.
8
+ - Cutoffs for logging large and slow Transition messages have been lowered.
9
+
3
10
  ## 1.27.2
4
11
 
5
12
  - `npx convex run` sends function log output to stderr instead of stdout.
@@ -28,7 +28,7 @@ var convex = (() => {
28
28
  });
29
29
 
30
30
  // src/index.ts
31
- var version = "1.27.2";
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
- return this.queryResults.get(queryToken);
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);
@@ -2024,21 +2044,17 @@ var convex = (() => {
2024
2044
  this._logVerbose(
2025
2045
  `received ${prettyMessageMB} transition in ${prettyTransitionTime} at ${prettyBytesPerSecond}`
2026
2046
  );
2027
- if (transitionTransitTime > 1e4 && messageLength > 1e7) {
2047
+ if (messageLength > 2e7) {
2028
2048
  this.logger.log(
2029
- `received query results totalling more than 10MB (${prettyMessageMB}) which took more than 10s (${prettyTransitionTime}) to arrive`
2030
- );
2031
- } else if (messageLength > 2e7) {
2032
- this.logger.log(
2033
- `received query results totalling more that 20MB (${prettyMessageMB}) which will take a long time to download on slower connections`
2049
+ `received query results totaling more that 20MB (${prettyMessageMB}) which will take a long time to download on slower connections`
2034
2050
  );
2035
2051
  } else if (transitionTransitTime > 2e4) {
2036
2052
  this.logger.log(
2037
- `received query results totalling ${prettyMessageMB} which took more than 20s to arrive (${prettyTransitionTime})`
2053
+ `received query results totaling ${prettyMessageMB} which took more than 20s to arrive (${prettyTransitionTime})`
2038
2054
  );
2039
2055
  }
2040
2056
  if (this.debug) {
2041
- if (transitionTransitTime > 1e4 || messageLength > 1e7) {
2057
+ if (transitionTransitTime > 2e3) {
2042
2058
  this.sendMessage({
2043
2059
  type: "Event",
2044
2060
  eventType: "ClientReceivedTransition",
@@ -2748,7 +2764,7 @@ var convex = (() => {
2748
2764
  token,
2749
2765
  modification: {
2750
2766
  kind: "Updated",
2751
- result: optimisticResult.result
2767
+ result: optimisticResult
2752
2768
  }
2753
2769
  };
2754
2770
  }),
@@ -2861,7 +2877,7 @@ var convex = (() => {
2861
2877
  return this.optimisticQueryResults.queryResult(queryToken);
2862
2878
  }
2863
2879
  /**
2864
- * Whether local query result is available for a toke.
2880
+ * Whether local query result is available for a token.
2865
2881
  *
2866
2882
  * This method does not throw if the result is an error.
2867
2883
  *
@@ -3162,11 +3178,374 @@ var convex = (() => {
3162
3178
  }
3163
3179
  };
3164
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
+
3165
3543
  // src/browser/simple_client.ts
3166
3544
  var defaultWebSocketConstructor;
3167
3545
  var ConvexClient = class {
3168
3546
  listeners;
3169
3547
  _client;
3548
+ _paginatedClient;
3170
3549
  // A synthetic server event to run callbacks the first time
3171
3550
  callNewListenersWithCurrentValuesTimer;
3172
3551
  _closed;
@@ -3181,6 +3560,10 @@ var convex = (() => {
3181
3560
  if (this._client) return this._client;
3182
3561
  throw new Error("ConvexClient is disabled");
3183
3562
  }
3563
+ get paginatedClient() {
3564
+ if (this._paginatedClient) return this._paginatedClient;
3565
+ throw new Error("ConvexClient is disabled");
3566
+ }
3184
3567
  get disabled() {
3185
3568
  return this._disabled;
3186
3569
  }
@@ -3205,9 +3588,15 @@ var convex = (() => {
3205
3588
  if (!this.disabled) {
3206
3589
  this._client = new BaseConvexClient(
3207
3590
  address,
3208
- (updatedQueries) => this._transition(updatedQueries),
3591
+ () => {
3592
+ },
3593
+ // NOP, let the paginated query client do it all
3209
3594
  baseOptions
3210
3595
  );
3596
+ this._paginatedClient = new PaginatedQueryClient(
3597
+ this._client,
3598
+ (transition) => this._transition(transition)
3599
+ );
3211
3600
  }
3212
3601
  this.listeners = /* @__PURE__ */ new Set();
3213
3602
  }
@@ -3245,15 +3634,7 @@ var convex = (() => {
3245
3634
  */
3246
3635
  onUpdate(query, args, callback, onError) {
3247
3636
  if (this.disabled) {
3248
- const disabledUnsubscribe = () => {
3249
- };
3250
- const unsubscribeProps2 = {
3251
- unsubscribe: disabledUnsubscribe,
3252
- getCurrentValue: () => void 0,
3253
- getQueryLogs: () => void 0
3254
- };
3255
- Object.assign(disabledUnsubscribe, unsubscribeProps2);
3256
- return disabledUnsubscribe;
3637
+ return this.createDisabledUnsubscribe();
3257
3638
  }
3258
3639
  const { queryToken, unsubscribe } = this.client.subscribe(
3259
3640
  getFunctionName(query),
@@ -3266,7 +3647,8 @@ var convex = (() => {
3266
3647
  unsubscribe,
3267
3648
  hasEverRun: false,
3268
3649
  query,
3269
- args
3650
+ args,
3651
+ paginationOptions: void 0
3270
3652
  };
3271
3653
  this.listeners.add(queryInfo);
3272
3654
  if (this.queryResultReady(queryToken) && this.callNewListenersWithCurrentValuesTimer === void 0) {
@@ -3290,19 +3672,100 @@ var convex = (() => {
3290
3672
  Object.assign(ret, unsubscribeProps);
3291
3673
  return ret;
3292
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
+ }
3293
3742
  // Run all callbacks that have never been run before if they have a query
3294
3743
  // result available now.
3295
3744
  callNewListenersWithCurrentValues() {
3296
3745
  this.callNewListenersWithCurrentValuesTimer = void 0;
3297
- this._transition([], true);
3746
+ this._transition({ queries: [], paginatedQueries: [] }, true);
3298
3747
  }
3299
3748
  queryResultReady(queryToken) {
3300
3749
  return this.client.hasLocalQueryResultByToken(queryToken);
3301
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
+ }
3302
3762
  async close() {
3303
3763
  if (this.disabled) return;
3304
3764
  this.listeners.clear();
3305
3765
  this._closed = true;
3766
+ if (this._paginatedClient) {
3767
+ this._paginatedClient = void 0;
3768
+ }
3306
3769
  return this.client.close();
3307
3770
  }
3308
3771
  /**
@@ -3334,14 +3797,27 @@ var convex = (() => {
3334
3797
  /**
3335
3798
  * @internal
3336
3799
  */
3337
- _transition(updatedQueries, callNewListeners = false) {
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
+ ];
3338
3808
  for (const queryInfo of this.listeners) {
3339
3809
  const { callback, queryToken, onError, hasEverRun } = queryInfo;
3340
- if (updatedQueries.includes(queryToken) || callNewListeners && !hasEverRun && this.client.hasLocalQueryResultByToken(queryToken)) {
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) {
3341
3813
  queryInfo.hasEverRun = true;
3342
3814
  let newValue;
3343
3815
  try {
3344
- newValue = this.client.localQueryResultByToken(queryToken);
3816
+ if (isPaginatedQuery) {
3817
+ newValue = this.paginatedClient.localPaginatedQueryResultByToken(queryToken);
3818
+ } else {
3819
+ newValue = this.client.localQueryResultByToken(queryToken);
3820
+ }
3345
3821
  } catch (error) {
3346
3822
  if (!(error instanceof Error)) throw error;
3347
3823
  if (onError) {