convex 1.36.0 → 1.37.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 (240) hide show
  1. package/CHANGELOG.md +50 -27
  2. package/dist/browser.bundle.js +1 -1
  3. package/dist/browser.bundle.js.map +1 -1
  4. package/dist/cjs/cli/codegen_templates/agentsmd.js +8 -2
  5. package/dist/cjs/cli/codegen_templates/agentsmd.js.map +2 -2
  6. package/dist/cjs/cli/codegen_templates/claudemd.js +2 -0
  7. package/dist/cjs/cli/codegen_templates/claudemd.js.map +2 -2
  8. package/dist/cjs/cli/configure.js +0 -8
  9. package/dist/cjs/cli/configure.js.map +2 -2
  10. package/dist/cjs/cli/deployment.js +2 -1
  11. package/dist/cjs/cli/deployment.js.map +2 -2
  12. package/dist/cjs/cli/deploymentToken.js +30 -0
  13. package/dist/cjs/cli/deploymentToken.js.map +7 -0
  14. package/dist/cjs/cli/deploymentTokenCreate.js +109 -0
  15. package/dist/cjs/cli/deploymentTokenCreate.js.map +7 -0
  16. package/dist/cjs/cli/deploymentTokenDelete.js +87 -0
  17. package/dist/cjs/cli/deploymentTokenDelete.js.map +7 -0
  18. package/dist/cjs/cli/envDefault.js +130 -41
  19. package/dist/cjs/cli/envDefault.js.map +3 -3
  20. package/dist/cjs/cli/generatedApi.js.map +1 -1
  21. package/dist/cjs/cli/lib/command.js +1 -1
  22. package/dist/cjs/cli/lib/command.js.map +1 -1
  23. package/dist/cjs/cli/lib/generatedFunctionLogsApi.js.map +1 -1
  24. package/dist/cjs/cli/lib/login.js +51 -0
  25. package/dist/cjs/cli/lib/login.js.map +3 -3
  26. package/dist/cjs/cli/lib/usage.js +13 -6
  27. package/dist/cjs/cli/lib/usage.js.map +2 -2
  28. package/dist/cjs/cli/lib/workos/environmentApi.js +6 -12
  29. package/dist/cjs/cli/lib/workos/environmentApi.js.map +3 -3
  30. package/dist/cjs/index.js +1 -1
  31. package/dist/cjs/index.js.map +1 -1
  32. package/dist/cjs/react/client.js +40 -42
  33. package/dist/cjs/react/client.js.map +2 -2
  34. package/dist/cjs/react/index.js +1 -0
  35. package/dist/cjs/react/index.js.map +2 -2
  36. package/dist/cjs/react/use_paginated_query.js +5 -46
  37. package/dist/cjs/react/use_paginated_query.js.map +2 -2
  38. package/dist/cjs/react/use_paginated_query2.js.map +2 -2
  39. package/dist/cjs/server/audit_logging.js +67 -0
  40. package/dist/cjs/server/audit_logging.js.map +7 -0
  41. package/dist/cjs/server/impl/meta_impl.js +27 -3
  42. package/dist/cjs/server/impl/meta_impl.js.map +2 -2
  43. package/dist/cjs/server/impl/registration_impl.js +2 -0
  44. package/dist/cjs/server/impl/registration_impl.js.map +2 -2
  45. package/dist/cjs/server/index.js +2 -0
  46. package/dist/cjs/server/index.js.map +2 -2
  47. package/dist/cjs/server/log.js +30 -0
  48. package/dist/cjs/server/log.js.map +7 -0
  49. package/dist/cjs/server/logVars.js +48 -0
  50. package/dist/cjs/server/logVars.js.map +7 -0
  51. package/dist/cjs/server/meta.js.map +1 -1
  52. package/dist/cjs/server/registration.js.map +1 -1
  53. package/dist/cjs-types/cli/codegen_templates/agentsmd.d.ts.map +1 -1
  54. package/dist/cjs-types/cli/codegen_templates/claudemd.d.ts.map +1 -1
  55. package/dist/cjs-types/cli/configure.d.ts.map +1 -1
  56. package/dist/cjs-types/cli/deployment.d.ts.map +1 -1
  57. package/dist/cjs-types/cli/deploymentToken.d.ts +3 -0
  58. package/dist/cjs-types/cli/deploymentToken.d.ts.map +1 -0
  59. package/dist/cjs-types/cli/deploymentToken.test.d.ts +2 -0
  60. package/dist/cjs-types/cli/deploymentToken.test.d.ts.map +1 -0
  61. package/dist/cjs-types/cli/deploymentTokenCreate.d.ts +13 -0
  62. package/dist/cjs-types/cli/deploymentTokenCreate.d.ts.map +1 -0
  63. package/dist/cjs-types/cli/deploymentTokenDelete.d.ts +11 -0
  64. package/dist/cjs-types/cli/deploymentTokenDelete.d.ts.map +1 -0
  65. package/dist/cjs-types/cli/envDefault.d.ts +2 -2
  66. package/dist/cjs-types/cli/envDefault.d.ts.map +1 -1
  67. package/dist/cjs-types/cli/envDefault.test.d.ts +2 -0
  68. package/dist/cjs-types/cli/envDefault.test.d.ts.map +1 -0
  69. package/dist/cjs-types/cli/generatedApi.d.ts +1 -1
  70. package/dist/cjs-types/cli/generatedApi.d.ts.map +1 -1
  71. package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts +1 -0
  72. package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
  73. package/dist/cjs-types/cli/lib/login.d.ts.map +1 -1
  74. package/dist/cjs-types/cli/lib/usage.d.ts.map +1 -1
  75. package/dist/cjs-types/cli/lib/workos/environmentApi.d.ts.map +1 -1
  76. package/dist/cjs-types/cli/lib/workos/environmentApi.test.d.ts +2 -0
  77. package/dist/cjs-types/cli/lib/workos/environmentApi.test.d.ts.map +1 -0
  78. package/dist/cjs-types/index.d.ts +1 -1
  79. package/dist/cjs-types/react/client.d.ts +52 -0
  80. package/dist/cjs-types/react/client.d.ts.map +1 -1
  81. package/dist/cjs-types/react/index.d.ts +2 -2
  82. package/dist/cjs-types/react/index.d.ts.map +1 -1
  83. package/dist/cjs-types/react/use_paginated_query.d.ts.map +1 -1
  84. package/dist/cjs-types/react/use_paginated_query2.d.ts +63 -1
  85. package/dist/cjs-types/react/use_paginated_query2.d.ts.map +1 -1
  86. package/dist/cjs-types/server/api.intersect.test.d.ts +2 -0
  87. package/dist/cjs-types/server/api.intersect.test.d.ts.map +1 -0
  88. package/dist/cjs-types/server/audit_logging.d.ts +19 -0
  89. package/dist/cjs-types/server/audit_logging.d.ts.map +1 -0
  90. package/dist/cjs-types/server/audit_logging.test.d.ts +2 -0
  91. package/dist/cjs-types/server/audit_logging.test.d.ts.map +1 -0
  92. package/dist/cjs-types/server/impl/meta_impl.d.ts.map +1 -1
  93. package/dist/cjs-types/server/impl/registration_impl.d.ts.map +1 -1
  94. package/dist/cjs-types/server/index.d.ts +2 -2
  95. package/dist/cjs-types/server/index.d.ts.map +1 -1
  96. package/dist/cjs-types/server/log.d.ts +2 -0
  97. package/dist/cjs-types/server/log.d.ts.map +1 -0
  98. package/dist/cjs-types/server/logVars.d.ts +20 -0
  99. package/dist/cjs-types/server/logVars.d.ts.map +1 -0
  100. package/dist/cjs-types/server/meta.d.ts +40 -0
  101. package/dist/cjs-types/server/meta.d.ts.map +1 -1
  102. package/dist/cjs-types/server/registration.d.ts +5 -2
  103. package/dist/cjs-types/server/registration.d.ts.map +1 -1
  104. package/dist/cli.bundle.cjs +362 -74
  105. package/dist/cli.bundle.cjs.map +4 -4
  106. package/dist/esm/cli/codegen_templates/agentsmd.js +8 -2
  107. package/dist/esm/cli/codegen_templates/agentsmd.js.map +2 -2
  108. package/dist/esm/cli/codegen_templates/claudemd.js +2 -0
  109. package/dist/esm/cli/codegen_templates/claudemd.js.map +2 -2
  110. package/dist/esm/cli/configure.js +0 -8
  111. package/dist/esm/cli/configure.js.map +2 -2
  112. package/dist/esm/cli/deployment.js +2 -1
  113. package/dist/esm/cli/deployment.js.map +2 -2
  114. package/dist/esm/cli/deploymentToken.js +8 -0
  115. package/dist/esm/cli/deploymentToken.js.map +7 -0
  116. package/dist/esm/cli/deploymentTokenCreate.js +91 -0
  117. package/dist/esm/cli/deploymentTokenCreate.js.map +7 -0
  118. package/dist/esm/cli/deploymentTokenDelete.js +68 -0
  119. package/dist/esm/cli/deploymentTokenDelete.js.map +7 -0
  120. package/dist/esm/cli/envDefault.js +131 -42
  121. package/dist/esm/cli/envDefault.js.map +3 -3
  122. package/dist/esm/cli/lib/command.js +1 -1
  123. package/dist/esm/cli/lib/command.js.map +1 -1
  124. package/dist/esm/cli/lib/login.js +52 -0
  125. package/dist/esm/cli/lib/login.js.map +3 -3
  126. package/dist/esm/cli/lib/usage.js +15 -8
  127. package/dist/esm/cli/lib/usage.js.map +2 -2
  128. package/dist/esm/cli/lib/workos/environmentApi.js +6 -12
  129. package/dist/esm/cli/lib/workos/environmentApi.js.map +3 -3
  130. package/dist/esm/index.js +1 -1
  131. package/dist/esm/index.js.map +1 -1
  132. package/dist/esm/react/client.js +38 -41
  133. package/dist/esm/react/client.js.map +2 -2
  134. package/dist/esm/react/index.js +4 -1
  135. package/dist/esm/react/index.js.map +2 -2
  136. package/dist/esm/react/use_paginated_query.js +5 -46
  137. package/dist/esm/react/use_paginated_query.js.map +2 -2
  138. package/dist/esm/react/use_paginated_query2.js.map +2 -2
  139. package/dist/esm/server/audit_logging.js +44 -0
  140. package/dist/esm/server/audit_logging.js.map +7 -0
  141. package/dist/esm/server/impl/meta_impl.js +27 -3
  142. package/dist/esm/server/impl/meta_impl.js.map +2 -2
  143. package/dist/esm/server/impl/registration_impl.js +2 -0
  144. package/dist/esm/server/impl/registration_impl.js.map +2 -2
  145. package/dist/esm/server/index.js +1 -0
  146. package/dist/esm/server/index.js.map +2 -2
  147. package/dist/esm/server/log.js +8 -0
  148. package/dist/esm/server/log.js.map +7 -0
  149. package/dist/esm/server/logVars.js +25 -0
  150. package/dist/esm/server/logVars.js.map +7 -0
  151. package/dist/esm-types/cli/codegen_templates/agentsmd.d.ts.map +1 -1
  152. package/dist/esm-types/cli/codegen_templates/claudemd.d.ts.map +1 -1
  153. package/dist/esm-types/cli/configure.d.ts.map +1 -1
  154. package/dist/esm-types/cli/deployment.d.ts.map +1 -1
  155. package/dist/esm-types/cli/deploymentToken.d.ts +3 -0
  156. package/dist/esm-types/cli/deploymentToken.d.ts.map +1 -0
  157. package/dist/esm-types/cli/deploymentToken.test.d.ts +2 -0
  158. package/dist/esm-types/cli/deploymentToken.test.d.ts.map +1 -0
  159. package/dist/esm-types/cli/deploymentTokenCreate.d.ts +13 -0
  160. package/dist/esm-types/cli/deploymentTokenCreate.d.ts.map +1 -0
  161. package/dist/esm-types/cli/deploymentTokenDelete.d.ts +11 -0
  162. package/dist/esm-types/cli/deploymentTokenDelete.d.ts.map +1 -0
  163. package/dist/esm-types/cli/envDefault.d.ts +2 -2
  164. package/dist/esm-types/cli/envDefault.d.ts.map +1 -1
  165. package/dist/esm-types/cli/envDefault.test.d.ts +2 -0
  166. package/dist/esm-types/cli/envDefault.test.d.ts.map +1 -0
  167. package/dist/esm-types/cli/generatedApi.d.ts +1 -1
  168. package/dist/esm-types/cli/generatedApi.d.ts.map +1 -1
  169. package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts +1 -0
  170. package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
  171. package/dist/esm-types/cli/lib/login.d.ts.map +1 -1
  172. package/dist/esm-types/cli/lib/usage.d.ts.map +1 -1
  173. package/dist/esm-types/cli/lib/workos/environmentApi.d.ts.map +1 -1
  174. package/dist/esm-types/cli/lib/workos/environmentApi.test.d.ts +2 -0
  175. package/dist/esm-types/cli/lib/workos/environmentApi.test.d.ts.map +1 -0
  176. package/dist/esm-types/index.d.ts +1 -1
  177. package/dist/esm-types/react/client.d.ts +52 -0
  178. package/dist/esm-types/react/client.d.ts.map +1 -1
  179. package/dist/esm-types/react/index.d.ts +2 -2
  180. package/dist/esm-types/react/index.d.ts.map +1 -1
  181. package/dist/esm-types/react/use_paginated_query.d.ts.map +1 -1
  182. package/dist/esm-types/react/use_paginated_query2.d.ts +63 -1
  183. package/dist/esm-types/react/use_paginated_query2.d.ts.map +1 -1
  184. package/dist/esm-types/server/api.intersect.test.d.ts +2 -0
  185. package/dist/esm-types/server/api.intersect.test.d.ts.map +1 -0
  186. package/dist/esm-types/server/audit_logging.d.ts +19 -0
  187. package/dist/esm-types/server/audit_logging.d.ts.map +1 -0
  188. package/dist/esm-types/server/audit_logging.test.d.ts +2 -0
  189. package/dist/esm-types/server/audit_logging.test.d.ts.map +1 -0
  190. package/dist/esm-types/server/impl/meta_impl.d.ts.map +1 -1
  191. package/dist/esm-types/server/impl/registration_impl.d.ts.map +1 -1
  192. package/dist/esm-types/server/index.d.ts +2 -2
  193. package/dist/esm-types/server/index.d.ts.map +1 -1
  194. package/dist/esm-types/server/log.d.ts +2 -0
  195. package/dist/esm-types/server/log.d.ts.map +1 -0
  196. package/dist/esm-types/server/logVars.d.ts +20 -0
  197. package/dist/esm-types/server/logVars.d.ts.map +1 -0
  198. package/dist/esm-types/server/meta.d.ts +40 -0
  199. package/dist/esm-types/server/meta.d.ts.map +1 -1
  200. package/dist/esm-types/server/registration.d.ts +5 -2
  201. package/dist/esm-types/server/registration.d.ts.map +1 -1
  202. package/dist/react.bundle.js +45 -88
  203. package/dist/react.bundle.js.map +2 -2
  204. package/package.json +4 -4
  205. package/src/cli/codegen_templates/agentsmd.ts +8 -2
  206. package/src/cli/codegen_templates/claudemd.ts +2 -0
  207. package/src/cli/configure.ts +0 -9
  208. package/src/cli/deployment.ts +3 -1
  209. package/src/cli/deploymentToken.test.ts +372 -0
  210. package/src/cli/deploymentToken.ts +11 -0
  211. package/src/cli/deploymentTokenCreate.ts +113 -0
  212. package/src/cli/deploymentTokenDelete.ts +91 -0
  213. package/src/cli/envDefault.test.ts +495 -0
  214. package/src/cli/envDefault.ts +222 -107
  215. package/src/cli/generatedApi.ts +1 -1
  216. package/src/cli/lib/command.ts +1 -1
  217. package/src/cli/lib/generatedFunctionLogsApi.ts +1 -0
  218. package/src/cli/lib/login.ts +67 -0
  219. package/src/cli/lib/usage.ts +18 -8
  220. package/src/cli/lib/workos/environmentApi.test.ts +107 -0
  221. package/src/cli/lib/workos/environmentApi.ts +12 -19
  222. package/src/index.ts +1 -1
  223. package/src/react/client.test.tsx +10 -8
  224. package/src/react/client.ts +88 -96
  225. package/src/react/index.ts +6 -1
  226. package/src/react/use_paginated_query.test.tsx +215 -132
  227. package/src/react/use_paginated_query.ts +8 -142
  228. package/src/react/use_paginated_query2.ts +78 -5
  229. package/src/react/use_query_object_options.test.ts +8 -7
  230. package/src/react/use_query_result.test.ts +40 -7
  231. package/src/server/api.intersect.test.ts +109 -0
  232. package/src/server/audit_logging.test.ts +129 -0
  233. package/src/server/audit_logging.ts +75 -0
  234. package/src/server/impl/meta_impl.ts +28 -0
  235. package/src/server/impl/registration_impl.ts +2 -0
  236. package/src/server/index.ts +12 -0
  237. package/src/server/log.ts +16 -0
  238. package/src/server/logVars.ts +34 -0
  239. package/src/server/meta.ts +53 -1
  240. package/src/server/registration.ts +10 -8
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["external-global-plugin:react", "../src/react/index.ts", "../src/react/use_paginated_query.ts", "../src/values/base64.ts", "../src/common/index.ts", "../src/values/value.ts", "../src/values/errors.ts", "../src/values/compare_utf8.ts", "../src/values/compare.ts", "../src/react/use_queries.ts", "../src/index.ts", "../src/browser/logging.ts", "../src/browser/sync/udf_path_utils.ts", "../src/browser/sync/local_state.ts", "../src/browser/sync/request_manager.ts", "../src/server/functionName.ts", "../src/server/components/paths.ts", "../src/server/api.ts", "../src/browser/sync/optimistic_updates_impl.ts", "../src/vendor/long.ts", "../src/browser/sync/remote_query_set.ts", "../src/browser/sync/protocol.ts", "../src/browser/sync/web_socket_manager.ts", "../src/browser/sync/session.ts", "../src/vendor/jwt-decode/index.ts", "../src/browser/sync/authentication_manager.ts", "../src/browser/sync/metrics.ts", "../src/browser/sync/client.ts", "../src/browser/sync/pagination.ts", "../src/browser/sync/paginated_query_client.ts", "../src/browser/query_options.ts", "../src/react/client.ts", "../src/react/use_subscription.ts", "../src/react/queries_observer.ts", "../src/react/use_paginated_query2.ts", "../src/react/auth_helpers.tsx", "../src/react/ConvexAuthState.tsx", "../src/react/hydration.tsx"],
4
- "sourcesContent": ["module.exports = window.React", "/**\n * Tools to integrate Convex into React applications.\n *\n * This module contains:\n * 1. {@link ConvexReactClient}, a client for using Convex in React.\n * 2. {@link ConvexProvider}, a component that stores this client in React context.\n * 3. {@link Authenticated}, {@link Unauthenticated} and {@link AuthLoading} helper auth components.\n * 4. Hooks {@link useQuery}, {@link useMutation}, {@link useAction} and more for accessing this\n * client from your React components.\n *\n * ## Usage\n *\n * ### Creating the client\n *\n * ```typescript\n * import { ConvexReactClient } from \"convex/react\";\n *\n * // typically loaded from an environment variable\n * const address = \"https://small-mouse-123.convex.cloud\"\n * const convex = new ConvexReactClient(address);\n * ```\n *\n * ### Storing the client in React Context\n *\n * ```typescript\n * import { ConvexProvider } from \"convex/react\";\n *\n * <ConvexProvider client={convex}>\n * <App />\n * </ConvexProvider>\n * ```\n *\n * ### Using the auth helpers\n *\n * ```typescript\n * import { Authenticated, Unauthenticated, AuthLoading } from \"convex/react\";\n *\n * <Authenticated>\n * Logged in\n * </Authenticated>\n * <Unauthenticated>\n * Logged out\n * </Unauthenticated>\n * <AuthLoading>\n * Still loading\n * </AuthLoading>\n * ```\n *\n * ### Using React hooks\n *\n * ```typescript\n * import { useQuery, useMutation } from \"convex/react\";\n * import { api } from \"../convex/_generated/api\";\n *\n * function App() {\n * const counter = useQuery(api.getCounter.default);\n * const increment = useMutation(api.incrementCounter.default);\n * // Your component here!\n * }\n * ```\n * @module\n */\nexport * from \"./use_paginated_query.js\";\nexport { usePaginatedQuery_experimental } from \"./use_paginated_query2.js\";\nexport { usePaginatedQuery } from \"./use_paginated_query.js\";\nexport { useQueries, type RequestForQueries } from \"./use_queries.js\";\nexport type { AuthTokenFetcher } from \"../browser/sync/client.js\";\nexport * from \"./auth_helpers.js\";\nexport * from \"./ConvexAuthState.js\";\nexport * from \"./hydration.js\";\n/* @internal */\nexport { useSubscription } from \"./use_subscription.js\";\nexport {\n type ReactMutation,\n type ReactAction,\n type Watch,\n type WatchQueryOptions,\n type MutationOptions,\n type ConvexReactClientOptions,\n type OptionalRestArgsOrSkip,\n ConvexReactClient,\n useConvex,\n ConvexProvider,\n useQuery,\n useMutation,\n useAction,\n useConvexConnectionState,\n} from \"./client.js\";\n/** @internal */\nexport type { UseQueryResult } from \"./client.js\";\n/** @internal */\nexport { convexQueryOptions } from \"../browser/query_options.js\";\nexport type { QueryOptions } from \"../browser/query_options.js\";\n", "import { useMemo, useState } from \"react\";\n\nimport { OptimisticLocalStore } from \"../browser/index.js\";\nimport {\n FunctionReturnType,\n PaginationOptions,\n paginationOptsValidator,\n PaginationResult,\n} from \"../server/index.js\";\nimport { ConvexError, convexToJson, Infer, Value } from \"../values/index.js\";\nimport { useQueries } from \"./use_queries.js\";\nimport {\n FunctionArgs,\n FunctionReference,\n getFunctionName,\n} from \"../server/api.js\";\nimport { BetterOmit, Expand } from \"../type_utils.js\";\nimport { useConvex } from \"./client.js\";\nimport { compareValues } from \"../values/compare.js\";\n\n/**\n * A {@link server.FunctionReference} that is usable with {@link usePaginatedQuery}.\n *\n * This function reference must:\n * - Refer to a public query\n * - Have an argument named \"paginationOpts\" of type {@link server.PaginationOptions}\n * - Have a return type of {@link server.PaginationResult}.\n *\n * @public\n */\nexport type PaginatedQueryReference = FunctionReference<\n \"query\",\n \"public\",\n { paginationOpts: PaginationOptions },\n PaginationResult<any>\n>;\n\n/**\n * Options for object-form {@link usePaginatedQuery}.\n *\n * @internal\n */\nexport type UsePaginatedQueryOptions<Query extends PaginatedQueryReference> = {\n query: Query;\n args: PaginatedQueryArgs<Query> | \"skip\";\n initialNumItems: number;\n /**\n * When `true` (default for positional form), errors are thrown and caught\n * by an error boundary. When `false` (default for object form), errors are\n * returned as `{ status: \"Error\", error: Error }` instead of being thrown.\n */\n throwOnError?: boolean;\n};\n\n// Incrementing integer for each page queried in the usePaginatedQuery hook.\ntype QueryPageKey = number;\n\ntype UsePaginatedQueryState = {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n id: number;\n nextPageKey: QueryPageKey;\n pageKeys: QueryPageKey[];\n queries: Record<\n QueryPageKey,\n {\n query: FunctionReference<\"query\">;\n // Use the validator type as a test that it matches the args\n // we generate.\n args: { paginationOpts: Infer<typeof paginationOptsValidator> };\n }\n >;\n ongoingSplits: Record<QueryPageKey, [QueryPageKey, QueryPageKey]>;\n skip: boolean;\n};\n\nconst splitQuery =\n (key: QueryPageKey, splitCursor: string, continueCursor: string) =>\n (prevState: UsePaginatedQueryState) => {\n const queries = { ...prevState.queries };\n const splitKey1 = prevState.nextPageKey;\n const splitKey2 = prevState.nextPageKey + 1;\n const nextPageKey = prevState.nextPageKey + 2;\n queries[splitKey1] = {\n query: prevState.query,\n args: {\n ...prevState.args,\n paginationOpts: {\n ...prevState.queries[key].args.paginationOpts,\n endCursor: splitCursor,\n },\n },\n };\n queries[splitKey2] = {\n query: prevState.query,\n args: {\n ...prevState.args,\n paginationOpts: {\n ...prevState.queries[key].args.paginationOpts,\n cursor: splitCursor,\n endCursor: continueCursor,\n },\n },\n };\n const ongoingSplits = { ...prevState.ongoingSplits };\n ongoingSplits[key] = [splitKey1, splitKey2];\n return {\n ...prevState,\n nextPageKey,\n queries,\n ongoingSplits,\n };\n };\n\nconst completeSplitQuery =\n (key: QueryPageKey) => (prevState: UsePaginatedQueryState) => {\n const completedSplit = prevState.ongoingSplits[key];\n if (completedSplit === undefined) {\n return prevState;\n }\n const queries = { ...prevState.queries };\n delete queries[key];\n const ongoingSplits = { ...prevState.ongoingSplits };\n delete ongoingSplits[key];\n let pageKeys = prevState.pageKeys.slice();\n const pageIndex = prevState.pageKeys.findIndex((v) => v === key);\n if (pageIndex >= 0) {\n pageKeys = [\n ...prevState.pageKeys.slice(0, pageIndex),\n ...completedSplit,\n ...prevState.pageKeys.slice(pageIndex + 1),\n ];\n }\n return {\n ...prevState,\n queries,\n pageKeys,\n ongoingSplits,\n };\n };\n\n/**\n * Load data reactively from a paginated query to a create a growing list.\n *\n * This can be used to power \"infinite scroll\" UIs.\n *\n * This hook must be used with public query references that match\n * {@link PaginatedQueryReference}.\n *\n * `usePaginatedQuery` concatenates all the pages of results into a single list\n * and manages the continuation cursors when requesting more items.\n *\n * Example usage:\n * ```typescript\n * const { results, status, isLoading, loadMore } = usePaginatedQuery(\n * api.messages.list,\n * { channel: \"#general\" },\n * { initialNumItems: 5 }\n * );\n * ```\n *\n * If the query reference or arguments change, the pagination state will be reset\n * to the first page. Similarly, if any of the pages result in an InvalidCursor\n * error or an error associated with too much data, the pagination state will also\n * reset to the first page.\n *\n * To learn more about pagination, see [Paginated Queries](https://docs.convex.dev/database/pagination).\n *\n * @param query - A FunctionReference to the public query function to run.\n * @param args - The arguments object for the query function, excluding\n * the `paginationOpts` property. That property is injected by this hook.\n * @param options - An object specifying the `initialNumItems` to be loaded in\n * the first page.\n * @returns A {@link UsePaginatedQueryResult} that includes the currently loaded\n * items, the status of the pagination, and a `loadMore` function.\n *\n * @public\n */\nexport function usePaginatedQuery<Query extends PaginatedQueryReference>(\n query: Query,\n args: PaginatedQueryArgs<Query> | \"skip\",\n options: { initialNumItems: number },\n): UsePaginatedQueryReturnType<Query>;\n\n/**\n * Load data reactively from a paginated query using an options object.\n *\n * @param options - Object-form options for the paginated query.\n * @returns An object with `data`, `status`, `canLoadMore`, `isLoading`,\n * `error`, and `loadMore`. `status` is `\"pending\"` while loading,\n * `\"success\"` when data is available, or `\"error\"` if the query threw.\n * `canLoadMore` is `true` only when idle and more pages exist.\n *\n * @internal\n */\nexport function usePaginatedQuery<Query extends PaginatedQueryReference>(\n options: UsePaginatedQueryOptions<Query>,\n): UsePaginatedQueryObjectReturnType<Query>;\n\nexport function usePaginatedQuery<Query extends PaginatedQueryReference>(\n queryOrOptions: Query | UsePaginatedQueryOptions<Query>,\n args?: PaginatedQueryArgs<Query> | \"skip\",\n options?: { initialNumItems: number },\n):\n | UsePaginatedQueryReturnType<Query>\n | UsePaginatedQueryObjectReturnType<Query> {\n const isObjectOptions =\n typeof queryOrOptions === \"object\" &&\n queryOrOptions !== null &&\n \"query\" in queryOrOptions;\n\n const query = isObjectOptions ? queryOrOptions.query : queryOrOptions;\n const queryArgs = isObjectOptions ? queryOrOptions.args : args;\n const throwOnError = isObjectOptions\n ? (queryOrOptions.throwOnError ?? false)\n : true;\n const initialOptions = isObjectOptions\n ? { initialNumItems: queryOrOptions.initialNumItems }\n : options;\n\n const { user: positionalResult } = usePaginatedQueryInternal(\n query,\n queryArgs as PaginatedQueryArgs<Query> | \"skip\",\n initialOptions as { initialNumItems: number },\n throwOnError,\n );\n\n if (!isObjectOptions) {\n return positionalResult as unknown as UsePaginatedQueryReturnType<Query>;\n }\n\n return reshapeToObjectForm(\n positionalResult,\n ) as unknown as UsePaginatedQueryObjectReturnType<Query>;\n}\n\n/** @internal */\nexport const includePage = Symbol(\"includePageKeys\");\n\n/** @internal */\nexport const page = Symbol(\"page\");\n\n/**\n * @internal\n */\nexport function usePaginatedQueryInternal<\n Query extends PaginatedQueryReference,\n>(\n query: Query,\n args: PaginatedQueryArgs<Query> | \"skip\",\n options: {\n initialNumItems: number;\n [includePage]?: boolean;\n },\n throwOnError: boolean = true,\n): {\n user: UsePaginatedQueryInternalResult<PaginatedQueryItem<Query>>;\n internal: { state: UsePaginatedQueryState };\n} {\n if (\n typeof options?.initialNumItems !== \"number\" ||\n options.initialNumItems < 0\n ) {\n throw new Error(\n `\\`options.initialNumItems\\` must be a positive number. Received \\`${options?.initialNumItems}\\`.`,\n );\n }\n const skip = args === \"skip\";\n const argsObject = skip ? {} : args;\n const queryName = getFunctionName(query);\n const createInitialState = useMemo(() => {\n return () => {\n const id = nextPaginationId();\n return {\n query,\n args: argsObject as Record<string, Value>,\n id,\n nextPageKey: 1,\n pageKeys: skip ? [] : [0],\n queries: skip\n ? ({} as UsePaginatedQueryState[\"queries\"])\n : {\n 0: {\n query,\n args: {\n ...argsObject,\n paginationOpts: {\n numItems: options.initialNumItems,\n cursor: null,\n id,\n },\n },\n },\n },\n ongoingSplits: {},\n skip,\n };\n };\n // ESLint doesn't like that we're stringifying the args. We do this because\n // we want to avoid rerendering if the args are a different\n // object that serializes to the same result.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(convexToJson(argsObject as Value)),\n queryName,\n options.initialNumItems,\n skip,\n ]);\n\n const [state, setState] =\n useState<UsePaginatedQueryState>(createInitialState);\n\n // `currState` is the state that we'll render based on.\n let currState = state;\n if (\n getFunctionName(query) !== getFunctionName(state.query) ||\n JSON.stringify(convexToJson(argsObject as Value)) !==\n JSON.stringify(convexToJson(state.args)) ||\n skip !== state.skip\n ) {\n currState = createInitialState();\n setState(currState);\n }\n const convexClient = useConvex();\n const logger = convexClient.logger;\n\n const resultsObject = useQueries(currState.queries);\n\n const isIncludingPageKeys = options[includePage] ?? false;\n const [results, maybeLastResult, maybeError]: [\n Value[],\n undefined | PaginationResult<Value>,\n undefined | Error,\n ] = useMemo(() => {\n let currResult = undefined;\n\n const allItems = [];\n for (const pageKey of currState.pageKeys) {\n currResult = resultsObject[pageKey];\n if (currResult === undefined) {\n break;\n }\n\n if (currResult instanceof Error) {\n if (\n currResult.message.includes(\"InvalidCursor\") ||\n (currResult instanceof ConvexError &&\n typeof currResult.data === \"object\" &&\n currResult.data?.isConvexSystemError === true &&\n currResult.data?.paginationError === \"InvalidCursor\")\n ) {\n // - InvalidCursor: If the cursor is invalid, probably the paginated\n // database query was data-dependent and changed underneath us. The\n // cursor in the params or journal no longer matches the current\n // database query.\n\n // In all cases, we want to restart pagination to throw away all our\n // existing cursors.\n logger.warn(\n \"usePaginatedQuery hit error, resetting pagination state: \" +\n currResult.message,\n );\n setState(createInitialState);\n return [[], undefined, undefined];\n } else {\n if (throwOnError) {\n throw currResult;\n }\n return [allItems, undefined, currResult];\n }\n }\n const ongoingSplit = currState.ongoingSplits[pageKey];\n if (ongoingSplit !== undefined) {\n if (\n resultsObject[ongoingSplit[0]] !== undefined &&\n resultsObject[ongoingSplit[1]] !== undefined\n ) {\n // Both pages of the split have results now. Swap them in.\n setState(completeSplitQuery(pageKey));\n }\n } else if (\n currResult.splitCursor &&\n (currResult.pageStatus === \"SplitRecommended\" ||\n currResult.pageStatus === \"SplitRequired\" ||\n currResult.page.length > options.initialNumItems * 2)\n ) {\n // If a single page has more than double the expected number of items,\n // or if the server requests a split, split the page into two.\n setState(\n splitQuery(\n pageKey,\n currResult.splitCursor,\n currResult.continueCursor,\n ),\n );\n }\n if (currResult.pageStatus === \"SplitRequired\") {\n // If pageStatus is 'SplitRequired', it means the server was not able to\n // fetch the full page. So we stop results before the incomplete\n // page and return 'LoadingMore' while the page is splitting.\n return [allItems, undefined, undefined];\n }\n allItems.push(\n ...(isIncludingPageKeys\n ? currResult.page.map((i: any) => ({\n ...i,\n [page]: pageKey.toString(),\n }))\n : currResult.page),\n );\n }\n return [allItems, currResult, undefined];\n }, [\n resultsObject,\n currState.pageKeys,\n currState.ongoingSplits,\n options.initialNumItems,\n createInitialState,\n logger,\n isIncludingPageKeys,\n throwOnError,\n ]);\n\n const statusObject = useMemo(() => {\n if (maybeError !== undefined) {\n return {\n status: \"Error\",\n isLoading: false,\n error: maybeError,\n loadMore: () => {\n // Intentional noop.\n },\n } as const;\n }\n if (maybeLastResult === undefined) {\n if (currState.nextPageKey === 1) {\n return {\n status: \"LoadingFirstPage\",\n isLoading: true,\n loadMore: () => {\n // Intentional noop.\n },\n } as const;\n } else {\n return {\n status: \"LoadingMore\",\n isLoading: true,\n loadMore: (_numItems: number) => {\n // Intentional noop.\n },\n } as const;\n }\n }\n if (maybeLastResult.isDone) {\n return {\n status: \"Exhausted\",\n isLoading: false,\n loadMore: (_numItems: number) => {\n // Intentional noop.\n },\n } as const;\n }\n const continueCursor = maybeLastResult.continueCursor;\n let alreadyLoadingMore = false;\n return {\n status: \"CanLoadMore\",\n isLoading: false,\n loadMore: (numItems: number) => {\n if (!alreadyLoadingMore) {\n alreadyLoadingMore = true;\n setState((prevState) => {\n const pageKeys = [...prevState.pageKeys, prevState.nextPageKey];\n const queries = { ...prevState.queries };\n queries[prevState.nextPageKey] = {\n query: prevState.query,\n args: {\n ...prevState.args,\n paginationOpts: {\n numItems,\n cursor: continueCursor,\n id: prevState.id,\n },\n },\n };\n return {\n ...prevState,\n nextPageKey: prevState.nextPageKey + 1,\n pageKeys,\n queries,\n };\n });\n }\n },\n } as const;\n }, [maybeError, maybeLastResult, currState.nextPageKey]);\n\n return {\n user: {\n results,\n ...statusObject,\n },\n internal: { state: currState },\n };\n}\n\n/**\n * Reshape the internal TitleCase pagination result into the object-form\n * return type with lowercase `status`, `canLoadMore`, and `data`.\n */\nfunction reshapeToObjectForm<Item>(\n internal: UsePaginatedQueryInternalResult<Item>,\n) {\n const { results, loadMore } = internal;\n if (internal.status === \"Error\" && \"error\" in internal) {\n return {\n data: results,\n status: \"error\" as const,\n canLoadMore: false as const,\n isLoading: false as const,\n error: internal.error,\n loadMore,\n };\n }\n if (\n internal.status === \"LoadingFirstPage\" ||\n internal.status === \"LoadingMore\"\n ) {\n return {\n data: internal.status === \"LoadingFirstPage\" ? undefined : results,\n status: \"pending\" as const,\n canLoadMore: false as const,\n isLoading: true as const,\n error: undefined,\n loadMore,\n };\n }\n // CanLoadMore or Exhausted\n return {\n data: results,\n status: \"success\" as const,\n canLoadMore: internal.status === \"CanLoadMore\",\n isLoading: false as const,\n error: undefined,\n loadMore,\n };\n}\n\nlet paginationId = 0;\n/**\n * Generate a new, unique ID for a pagination session.\n *\n * Every usage of {@link usePaginatedQuery} puts a unique ID into the\n * query function arguments as a \"cache-buster\". This serves two purposes:\n *\n * 1. All calls to {@link usePaginatedQuery} have independent query\n * journals.\n *\n * Every time we start a new pagination session, we'll load the first page of\n * results and receive a fresh journal. Without the ID, we might instead reuse\n * a query subscription already present in our client. This isn't desirable\n * because the existing query function result may have grown or shrunk from the\n * requested `initialNumItems`.\n *\n * 2. We can restart the pagination session on some types of errors.\n *\n * Sometimes we want to restart pagination from the beginning if we hit an error.\n * Similar to (1), we'd like to ensure that this new session actually requests\n * its first page from the server and doesn't reuse a query result already\n * present in the client that may have hit the error.\n *\n * @returns The pagination ID.\n */\nfunction nextPaginationId(): number {\n paginationId++;\n return paginationId;\n}\n\n/**\n * Reset pagination id for tests only, so tests know what it is.\n */\nexport function resetPaginationId() {\n paginationId = 0;\n}\n\n/**\n * The result of calling the {@link usePaginatedQuery} hook.\n *\n * This includes:\n * - `results` - An array of the currently loaded results.\n * - `isLoading` - Whether the hook is currently loading results.\n * - `status` - The status of the pagination. The possible statuses are:\n * - \"LoadingFirstPage\": The hook is loading the first page of results.\n * - \"CanLoadMore\": This query may have more items to fetch. Call `loadMore` to\n * fetch another page.\n * - \"LoadingMore\": We're currently loading another page of results.\n * - \"Exhausted\": We've paginated to the end of the list.\n * - `loadMore(n)` A callback to fetch more results. This will only fetch more\n * results if the status is \"CanLoadMore\".\n *\n * @public\n */\nexport type UsePaginatedQueryResult<Item> = {\n results: Item[];\n loadMore: (numItems: number) => void;\n} & (\n | {\n status: \"LoadingFirstPage\";\n isLoading: true;\n }\n | {\n status: \"CanLoadMore\";\n isLoading: false;\n }\n | {\n status: \"LoadingMore\";\n isLoading: true;\n }\n | {\n status: \"Exhausted\";\n isLoading: false;\n }\n);\n\n/**\n * @internal\n */\nexport type UsePaginatedQueryInternalResult<Item> =\n | UsePaginatedQueryResult<Item>\n | {\n results: Item[];\n status: \"Error\";\n isLoading: false;\n error: Error;\n loadMore: (numItems: number) => void;\n };\n\n/**\n * The possible pagination statuses in {@link UsePaginatedQueryResult}.\n *\n * This is a union of string literal types.\n * @public\n */\nexport type PaginationStatus = UsePaginatedQueryResult<any>[\"status\"];\n\n/**\n * Given a {@link PaginatedQueryReference}, get the type of the arguments\n * object for the query, excluding the `paginationOpts` argument.\n *\n * @public\n */\nexport type PaginatedQueryArgs<Query extends PaginatedQueryReference> = Expand<\n BetterOmit<FunctionArgs<Query>, \"paginationOpts\">\n>;\n\n/**\n * Given a {@link PaginatedQueryReference}, get the type of the item being\n * paginated over.\n * @public\n */\nexport type PaginatedQueryItem<Query extends PaginatedQueryReference> =\n FunctionReturnType<Query>[\"page\"][number];\n\n/**\n * The return type of {@link usePaginatedQuery}.\n *\n * @public\n */\nexport type UsePaginatedQueryReturnType<Query extends PaginatedQueryReference> =\n UsePaginatedQueryResult<PaginatedQueryItem<Query>>;\n\n/**\n * Return type of the object-form {@link usePaginatedQuery} overload.\n *\n * Uses lowercase query status (`\"pending\" | \"success\" | \"error\"`) and a\n * `canLoadMore` boolean instead of the TitleCase pagination status strings\n * used by the positional form.\n *\n * @internal\n */\nexport type UsePaginatedQueryObjectReturnType<\n Query extends PaginatedQueryReference,\n> =\n | {\n data: PaginatedQueryItem<Query>[] | undefined;\n status: \"pending\";\n canLoadMore: false;\n isLoading: true;\n error: undefined;\n loadMore: (numItems: number) => void;\n }\n | {\n data: PaginatedQueryItem<Query>[];\n status: \"success\";\n canLoadMore: boolean;\n isLoading: false;\n error: undefined;\n loadMore: (numItems: number) => void;\n }\n | {\n data: PaginatedQueryItem<Query>[];\n status: \"error\";\n canLoadMore: false;\n isLoading: false;\n error: Error;\n loadMore: (numItems: number) => void;\n };\n\n/**\n * Optimistically update the values in a paginated list.\n *\n * This optimistic update is designed to be used to update data loaded with\n * {@link usePaginatedQuery}. It updates the list by applying\n * `updateValue` to each element of the list across all of the loaded pages.\n *\n * This will only apply to queries with a matching names and arguments.\n *\n * Example usage:\n * ```ts\n * const myMutation = useMutation(api.myModule.myMutation)\n * .withOptimisticUpdate((localStore, mutationArg) => {\n *\n * // Optimistically update the document with ID `mutationArg`\n * // to have an additional property.\n *\n * optimisticallyUpdateValueInPaginatedQuery(\n * localStore,\n * api.myModule.paginatedQuery\n * {},\n * currentValue => {\n * if (mutationArg === currentValue._id) {\n * return {\n * ...currentValue,\n * \"newProperty\": \"newValue\",\n * };\n * }\n * return currentValue;\n * }\n * );\n *\n * });\n * ```\n *\n * @param localStore - An {@link OptimisticLocalStore} to update.\n * @param query - A {@link FunctionReference} for the paginated query to update.\n * @param args - The arguments object to the query function, excluding the\n * `paginationOpts` property.\n * @param updateValue - A function to produce the new values.\n *\n * @public\n */\nexport function optimisticallyUpdateValueInPaginatedQuery<\n Query extends PaginatedQueryReference,\n>(\n localStore: OptimisticLocalStore,\n query: Query,\n args: PaginatedQueryArgs<Query>,\n updateValue: (\n currentValue: PaginatedQueryItem<Query>,\n ) => PaginatedQueryItem<Query>,\n): void {\n const expectedArgs = JSON.stringify(convexToJson(args as Value));\n\n for (const queryResult of localStore.getAllQueries(query)) {\n if (queryResult.value !== undefined) {\n const { paginationOpts: _, ...innerArgs } = queryResult.args as {\n paginationOpts: PaginationOptions;\n };\n if (JSON.stringify(convexToJson(innerArgs as Value)) === expectedArgs) {\n const value = queryResult.value;\n if (\n typeof value === \"object\" &&\n value !== null &&\n Array.isArray(value.page)\n ) {\n localStore.setQuery(query, queryResult.args, {\n ...value,\n page: value.page.map(updateValue),\n });\n }\n }\n }\n }\n}\n\n/**\n * Updates a paginated query to insert an element at the top of the list.\n *\n * This is regardless of the sort order, so if the list is in descending order,\n * the inserted element will be treated as the \"biggest\" element, but if it's\n * ascending, it'll be treated as the \"smallest\".\n *\n * Example:\n * ```ts\n * const createTask = useMutation(api.tasks.create)\n * .withOptimisticUpdate((localStore, mutationArgs) => {\n * insertAtTop({\n * paginatedQuery: api.tasks.list,\n * argsToMatch: { listId: mutationArgs.listId },\n * localQueryStore: localStore,\n * item: { _id: crypto.randomUUID() as Id<\"tasks\">, title: mutationArgs.title, completed: false },\n * });\n * });\n * ```\n *\n * @param options.paginatedQuery - A function reference to the paginated query.\n * @param options.argsToMatch - Optional arguments that must be in each relevant paginated query.\n * This is useful if you use the same query function with different arguments to load\n * different lists.\n * @param options.localQueryStore\n * @param options.item The item to insert.\n * @returns\n */\nexport function insertAtTop<Query extends PaginatedQueryReference>(options: {\n paginatedQuery: Query;\n argsToMatch?: Partial<PaginatedQueryArgs<Query>>;\n localQueryStore: OptimisticLocalStore;\n item: PaginatedQueryItem<Query>;\n}) {\n const { paginatedQuery, argsToMatch, localQueryStore, item } = options;\n const queries = localQueryStore.getAllQueries(paginatedQuery);\n const queriesThatMatch = queries.filter((q) => {\n if (argsToMatch === undefined) {\n return true;\n }\n return Object.keys(argsToMatch).every(\n // @ts-expect-error -- This should be safe since both should be plain objects\n (k) => compareValues(argsToMatch[k], q.args[k]) === 0,\n );\n });\n const firstPage = queriesThatMatch.find(\n (q) => q.args.paginationOpts.cursor === null,\n );\n if (firstPage === undefined || firstPage.value === undefined) {\n // first page is not loaded, so don't update it until it loads\n return;\n }\n localQueryStore.setQuery(paginatedQuery, firstPage.args, {\n ...firstPage.value,\n page: [item, ...firstPage.value.page],\n });\n}\n\n/**\n * Updates a paginated query to insert an element at the bottom of the list.\n *\n * This is regardless of the sort order, so if the list is in descending order,\n * the inserted element will be treated as the \"smallest\" element, but if it's\n * ascending, it'll be treated as the \"biggest\".\n *\n * This only has an effect if the last page is loaded, since otherwise it would result\n * in the element being inserted at the end of whatever is loaded (which is the middle of the list)\n * and then popping out once the optimistic update is over.\n *\n * @param options.paginatedQuery - A function reference to the paginated query.\n * @param options.argsToMatch - Optional arguments that must be in each relevant paginated query.\n * This is useful if you use the same query function with different arguments to load\n * different lists.\n * @param options.localQueryStore\n * @param options.element The element to insert.\n * @returns\n */\nexport function insertAtBottomIfLoaded<\n Query extends PaginatedQueryReference,\n>(options: {\n paginatedQuery: Query;\n argsToMatch?: Partial<PaginatedQueryArgs<Query>>;\n localQueryStore: OptimisticLocalStore;\n item: PaginatedQueryItem<Query>;\n}) {\n const { paginatedQuery, localQueryStore, item, argsToMatch } = options;\n const queries = localQueryStore.getAllQueries(paginatedQuery);\n const queriesThatMatch = queries.filter((q) => {\n if (argsToMatch === undefined) {\n return true;\n }\n return Object.keys(argsToMatch).every(\n // @ts-expect-error -- This should be safe since both should be plain objects\n (k) => compareValues(argsToMatch[k], q.args[k]) === 0,\n );\n });\n const lastPage = queriesThatMatch.find(\n (q) => q.value !== undefined && q.value.isDone,\n );\n if (lastPage === undefined) {\n // last page is not loaded, so don't update it since the item would immediately pop out\n // when the server updates\n return;\n }\n localQueryStore.setQuery(paginatedQuery, lastPage.args, {\n ...lastPage.value!,\n page: [...lastPage.value!.page, item],\n });\n}\n\ntype LocalQueryResult<Query extends FunctionReference<\"query\">> = {\n args: FunctionArgs<Query>;\n value: undefined | FunctionReturnType<Query>;\n};\n\ntype LoadedResult<Query extends FunctionReference<\"query\">> = {\n args: FunctionArgs<Query>;\n value: FunctionReturnType<Query>;\n};\n\n/**\n * This is a helper function for inserting an item at a specific position in a paginated query.\n *\n * You must provide the sortOrder and a function for deriving the sort key (an array of values) from an item in the list.\n *\n * This will only work if the server query uses the same sort order and sort key as the optimistic update.\n *\n * Example:\n * ```ts\n * const createTask = useMutation(api.tasks.create)\n * .withOptimisticUpdate((localStore, mutationArgs) => {\n * insertAtPosition({\n * paginatedQuery: api.tasks.listByPriority,\n * argsToMatch: { listId: mutationArgs.listId },\n * sortOrder: \"asc\",\n * sortKeyFromItem: (item) => [item.priority, item._creationTime],\n * localQueryStore: localStore,\n * item: {\n * _id: crypto.randomUUID() as Id<\"tasks\">,\n * _creationTime: Date.now(),\n * title: mutationArgs.title,\n * completed: false,\n * priority: mutationArgs.priority,\n * },\n * });\n * });\n * ```\n * @param options.paginatedQuery - A function reference to the paginated query.\n * @param options.argsToMatch - Optional arguments that must be in each relevant paginated query.\n * This is useful if you use the same query function with different arguments to load\n * different lists.\n * @param options.sortOrder - The sort order of the paginated query (\"asc\" or \"desc\").\n * @param options.sortKeyFromItem - A function for deriving the sort key (an array of values) from an element in the list.\n * Including a tie-breaker field like `_creationTime` is recommended.\n * @param options.localQueryStore\n * @param options.item - The item to insert.\n * @returns\n */\nexport function insertAtPosition<\n Query extends PaginatedQueryReference,\n>(options: {\n paginatedQuery: Query;\n argsToMatch?: Partial<PaginatedQueryArgs<Query>>;\n sortOrder: \"asc\" | \"desc\";\n sortKeyFromItem: (element: PaginatedQueryItem<Query>) => Value | Value[];\n localQueryStore: OptimisticLocalStore;\n item: PaginatedQueryItem<Query>;\n}) {\n const {\n paginatedQuery,\n sortOrder,\n sortKeyFromItem,\n localQueryStore,\n item,\n argsToMatch,\n } = options;\n\n const queries: LocalQueryResult<Query>[] =\n localQueryStore.getAllQueries(paginatedQuery);\n // Group into sets of pages for the same usePaginatedQuery. Grouping is by all\n // args except paginationOpts, but including paginationOpts.id.\n const queryGroups: Record<string, LocalQueryResult<Query>[]> = {};\n for (const query of queries) {\n if (\n argsToMatch !== undefined &&\n !Object.keys(argsToMatch).every(\n (k) =>\n // @ts-ignore why is this not working?\n argsToMatch[k] === query.args[k],\n )\n ) {\n continue;\n }\n const key = JSON.stringify(\n Object.fromEntries(\n Object.entries(query.args).map(([k, v]) => [\n k,\n k === \"paginationOpts\" ? (v as any).id : v,\n ]),\n ),\n );\n queryGroups[key] ??= [];\n queryGroups[key].push(query);\n }\n for (const pageQueries of Object.values(queryGroups)) {\n insertAtPositionInPages({\n pageQueries,\n paginatedQuery,\n sortOrder,\n sortKeyFromItem,\n localQueryStore,\n item,\n });\n }\n}\n\nfunction insertAtPositionInPages<\n Query extends PaginatedQueryReference,\n>(options: {\n pageQueries: LocalQueryResult<Query>[];\n paginatedQuery: Query;\n sortOrder: \"asc\" | \"desc\";\n sortKeyFromItem: (element: PaginatedQueryItem<Query>) => Value | Value[];\n localQueryStore: OptimisticLocalStore;\n item: PaginatedQueryItem<Query>;\n}) {\n const {\n pageQueries,\n sortOrder,\n sortKeyFromItem,\n localQueryStore,\n item,\n paginatedQuery,\n } = options;\n const insertedKey = sortKeyFromItem(item);\n const loadedPages: LoadedResult<Query>[] = pageQueries.filter(\n (q): q is LoadedResult<Query> =>\n q.value !== undefined && q.value.page.length > 0,\n );\n const sortedPages = loadedPages.sort((a, b) => {\n const aKey = sortKeyFromItem(a.value.page[0]);\n const bKey = sortKeyFromItem(b.value.page[0]);\n if (sortOrder === \"asc\") {\n return compareValues(aKey, bKey);\n } else {\n return compareValues(bKey, aKey);\n }\n });\n\n // check if the inserted element is before the first page\n const firstLoadedPage = sortedPages[0];\n if (firstLoadedPage === undefined) {\n // no pages, so don't update until they load\n return;\n }\n const firstPageKey = sortKeyFromItem(firstLoadedPage.value.page[0]);\n const isBeforeFirstPage =\n sortOrder === \"asc\"\n ? compareValues(insertedKey, firstPageKey) <= 0\n : compareValues(insertedKey, firstPageKey) >= 0;\n if (isBeforeFirstPage) {\n if (firstLoadedPage.args.paginationOpts.cursor === null) {\n localQueryStore.setQuery(paginatedQuery, firstLoadedPage.args, {\n ...firstLoadedPage.value,\n page: [item, ...firstLoadedPage.value.page],\n });\n } else {\n // if the very first page is not loaded\n return;\n }\n return;\n }\n\n const lastLoadedPage = sortedPages[sortedPages.length - 1];\n if (lastLoadedPage === undefined) {\n // no pages, so don't update until they load\n return;\n }\n const lastPageKey = sortKeyFromItem(\n lastLoadedPage.value.page[lastLoadedPage.value.page.length - 1],\n );\n const isAfterLastPage =\n sortOrder === \"asc\"\n ? compareValues(insertedKey, lastPageKey) >= 0\n : compareValues(insertedKey, lastPageKey) <= 0;\n if (isAfterLastPage) {\n // Only update if the last page is done loading, otherwise it will pop out\n // when the server updates the query\n if (lastLoadedPage.value.isDone) {\n localQueryStore.setQuery(paginatedQuery, lastLoadedPage.args, {\n ...lastLoadedPage.value,\n page: [...lastLoadedPage.value.page, item],\n });\n }\n return;\n }\n\n // if sorted in ascending order, find the first page that starts with a key greater than the inserted element,\n // and update the page before it\n // if sorted in descending order, find the first page that starts with a key less than the inserted element,\n // and update the page before it\n\n const successorPageIndex = sortedPages.findIndex((p) =>\n sortOrder === \"asc\"\n ? compareValues(sortKeyFromItem(p.value.page[0]), insertedKey) > 0\n : compareValues(sortKeyFromItem(p.value.page[0]), insertedKey) < 0,\n );\n const pageToUpdate =\n successorPageIndex === -1\n ? sortedPages[sortedPages.length - 1]\n : sortedPages[successorPageIndex - 1];\n if (pageToUpdate === undefined) {\n // no pages, so don't update until they load\n return;\n }\n // If ascending, find the first element that is greater than or equal to the inserted element\n // If descending, find the first element that is less than or equal to the inserted element\n const indexWithinPage = pageToUpdate.value.page.findIndex((e) =>\n sortOrder === \"asc\"\n ? compareValues(sortKeyFromItem(e), insertedKey) >= 0\n : compareValues(sortKeyFromItem(e), insertedKey) <= 0,\n );\n const newPage =\n indexWithinPage === -1\n ? [...pageToUpdate.value.page, item]\n : [\n ...pageToUpdate.value.page.slice(0, indexWithinPage),\n item,\n ...pageToUpdate.value.page.slice(indexWithinPage),\n ];\n localQueryStore.setQuery(paginatedQuery, pageToUpdate.args, {\n ...pageToUpdate.value,\n page: newPage,\n });\n}\n", "/*\nhttps://github.com/beatgammit/base64-js/blob/88957c9943c7e2a0f03cdf73e71d579e433627d3/index.js\nCopyright (c) 2014 Jameson Little\nThe MIT License (MIT)\n*/\n\n// Vendored because this library has no ESM build, and some environments\n// (SvelteKit) are happiest when all dependencies are ESM.\n\nvar lookup: string[] = [];\nvar revLookup: number[] = [];\nvar Arr = Uint8Array;\n\nvar code = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\nfor (var i = 0, len = code.length; i < len; ++i) {\n lookup[i] = code[i];\n revLookup[code.charCodeAt(i)] = i;\n}\n\n// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup[\"-\".charCodeAt(0)] = 62;\nrevLookup[\"_\".charCodeAt(0)] = 63;\n\nfunction getLens(b64: string) {\n var len = b64.length;\n\n if (len % 4 > 0) {\n throw new Error(\"Invalid string. Length must be a multiple of 4\");\n }\n\n // Trim off extra bytes after placeholder bytes are found\n // See: https://github.com/beatgammit/base64-js/issues/42\n var validLen = b64.indexOf(\"=\");\n if (validLen === -1) validLen = len;\n\n var placeHoldersLen = validLen === len ? 0 : 4 - (validLen % 4);\n\n return [validLen, placeHoldersLen];\n}\n\n// base64 is 4/3 + up to two characters of the original data\n/** @public */\nexport function byteLength(b64: string): number {\n var lens = getLens(b64);\n var validLen = lens[0];\n var placeHoldersLen = lens[1];\n return ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen;\n}\n\nfunction _byteLength(_b64: string, validLen: number, placeHoldersLen: number) {\n return ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen;\n}\n\n/** @public */\nexport function toByteArray(b64: string): Uint8Array {\n var tmp;\n var lens = getLens(b64);\n var validLen = lens[0];\n var placeHoldersLen = lens[1];\n\n var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen));\n\n var curByte = 0;\n\n // if there are placeholders, only get up to the last complete 4 chars\n var len = placeHoldersLen > 0 ? validLen - 4 : validLen;\n\n var i;\n for (i = 0; i < len; i += 4) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 18) |\n (revLookup[b64.charCodeAt(i + 1)] << 12) |\n (revLookup[b64.charCodeAt(i + 2)] << 6) |\n revLookup[b64.charCodeAt(i + 3)];\n arr[curByte++] = (tmp >> 16) & 0xff;\n arr[curByte++] = (tmp >> 8) & 0xff;\n arr[curByte++] = tmp & 0xff;\n }\n\n if (placeHoldersLen === 2) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 2) |\n (revLookup[b64.charCodeAt(i + 1)] >> 4);\n arr[curByte++] = tmp & 0xff;\n }\n\n if (placeHoldersLen === 1) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 10) |\n (revLookup[b64.charCodeAt(i + 1)] << 4) |\n (revLookup[b64.charCodeAt(i + 2)] >> 2);\n arr[curByte++] = (tmp >> 8) & 0xff;\n arr[curByte++] = tmp & 0xff;\n }\n\n return arr;\n}\n\nfunction tripletToBase64(num: number) {\n return (\n lookup[(num >> 18) & 0x3f] +\n lookup[(num >> 12) & 0x3f] +\n lookup[(num >> 6) & 0x3f] +\n lookup[num & 0x3f]\n );\n}\n\nfunction encodeChunk(uint8: Uint8Array, start: number, end: number) {\n var tmp;\n var output = [];\n for (var i = start; i < end; i += 3) {\n tmp =\n ((uint8[i] << 16) & 0xff0000) +\n ((uint8[i + 1] << 8) & 0xff00) +\n (uint8[i + 2] & 0xff);\n output.push(tripletToBase64(tmp));\n }\n return output.join(\"\");\n}\n\n/** @public */\nexport function fromByteArray(uint8: Uint8Array): string {\n var tmp;\n var len = uint8.length;\n var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes\n var parts = [];\n var maxChunkLength = 16383; // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(\n encodeChunk(\n uint8,\n i,\n i + maxChunkLength > len2 ? len2 : i + maxChunkLength,\n ),\n );\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1];\n parts.push(lookup[tmp >> 2] + lookup[(tmp << 4) & 0x3f] + \"==\");\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + uint8[len - 1];\n parts.push(\n lookup[tmp >> 10] +\n lookup[(tmp >> 4) & 0x3f] +\n lookup[(tmp << 2) & 0x3f] +\n \"=\",\n );\n }\n\n return parts.join(\"\");\n}\n\nexport function fromByteArrayUrlSafeNoPadding(uint8: Uint8Array): string {\n return fromByteArray(uint8)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=/g, \"\");\n}\n", "import type { Value } from \"../values/value.js\";\n\n/**\n * Validate that the arguments to a Convex function are an object, defaulting\n * `undefined` to `{}`.\n */\nexport function parseArgs(\n args: Record<string, Value> | undefined,\n): Record<string, Value> {\n if (args === undefined) {\n return {};\n }\n if (!isSimpleObject(args)) {\n throw new Error(\n `The arguments to a Convex function must be an object. Received: ${\n args as any\n }`,\n );\n }\n return args;\n}\n\nexport function validateDeploymentUrl(deploymentUrl: string) {\n // Don't use things like `new URL(deploymentUrl).hostname` since these aren't\n // supported by React Native's JS environment\n if (typeof deploymentUrl === \"undefined\") {\n throw new Error(\n `Client created with undefined deployment address. If you used an environment variable, check that it's set.`,\n );\n }\n if (typeof deploymentUrl !== \"string\") {\n throw new Error(\n `Invalid deployment address: found ${deploymentUrl as any}\".`,\n );\n }\n if (\n !(deploymentUrl.startsWith(\"http:\") || deploymentUrl.startsWith(\"https:\"))\n ) {\n throw new Error(\n `Invalid deployment address: Must start with \"https://\" or \"http://\". Found \"${deploymentUrl}\".`,\n );\n }\n\n // Most clients should connect to \".convex.cloud\". But we also support localhost and\n // custom custom. We validate the deployment url is a valid url, which is the most\n // common failure pattern.\n try {\n new URL(deploymentUrl);\n } catch {\n throw new Error(\n `Invalid deployment address: \"${deploymentUrl}\" is not a valid URL. If you believe this URL is correct, use the \\`skipConvexDeploymentUrlCheck\\` option to bypass this.`,\n );\n }\n\n // If a user uses .convex.site, this is very likely incorrect.\n if (deploymentUrl.endsWith(\".convex.site\")) {\n throw new Error(\n `Invalid deployment address: \"${deploymentUrl}\" ends with .convex.site, which is used for HTTP Actions. Convex deployment URLs typically end with .convex.cloud? If you believe this URL is correct, use the \\`skipConvexDeploymentUrlCheck\\` option to bypass this.`,\n );\n }\n}\n\n/**\n * Check whether a value is a plain old JavaScript object.\n */\nexport function isSimpleObject(value: unknown) {\n const isObject = typeof value === \"object\";\n const prototype = Object.getPrototypeOf(value);\n const isSimple =\n prototype === null ||\n prototype === Object.prototype ||\n // Objects generated from other contexts (e.g. across Node.js `vm` modules) will not satisfy the previous\n // conditions but are still simple objects.\n prototype?.constructor?.name === \"Object\";\n return isObject && isSimple;\n}\n", "/**\n * Utilities for working with values stored in Convex.\n *\n * You can see the full set of supported types at\n * [Types](https://docs.convex.dev/using/types).\n * @module\n */\nimport * as Base64 from \"./base64.js\";\nimport { isSimpleObject } from \"../common/index.js\";\n\nconst LITTLE_ENDIAN = true;\n// This code is used by code that may not have bigint literals.\nconst MIN_INT64 = BigInt(\"-9223372036854775808\");\nconst MAX_INT64 = BigInt(\"9223372036854775807\");\nconst ZERO = BigInt(\"0\");\nconst EIGHT = BigInt(\"8\");\nconst TWOFIFTYSIX = BigInt(\"256\");\n\n/**\n * The type of JavaScript values serializable to JSON.\n *\n * @public\n */\nexport type JSONValue =\n | null\n | boolean\n | number\n | string\n | JSONValue[]\n | { [key: string]: JSONValue };\n\n/**\n * An identifier for a document in Convex.\n *\n * Convex documents are uniquely identified by their `Id`, which is accessible\n * on the `_id` field. To learn more, see [Document IDs](https://docs.convex.dev/database/document-ids).\n *\n * Documents can be loaded using `db.get(tableName, id)` in query and mutation functions.\n *\n * IDs are base 32 encoded strings which are URL safe.\n *\n * IDs are just strings at runtime, but this type can be used to distinguish them from other\n * strings at compile time.\n *\n * If you're using code generation, use the `Id` type generated for your data model in\n * `convex/_generated/dataModel.d.ts`.\n *\n * @typeParam TableName - A string literal type of the table name (like \"users\").\n *\n * @public\n */\nexport type Id<TableName extends string> = string & { __tableName: TableName };\n\n/**\n * A value supported by Convex.\n *\n * Values can be:\n * - stored inside of documents.\n * - used as arguments and return types to queries and mutation functions.\n *\n * You can see the full set of supported types at\n * [Types](https://docs.convex.dev/using/types).\n *\n * @public\n */\nexport type Value =\n | null\n | bigint\n | number\n | boolean\n | string\n | ArrayBuffer\n | Value[]\n | { [key: string]: undefined | Value };\n\n/**\n * The types of {@link Value} that can be used to represent numbers.\n *\n * @public\n */\nexport type NumericValue = bigint | number;\n\nfunction isSpecial(n: number) {\n return Number.isNaN(n) || !Number.isFinite(n) || Object.is(n, -0);\n}\n\nexport function slowBigIntToBase64(value: bigint): string {\n // the conversion is easy if we pretend it's unsigned\n if (value < ZERO) {\n value -= MIN_INT64 + MIN_INT64;\n }\n let hex = value.toString(16);\n if (hex.length % 2 === 1) hex = \"0\" + hex;\n\n const bytes = new Uint8Array(new ArrayBuffer(8));\n let i = 0;\n for (const hexByte of hex.match(/.{2}/g)!.reverse()) {\n bytes.set([parseInt(hexByte, 16)], i++);\n value >>= EIGHT;\n }\n return Base64.fromByteArray(bytes);\n}\n\nexport function slowBase64ToBigInt(encoded: string): bigint {\n const integerBytes = Base64.toByteArray(encoded);\n if (integerBytes.byteLength !== 8) {\n throw new Error(\n `Received ${integerBytes.byteLength} bytes, expected 8 for $integer`,\n );\n }\n let value = ZERO;\n let power = ZERO;\n for (const byte of integerBytes) {\n value += BigInt(byte) * TWOFIFTYSIX ** power;\n power++;\n }\n if (value > MAX_INT64) {\n value += MIN_INT64 + MIN_INT64;\n }\n return value;\n}\n\nexport function modernBigIntToBase64(value: bigint): string {\n if (value < MIN_INT64 || MAX_INT64 < value) {\n throw new Error(\n `BigInt ${value} does not fit into a 64-bit signed integer.`,\n );\n }\n const buffer = new ArrayBuffer(8);\n new DataView(buffer).setBigInt64(0, value, true);\n return Base64.fromByteArray(new Uint8Array(buffer));\n}\n\nexport function modernBase64ToBigInt(encoded: string): bigint {\n const integerBytes = Base64.toByteArray(encoded);\n if (integerBytes.byteLength !== 8) {\n throw new Error(\n `Received ${integerBytes.byteLength} bytes, expected 8 for $integer`,\n );\n }\n const intBytesView = new DataView(integerBytes.buffer);\n return intBytesView.getBigInt64(0, true);\n}\n\n// Fall back to a slower version on Safari 14 which lacks these APIs.\nexport const bigIntToBase64 = (DataView.prototype as any).setBigInt64\n ? modernBigIntToBase64\n : slowBigIntToBase64;\nexport const base64ToBigInt = (DataView.prototype as any).getBigInt64\n ? modernBase64ToBigInt\n : slowBase64ToBigInt;\n\nconst MAX_IDENTIFIER_LEN = 1024;\n\nfunction validateObjectField(k: string) {\n if (k.length > MAX_IDENTIFIER_LEN) {\n throw new Error(\n `Field name ${k} exceeds maximum field name length ${MAX_IDENTIFIER_LEN}.`,\n );\n }\n if (k.startsWith(\"$\")) {\n throw new Error(`Field name ${k} starts with a '$', which is reserved.`);\n }\n for (let i = 0; i < k.length; i += 1) {\n const charCode = k.charCodeAt(i);\n // Non-control ASCII characters\n if (charCode < 32 || charCode >= 127) {\n throw new Error(\n `Field name ${k} has invalid character '${k[i]}': Field names can only contain non-control ASCII characters`,\n );\n }\n }\n}\n\n/**\n * Parse a Convex value from its JSON representation.\n *\n * This function will deserialize serialized Int64s to `BigInt`s, Bytes to `ArrayBuffer`s etc.\n *\n * To learn more about Convex values, see [Types](https://docs.convex.dev/using/types).\n *\n * @param value - The JSON representation of a Convex value previously created with {@link convexToJson}.\n * @returns The JavaScript representation of the Convex value.\n *\n * @public\n */\nexport function jsonToConvex(value: JSONValue): Value {\n if (value === null) {\n return value;\n }\n if (typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"number\") {\n return value;\n }\n if (typeof value === \"string\") {\n return value;\n }\n if (Array.isArray(value)) {\n return value.map((value) => jsonToConvex(value));\n }\n if (typeof value !== \"object\") {\n throw new Error(`Unexpected type of ${value as any}`);\n }\n const entries = Object.entries(value);\n if (entries.length === 1) {\n const key = entries[0][0];\n if (key === \"$bytes\") {\n if (typeof value.$bytes !== \"string\") {\n throw new Error(`Malformed $bytes field on ${value as any}`);\n }\n return Base64.toByteArray(value.$bytes).buffer;\n }\n if (key === \"$integer\") {\n if (typeof value.$integer !== \"string\") {\n throw new Error(`Malformed $integer field on ${value as any}`);\n }\n return base64ToBigInt(value.$integer);\n }\n if (key === \"$float\") {\n if (typeof value.$float !== \"string\") {\n throw new Error(`Malformed $float field on ${value as any}`);\n }\n const floatBytes = Base64.toByteArray(value.$float);\n if (floatBytes.byteLength !== 8) {\n throw new Error(\n `Received ${floatBytes.byteLength} bytes, expected 8 for $float`,\n );\n }\n const floatBytesView = new DataView(floatBytes.buffer);\n const float = floatBytesView.getFloat64(0, LITTLE_ENDIAN);\n if (!isSpecial(float)) {\n throw new Error(`Float ${float} should be encoded as a number`);\n }\n return float;\n }\n if (key === \"$set\") {\n throw new Error(\n `Received a Set which is no longer supported as a Convex type.`,\n );\n }\n if (key === \"$map\") {\n throw new Error(\n `Received a Map which is no longer supported as a Convex type.`,\n );\n }\n }\n const out: { [key: string]: Value } = {};\n for (const [k, v] of Object.entries(value)) {\n validateObjectField(k);\n out[k] = jsonToConvex(v);\n }\n return out;\n}\n\nconst MAX_VALUE_FOR_ERROR_LEN = 16384;\n\nexport function stringifyValueForError(value: any) {\n const str = JSON.stringify(value, (_key, value) => {\n if (value === undefined) {\n // By default `JSON.stringify` converts undefined, functions, symbols,\n // Infinity, and NaN to null which produces a confusing error message.\n // We deal with `undefined` specifically because it's the most common.\n // Ideally we'd use a pretty-printing library that prints `undefined`\n // (no quotes), but it might not be worth the bundle size cost.\n return \"undefined\";\n }\n if (typeof value === \"bigint\") {\n // `JSON.stringify` throws on bigints by default.\n return `${value.toString()}n`;\n }\n return value;\n });\n if (str.length > MAX_VALUE_FOR_ERROR_LEN) {\n const rest = \"[...truncated]\";\n let truncateAt = MAX_VALUE_FOR_ERROR_LEN - rest.length;\n const codePoint = str.codePointAt(truncateAt - 1);\n if (codePoint !== undefined && codePoint > 0xffff) {\n // don't split a surrogate pair in half\n truncateAt -= 1;\n }\n return str.substring(0, truncateAt) + rest;\n }\n return str;\n}\n\nfunction convexToJsonInternal(\n value: Value,\n originalValue: Value,\n context: string,\n includeTopLevelUndefined: boolean,\n): JSONValue {\n if (value === undefined) {\n const contextText =\n context &&\n ` (present at path ${context} in original object ${stringifyValueForError(\n originalValue,\n )})`;\n throw new Error(\n `undefined is not a valid Convex value${contextText}. To learn about Convex's supported types, see https://docs.convex.dev/using/types.`,\n );\n }\n if (value === null) {\n return value;\n }\n if (typeof value === \"bigint\") {\n if (value < MIN_INT64 || MAX_INT64 < value) {\n throw new Error(\n `BigInt ${value} does not fit into a 64-bit signed integer.`,\n );\n }\n return { $integer: bigIntToBase64(value) };\n }\n if (typeof value === \"number\") {\n if (isSpecial(value)) {\n const buffer = new ArrayBuffer(8);\n new DataView(buffer).setFloat64(0, value, LITTLE_ENDIAN);\n return { $float: Base64.fromByteArray(new Uint8Array(buffer)) };\n } else {\n return value;\n }\n }\n if (typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"string\") {\n return value;\n }\n if (value instanceof ArrayBuffer) {\n return { $bytes: Base64.fromByteArray(new Uint8Array(value)) };\n }\n if (Array.isArray(value)) {\n return value.map((value, i) =>\n convexToJsonInternal(value, originalValue, context + `[${i}]`, false),\n );\n }\n if (value instanceof Set) {\n throw new Error(\n errorMessageForUnsupportedType(context, \"Set\", [...value], originalValue),\n );\n }\n if (value instanceof Map) {\n throw new Error(\n errorMessageForUnsupportedType(context, \"Map\", [...value], originalValue),\n );\n }\n\n if (!isSimpleObject(value)) {\n const theType = value?.constructor?.name;\n const typeName = theType ? `${theType} ` : \"\";\n throw new Error(\n errorMessageForUnsupportedType(context, typeName, value, originalValue),\n );\n }\n\n const out: { [key: string]: JSONValue } = {};\n const entries = Object.entries(value);\n entries.sort(([k1, _v1], [k2, _v2]) => (k1 === k2 ? 0 : k1 < k2 ? -1 : 1));\n for (const [k, v] of entries) {\n if (v !== undefined) {\n validateObjectField(k);\n out[k] = convexToJsonInternal(v, originalValue, context + `.${k}`, false);\n } else if (includeTopLevelUndefined) {\n validateObjectField(k);\n out[k] = convexOrUndefinedToJsonInternal(\n v,\n originalValue,\n context + `.${k}`,\n );\n }\n }\n return out;\n}\n\nfunction errorMessageForUnsupportedType(\n context: string,\n typeName: string,\n value: any,\n originalValue: any,\n) {\n if (context) {\n return `${typeName}${stringifyValueForError(\n value,\n )} is not a supported Convex type (present at path ${context} in original object ${stringifyValueForError(\n originalValue,\n )}). To learn about Convex's supported types, see https://docs.convex.dev/using/types.`;\n } else {\n return `${typeName}${stringifyValueForError(\n value,\n )} is not a supported Convex type.`;\n }\n}\n\n// convexOrUndefinedToJsonInternal wrapper exists so we can pipe through the\n// `originalValue` and `context` through for better error messaging.\nfunction convexOrUndefinedToJsonInternal(\n value: Value | undefined,\n originalValue: Value | undefined,\n context: string,\n): JSONValue {\n if (value === undefined) {\n return { $undefined: null };\n } else {\n if (originalValue === undefined) {\n // This should not happen.\n throw new Error(\n `Programming error. Current value is ${stringifyValueForError(\n value,\n )} but original value is undefined`,\n );\n }\n return convexToJsonInternal(value, originalValue, context, false);\n }\n}\n\n/**\n * Convert a Convex value to its JSON representation.\n *\n * Use {@link jsonToConvex} to recreate the original value.\n *\n * To learn more about Convex values, see [Types](https://docs.convex.dev/using/types).\n *\n * @param value - A Convex value to convert into JSON.\n * @returns The JSON representation of `value`.\n *\n * @public\n */\nexport function convexToJson(value: Value): JSONValue {\n return convexToJsonInternal(value, value, \"\", false);\n}\n\n// Convert a Convex value or `undefined` into its JSON representation.\n// `undefined` is used in filters to represent a missing object field.\nexport function convexOrUndefinedToJson(value: Value | undefined): JSONValue {\n return convexOrUndefinedToJsonInternal(value, value, \"\");\n}\n\n/**\n * Similar to convexToJson but also serializes top level undefined fields\n * using convexOrUndefinedToJson().\n *\n * @param value - A Convex value to convert into JSON.\n * @returns The JSON representation of `value`.\n */\nexport function patchValueToJson(value: Value): JSONValue {\n return convexToJsonInternal(value, value, \"\", true);\n}\n", "import { Value, stringifyValueForError } from \"./value.js\";\n\nconst IDENTIFYING_FIELD = Symbol.for(\"ConvexError\");\n\nexport class ConvexError<TData extends Value> extends Error {\n name = \"ConvexError\";\n data: TData;\n [IDENTIFYING_FIELD] = true;\n\n constructor(data: TData) {\n super(typeof data === \"string\" ? data : stringifyValueForError(data));\n this.data = data;\n }\n}\n", "/**\n * Taken from https://github.com/rocicorp/compare-utf8/blob/main/LICENSE\n * (Apache Version 2.0, January 2004)\n */\n\n/**\n * This is copied here instead of added as a dependency to avoid bundling issues.\n */\n\n/**\n * Compares two JavaScript strings as if they were UTF-8 encoded byte arrays.\n * @param {string} a\n * @param {string} b\n * @returns {number}\n */\nexport function compareUTF8(a: string, b: string): number {\n const aLength = a.length;\n const bLength = b.length;\n const length = Math.min(aLength, bLength);\n for (let i = 0; i < length; ) {\n const aCodePoint = a.codePointAt(i)!;\n const bCodePoint = b.codePointAt(i)!;\n if (aCodePoint !== bCodePoint) {\n // Code points below 0x80 are represented the same way in UTF-8 as in\n // UTF-16.\n if (aCodePoint < 0x80 && bCodePoint < 0x80) {\n return aCodePoint - bCodePoint;\n }\n\n // get the UTF-8 bytes for the code points\n const aLength = utf8Bytes(aCodePoint, aBytes);\n const bLength = utf8Bytes(bCodePoint, bBytes);\n return compareArrays(aBytes, aLength, bBytes, bLength);\n }\n\n i += utf16LengthForCodePoint(aCodePoint);\n }\n\n return aLength - bLength;\n}\n\n/**\n * @param {number[]} a\n * @param {number} aLength\n * @param {number[]} b\n * @param {number} bLength\n * @returns {number}\n */\nfunction compareArrays(\n a: number[],\n aLength: number,\n b: number[],\n bLength: number,\n) {\n const length = Math.min(aLength, bLength);\n for (let i = 0; i < length; i++) {\n const aValue = a[i];\n const bValue = b[i];\n if (aValue !== bValue) {\n return aValue - bValue;\n }\n }\n return aLength - bLength;\n}\n\n/**\n * @param {number} aCodePoint\n * @returns {number}\n */\nexport function utf16LengthForCodePoint(aCodePoint: number) {\n return aCodePoint > 0xffff ? 2 : 1;\n}\n\n// 2 preallocated arrays for utf8Bytes.\nconst arr = () => Array.from({ length: 4 }, () => 0);\nconst aBytes = arr();\nconst bBytes = arr();\n\n/**\n * @param {number} codePoint\n * @param {number[]} bytes\n * @returns {number}\n */\nfunction utf8Bytes(codePoint: number, bytes: number[]) {\n if (codePoint < 0x80) {\n bytes[0] = codePoint;\n return 1;\n }\n\n let count;\n let offset;\n\n if (codePoint <= 0x07ff) {\n count = 1;\n offset = 0xc0;\n } else if (codePoint <= 0xffff) {\n count = 2;\n offset = 0xe0;\n } else if (codePoint <= 0x10ffff) {\n count = 3;\n offset = 0xf0;\n } else {\n throw new Error(\"Invalid code point\");\n }\n\n bytes[0] = (codePoint >> (6 * count)) + offset;\n let i = 1;\n for (; count > 0; count--) {\n const temp = codePoint >> (6 * (count - 1));\n bytes[i++] = 0x80 | (temp & 0x3f);\n }\n return i;\n}\n\n/**\n * @param {string} a\n * @param {string} b\n * @returns {boolean}\n */\nexport function greaterThan(a: string, b: string) {\n return compareUTF8(a, b) > 0;\n}\n\n/**\n * @param {string} a\n * @param {string} b\n * @returns {boolean}\n */\nexport function greaterThanEq(a: string, b: string) {\n return compareUTF8(a, b) >= 0;\n}\n\n/**\n * @param {string} a\n * @param {string} b\n * @returns {boolean}\n */\nexport function lessThan(a: string, b: string) {\n return compareUTF8(a, b) < 0;\n}\n\n/**\n * @param {string} a\n * @param {string} b\n * @returns {boolean}\n */\nexport function lessThanEq(a: string, b: string) {\n return compareUTF8(a, b) <= 0;\n}\n", "import { Value } from \"./value.js\";\nimport { compareUTF8 } from \"./compare_utf8.js\";\n\nexport function compareValues(k1: Value | undefined, k2: Value | undefined) {\n return compareAsTuples(makeComparable(k1), makeComparable(k2));\n}\n\nfunction compareAsTuples<T>(a: [number, T], b: [number, T]): number {\n if (a[0] === b[0]) {\n return compareSameTypeValues(a[1], b[1]);\n } else if (a[0] < b[0]) {\n return -1;\n }\n return 1;\n}\n\nfunction compareSameTypeValues<T>(v1: T, v2: T): number {\n if (v1 === undefined || v1 === null) {\n return 0;\n }\n if (typeof v1 === \"number\") {\n if (typeof v2 !== \"number\") {\n throw new Error(`Unexpected type ${v2 as any}`);\n }\n return compareNumbers(v1, v2);\n }\n if (typeof v1 === \"string\") {\n if (typeof v2 !== \"string\") {\n throw new Error(`Unexpected type ${v2 as any}`);\n }\n return compareUTF8(v1, v2);\n }\n if (\n typeof v1 === \"bigint\" ||\n typeof v1 === \"boolean\" ||\n typeof v1 === \"string\"\n ) {\n return v1 < v2 ? -1 : v1 === v2 ? 0 : 1;\n }\n if (!Array.isArray(v1) || !Array.isArray(v2)) {\n throw new Error(`Unexpected type ${v1 as any}`);\n }\n for (let i = 0; i < v1.length && i < v2.length; i++) {\n const cmp = compareAsTuples(v1[i], v2[i]);\n if (cmp !== 0) {\n return cmp;\n }\n }\n if (v1.length < v2.length) {\n return -1;\n }\n if (v1.length > v2.length) {\n return 1;\n }\n return 0;\n}\n\nfunction compareNumbers(v1: number, v2: number): number {\n // Handle NaN values\n if (isNaN(v1) || isNaN(v2)) {\n // Create DataViews for bit-level comparison\n const buffer1 = new ArrayBuffer(8);\n const buffer2 = new ArrayBuffer(8);\n new DataView(buffer1).setFloat64(0, v1, /* little-endian */ true);\n new DataView(buffer2).setFloat64(0, v2, /* little-endian */ true);\n\n // Read as BigInt to compare bits\n const v1Bits = BigInt(\n new DataView(buffer1).getBigInt64(0, /* little-endian */ true),\n );\n const v2Bits = BigInt(\n new DataView(buffer2).getBigInt64(0, /* little-endian */ true),\n );\n\n // The sign bit is the most significant bit (bit 63)\n const v1Sign = (v1Bits & 0x8000000000000000n) !== 0n;\n const v2Sign = (v2Bits & 0x8000000000000000n) !== 0n;\n\n // If one value is NaN and the other isn't, use sign bits first\n if (isNaN(v1) !== isNaN(v2)) {\n // If v1 is NaN, compare based on sign bits\n if (isNaN(v1)) {\n return v1Sign ? -1 : 1;\n }\n // If v2 is NaN, compare based on sign bits\n return v2Sign ? 1 : -1;\n }\n\n // If both are NaN, compare their binary representations\n if (v1Sign !== v2Sign) {\n return v1Sign ? -1 : 1; // true means negative\n }\n return v1Bits < v2Bits ? -1 : v1Bits === v2Bits ? 0 : 1;\n }\n\n if (Object.is(v1, v2)) {\n return 0;\n }\n\n if (Object.is(v1, -0)) {\n return Object.is(v2, 0) ? -1 : -Math.sign(v2);\n }\n if (Object.is(v2, -0)) {\n return Object.is(v1, 0) ? 1 : Math.sign(v1);\n }\n\n // Handle regular number comparison\n return v1 < v2 ? -1 : 1;\n}\n\n// Returns an array which can be compared to other arrays as if they were tuples.\n// For example, [1, null] < [2, 1n] means null sorts before all bigints\n// And [3, 5] < [3, 6] means floats sort as expected\n// And [7, [[5, \"a\"]]] < [7, [[5, \"a\"], [5, \"b\"]]] means arrays sort as expected\nfunction makeComparable(v: Value | undefined): [number, any] {\n if (v === undefined) {\n return [0, undefined];\n }\n if (v === null) {\n return [1, null];\n }\n if (typeof v === \"bigint\") {\n return [2, v];\n }\n if (typeof v === \"number\") {\n return [3, v];\n }\n if (typeof v === \"boolean\") {\n return [4, v];\n }\n if (typeof v === \"string\") {\n return [5, v];\n }\n if (v instanceof ArrayBuffer) {\n return [6, Array.from(new Uint8Array(v)).map(makeComparable)];\n }\n if (Array.isArray(v)) {\n return [7, v.map(makeComparable)];\n }\n // Otherwise, it's an POJO.\n const keys = Object.keys(v).sort();\n const pojo: Value[] = keys.map((k) => [k, v[k]!]);\n return [8, pojo.map(makeComparable)];\n}\n", "import { Value } from \"../values/index.js\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useConvex } from \"./client.js\";\nimport { CreateWatch, QueriesObserver } from \"./queries_observer.js\";\nimport { useSubscription } from \"./use_subscription.js\";\nimport { QueryJournal } from \"../browser/index.js\";\nimport { FunctionReference } from \"../server/api.js\";\nimport { SubscribeToPaginatedQueryOptions } from \"../browser/sync/paginated_query_client.js\";\n\n/**\n * Load a variable number of reactive Convex queries.\n *\n * `useQueries` is similar to {@link useQuery} but it allows\n * loading multiple queries which can be useful for loading a dynamic number\n * of queries without violating the rules of React hooks.\n *\n * This hook accepts an object whose keys are identifiers for each query and the\n * values are objects of `{ query: FunctionReference, args: Record<string, Value> }`. The\n * `query` is a FunctionReference for the Convex query function to load, and the `args` are\n * the arguments to that function.\n *\n * The hook returns an object that maps each identifier to the result of the query,\n * `undefined` if the query is still loading, or an instance of `Error` if the query\n * threw an exception.\n *\n * For example if you loaded a query like:\n * ```typescript\n * const results = useQueries({\n * messagesInGeneral: {\n * query: \"listMessages\",\n * args: { channel: \"#general\" }\n * }\n * });\n * ```\n * then the result would look like:\n * ```typescript\n * {\n * messagesInGeneral: [{\n * channel: \"#general\",\n * body: \"hello\"\n * _id: ...,\n * _creationTime: ...\n * }]\n * }\n * ```\n *\n * This React hook contains internal state that will cause a rerender\n * whenever any of the query results change.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @param queries - An object mapping identifiers to objects of\n * `{query: string, args: Record<string, Value> }` describing which query\n * functions to fetch.\n * @returns An object with the same keys as the input. The values are the result\n * of the query function, `undefined` if it's still loading, or an `Error` if\n * it threw an exception.\n *\n * @public\n */\nexport function useQueries(\n queries: RequestForQueries,\n): Record<string, any | undefined | Error> {\n const convex = useConvex();\n if (convex === undefined) {\n // Error message includes `useQuery` because this hook is called by `useQuery`\n // more often than it's called directly.\n throw new Error(\n \"Could not find Convex client! `useQuery` must be used in the React component \" +\n \"tree under `ConvexProvider`. Did you forget it? \" +\n \"See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app\",\n );\n }\n const createWatch = useMemo(() => {\n return (\n query: FunctionReference<\"query\">,\n args: Record<string, Value>,\n {\n journal,\n paginationOptions,\n }: {\n journal?: QueryJournal;\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n },\n ) => {\n if (paginationOptions) {\n return convex.watchPaginatedQuery(query, args, paginationOptions);\n } else {\n return convex.watchQuery(query, args, journal ? { journal } : {});\n }\n };\n }, [convex]);\n return useQueriesHelper(queries, createWatch);\n}\n\n/**\n * Internal version of `useQueries` that is exported for testing.\n */\nexport function useQueriesHelper(\n queries: RequestForQueries,\n createWatch: CreateWatch,\n): Record<string, any | undefined | Error> {\n const [observer] = useState(() => new QueriesObserver(createWatch));\n\n if (observer.createWatch !== createWatch) {\n observer.setCreateWatch(createWatch);\n }\n\n // Unsubscribe from all queries on unmount.\n useEffect(() => () => observer.destroy(), [observer]);\n\n const subscription = useMemo(\n () => ({\n getCurrentValue: () => {\n return observer.getLocalResults(queries);\n },\n subscribe: (callback: () => void) => {\n observer.setQueries(queries);\n return observer.subscribe(callback);\n },\n }),\n [observer, queries],\n );\n\n return useSubscription(subscription);\n}\n\n/**\n * An object representing a request to load multiple queries.\n *\n * The keys of this object are identifiers and the values are objects containing\n * the query function and the arguments to pass to it.\n *\n * This is used as an argument to {@link useQueries}.\n * @public\n */\nexport type RequestForQueries = Record<\n string,\n {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n /** @internal */\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n }\n>;\n", "export const version = \"1.36.0\";\n", "/* eslint-disable no-console */ // This is the one file where we can `console.log` for the default logger implementation.\nimport { ConvexError, Value } from \"../values/index.js\";\nimport { FunctionFailure } from \"./sync/function_result.js\";\n\n// This is blue #9 from https://www.radix-ui.com/docs/colors/palette-composition/the-scales\n// It must look good in both light and dark mode.\nconst INFO_COLOR = \"color:rgb(0, 145, 255)\";\n\nexport type UdfType = \"query\" | \"mutation\" | \"action\" | \"any\";\n\nfunction prefix_for_source(source: UdfType) {\n switch (source) {\n case \"query\":\n return \"Q\";\n case \"mutation\":\n return \"M\";\n case \"action\":\n return \"A\";\n case \"any\":\n return \"?\";\n }\n}\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\n/**\n * A logger that can be used to log messages. By default, this is a wrapper\n * around `console`, but can be configured to not log at all or to log somewhere\n * else.\n */\nexport type Logger = {\n logVerbose(...args: any[]): void;\n log(...args: any[]): void;\n warn(...args: any[]): void;\n error(...args: any[]): void;\n};\n\nexport class DefaultLogger implements Logger {\n private _onLogLineFuncs: Record<\n string,\n (level: LogLevel, ...args: any[]) => void\n >;\n private _verbose: boolean;\n\n constructor(options: { verbose: boolean }) {\n this._onLogLineFuncs = {};\n this._verbose = options.verbose;\n }\n\n addLogLineListener(\n func: (level: LogLevel, ...args: any[]) => void,\n ): () => void {\n let id = Math.random().toString(36).substring(2, 15);\n for (let i = 0; i < 10; i++) {\n if (this._onLogLineFuncs[id] === undefined) {\n break;\n }\n id = Math.random().toString(36).substring(2, 15);\n }\n this._onLogLineFuncs[id] = func;\n return () => {\n delete this._onLogLineFuncs[id];\n };\n }\n\n logVerbose(...args: any[]) {\n if (this._verbose) {\n for (const func of Object.values(this._onLogLineFuncs)) {\n func(\"debug\", `${new Date().toISOString()}`, ...args);\n }\n }\n }\n\n log(...args: any[]) {\n for (const func of Object.values(this._onLogLineFuncs)) {\n func(\"info\", ...args);\n }\n }\n\n warn(...args: any[]) {\n for (const func of Object.values(this._onLogLineFuncs)) {\n func(\"warn\", ...args);\n }\n }\n\n error(...args: any[]) {\n for (const func of Object.values(this._onLogLineFuncs)) {\n func(\"error\", ...args);\n }\n }\n}\n\nexport function instantiateDefaultLogger(options: {\n verbose: boolean;\n}): Logger {\n const logger = new DefaultLogger(options);\n logger.addLogLineListener((level, ...args) => {\n switch (level) {\n case \"debug\":\n console.debug(...args);\n break;\n case \"info\":\n console.log(...args);\n break;\n case \"warn\":\n console.warn(...args);\n break;\n case \"error\":\n console.error(...args);\n break;\n default: {\n level satisfies never;\n console.log(...args);\n }\n }\n });\n return logger;\n}\n\nexport function instantiateNoopLogger(options: { verbose: boolean }): Logger {\n return new DefaultLogger(options);\n}\n\nexport function logForFunction(\n logger: Logger,\n type: \"info\" | \"error\",\n source: UdfType,\n udfPath: string,\n message: string | { errorData: Value },\n) {\n const prefix = prefix_for_source(source);\n\n if (typeof message === \"object\") {\n message = `ConvexError ${JSON.stringify(message.errorData, null, 2)}`;\n }\n if (type === \"info\") {\n const match = message.match(/^\\[.*?\\] /);\n if (match === null) {\n logger.error(\n `[CONVEX ${prefix}(${udfPath})] Could not parse console.log`,\n );\n return;\n }\n const level = message.slice(1, match[0].length - 2);\n const args = message.slice(match[0].length);\n\n logger.log(`%c[CONVEX ${prefix}(${udfPath})] [${level}]`, INFO_COLOR, args);\n } else {\n logger.error(`[CONVEX ${prefix}(${udfPath})] ${message}`);\n }\n}\n\nexport function logFatalError(logger: Logger, message: string): Error {\n const errorMessage = `[CONVEX FATAL ERROR] ${message}`;\n logger.error(errorMessage);\n return new Error(errorMessage);\n}\n\nexport function createHybridErrorStacktrace(\n source: UdfType,\n udfPath: string,\n result: FunctionFailure,\n): string {\n const prefix = prefix_for_source(source);\n return `[CONVEX ${prefix}(${udfPath})] ${result.errorMessage}\\n Called by client`;\n}\n\nexport function forwardData(\n result: FunctionFailure,\n error: ConvexError<string>,\n) {\n (error as ConvexError<any>).data = result.errorData;\n return error;\n}\n", "import { convexToJson, Value } from \"../../values/index.js\";\n\nexport function canonicalizeUdfPath(udfPath: string): string {\n const pieces = udfPath.split(\":\");\n let moduleName: string;\n let functionName: string;\n if (pieces.length === 1) {\n moduleName = pieces[0];\n functionName = \"default\";\n } else {\n moduleName = pieces.slice(0, pieces.length - 1).join(\":\");\n functionName = pieces[pieces.length - 1];\n }\n if (moduleName.endsWith(\".js\")) {\n moduleName = moduleName.slice(0, -3);\n }\n return `${moduleName}:${functionName}`;\n}\n\n/**\n * The serialization here is not stable, these strings never make it outside the client.\n */\n\n/**\n * A string representing the name and arguments of a query.\n *\n * This is used by the {@link BaseConvexClient}.\n *\n * @public\n */\nexport type QueryToken = string & { __queryToken: true };\n\n/**\n * A string representing the name and arguments of a paginated query.\n *\n * This is a specialized form of QueryToken used for paginated queries.\n */\nexport type PaginatedQueryToken = QueryToken & { __paginatedQueryToken: true };\n\nexport function serializePathAndArgs(\n udfPath: string,\n args: Record<string, Value>,\n): QueryToken {\n return JSON.stringify({\n udfPath: canonicalizeUdfPath(udfPath),\n args: convexToJson(args),\n }) as QueryToken;\n}\n\nexport function serializePaginatedPathAndArgs(\n udfPath: string,\n args: Record<string, Value>, // args WITHOUT paginationOpts\n options: { initialNumItems: number; id: number },\n): PaginatedQueryToken {\n const { initialNumItems, id } = options;\n const result = JSON.stringify({\n type: \"paginated\",\n udfPath: canonicalizeUdfPath(udfPath),\n args: convexToJson(args),\n options: convexToJson({ initialNumItems, id }),\n }) as PaginatedQueryToken;\n return result;\n}\n\nexport function serializedQueryTokenIsPaginated(\n token: QueryToken | PaginatedQueryToken,\n): token is PaginatedQueryToken {\n return JSON.parse(token).type === \"paginated\";\n}\n", "/**\n * The local state of the client:\n * - which queries are subscribed to\n * - the \"Query Set Version,\" used to produce QuerySetModification messages\n * - the current auth token and \"Identity Version\"\n *\n * Local state does not include:\n * - query results (see RemoteQuerySet)\n * - locally made \"optimistic update\" modifications to query results (see OptimisticQueryResults)\n * - any query results at all\n **/\n\nimport { convexToJson, Value } from \"../../values/index.js\";\nimport {\n AddQuery,\n RemoveQuery,\n QueryId,\n QuerySetModification,\n QuerySetVersion,\n IdentityVersion,\n Authenticate,\n QueryJournal,\n Transition,\n AdminAuthentication,\n UserIdentityAttributes,\n} from \"./protocol.js\";\nimport {\n canonicalizeUdfPath,\n QueryToken,\n serializePathAndArgs,\n} from \"./udf_path_utils.js\";\n\ntype LocalQuery = {\n id: QueryId;\n canonicalizedUdfPath: string;\n args: Record<string, Value>;\n numSubscribers: number;\n journal?: QueryJournal | undefined;\n componentPath?: string | undefined;\n};\n\nexport type AuthState =\n | {\n tokenType: \"User\";\n value: string;\n }\n | {\n tokenType: \"Admin\";\n value: string;\n impersonating?: UserIdentityAttributes | undefined;\n };\n\nexport class LocalSyncState {\n private nextQueryId: QueryId;\n private querySetVersion: QuerySetVersion;\n private readonly querySet: Map<QueryToken, LocalQuery>;\n private readonly queryIdToToken: Map<QueryId, QueryToken>;\n private identityVersion: IdentityVersion;\n private auth: AuthState | undefined;\n private readonly outstandingQueriesOlderThanRestart: Set<QueryId>;\n private outstandingAuthOlderThanRestart: boolean;\n private paused: boolean;\n private pendingQuerySetModifications: Map<QueryId, AddQuery | RemoveQuery>;\n\n constructor() {\n this.nextQueryId = 0;\n this.querySetVersion = 0;\n this.identityVersion = 0;\n this.querySet = new Map();\n this.queryIdToToken = new Map();\n this.outstandingQueriesOlderThanRestart = new Set();\n this.outstandingAuthOlderThanRestart = false;\n this.paused = false;\n this.pendingQuerySetModifications = new Map();\n }\n\n hasSyncedPastLastReconnect(): boolean {\n return (\n this.outstandingQueriesOlderThanRestart.size === 0 &&\n !this.outstandingAuthOlderThanRestart\n );\n }\n\n markAuthCompletion() {\n this.outstandingAuthOlderThanRestart = false;\n }\n\n subscribe(\n udfPath: string,\n args: Record<string, Value>,\n journal?: QueryJournal | undefined,\n componentPath?: string | undefined,\n ): {\n queryToken: QueryToken;\n modification: QuerySetModification | null;\n unsubscribe: () => QuerySetModification | null;\n } {\n const canonicalizedUdfPath = canonicalizeUdfPath(udfPath);\n const queryToken = serializePathAndArgs(canonicalizedUdfPath, args);\n\n const existingEntry = this.querySet.get(queryToken);\n\n if (existingEntry !== undefined) {\n existingEntry.numSubscribers += 1;\n return {\n queryToken,\n modification: null,\n unsubscribe: () => this.removeSubscriber(queryToken),\n };\n } else {\n const queryId = this.nextQueryId++;\n const query: LocalQuery = {\n id: queryId,\n canonicalizedUdfPath,\n args,\n numSubscribers: 1,\n journal,\n componentPath,\n };\n this.querySet.set(queryToken, query);\n this.queryIdToToken.set(queryId, queryToken);\n\n const baseVersion = this.querySetVersion;\n const newVersion = this.querySetVersion + 1;\n\n const add: AddQuery = {\n type: \"Add\",\n queryId,\n udfPath: canonicalizedUdfPath,\n args: [convexToJson(args)],\n journal,\n componentPath,\n };\n\n if (this.paused) {\n this.pendingQuerySetModifications.set(queryId, add);\n } else {\n this.querySetVersion = newVersion;\n }\n\n const modification: QuerySetModification = {\n type: \"ModifyQuerySet\",\n baseVersion,\n newVersion,\n modifications: [add],\n };\n return {\n queryToken,\n modification,\n unsubscribe: () => this.removeSubscriber(queryToken),\n };\n }\n }\n\n transition(transition: Transition) {\n for (const modification of transition.modifications) {\n switch (modification.type) {\n case \"QueryUpdated\":\n case \"QueryFailed\": {\n this.outstandingQueriesOlderThanRestart.delete(modification.queryId);\n const journal = modification.journal;\n if (journal !== undefined) {\n const queryToken = this.queryIdToToken.get(modification.queryId);\n // We may have already unsubscribed to this query by the time the server\n // sends us the journal. If so, just ignore it.\n if (queryToken !== undefined) {\n this.querySet.get(queryToken)!.journal = journal;\n }\n }\n\n break;\n }\n case \"QueryRemoved\": {\n this.outstandingQueriesOlderThanRestart.delete(modification.queryId);\n break;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n modification satisfies never;\n throw new Error(`Invalid modification ${(modification as any).type}`);\n }\n }\n }\n }\n\n queryId(udfPath: string, args: Record<string, Value>): QueryId | null {\n const canonicalizedUdfPath = canonicalizeUdfPath(udfPath);\n const queryToken = serializePathAndArgs(canonicalizedUdfPath, args);\n const existingEntry = this.querySet.get(queryToken);\n if (existingEntry !== undefined) {\n return existingEntry.id;\n }\n return null;\n }\n\n isCurrentOrNewerAuthVersion(version: IdentityVersion): boolean {\n return version >= this.identityVersion;\n }\n\n getAuth(): AuthState | undefined {\n return this.auth;\n }\n\n setAuth(value: string): Authenticate {\n this.auth = {\n tokenType: \"User\" as const,\n value: value,\n };\n const baseVersion = this.identityVersion;\n if (!this.paused) {\n this.identityVersion = baseVersion + 1;\n }\n return {\n type: \"Authenticate\",\n baseVersion: baseVersion,\n ...this.auth,\n };\n }\n\n setAdminAuth(\n value: string,\n actingAs?: UserIdentityAttributes,\n ): AdminAuthentication {\n const auth: typeof this.auth & {\n tokenType: \"Admin\";\n } = {\n tokenType: \"Admin\",\n value,\n impersonating: actingAs,\n };\n this.auth = auth;\n const baseVersion = this.identityVersion;\n if (!this.paused) {\n this.identityVersion = baseVersion + 1;\n }\n return {\n type: \"Authenticate\",\n baseVersion: baseVersion,\n ...auth,\n };\n }\n\n clearAuth(): Authenticate {\n this.auth = undefined;\n this.markAuthCompletion();\n const baseVersion = this.identityVersion;\n if (!this.paused) {\n this.identityVersion = baseVersion + 1;\n }\n return {\n type: \"Authenticate\",\n tokenType: \"None\",\n baseVersion: baseVersion,\n };\n }\n\n hasAuth(): boolean {\n return !!this.auth;\n }\n\n isNewAuth(value: string): boolean {\n return this.auth?.value !== value;\n }\n\n queryPath(queryId: QueryId): string | null {\n const pathAndArgs = this.queryIdToToken.get(queryId);\n if (pathAndArgs) {\n return this.querySet.get(pathAndArgs)!.canonicalizedUdfPath;\n }\n return null;\n }\n\n queryArgs(queryId: QueryId): Record<string, Value> | null {\n const pathAndArgs = this.queryIdToToken.get(queryId);\n if (pathAndArgs) {\n return this.querySet.get(pathAndArgs)!.args;\n }\n return null;\n }\n\n queryToken(queryId: QueryId): QueryToken | null {\n return this.queryIdToToken.get(queryId) ?? null;\n }\n\n queryJournal(queryToken: QueryToken): QueryJournal | undefined {\n return this.querySet.get(queryToken)?.journal;\n }\n\n restart(): [QuerySetModification, (Authenticate | undefined)?] {\n // Restart works whether we are paused or unpaused.\n // The `this.pendingQuerySetModifications` is not used\n // when restarting as the AddQuery and RemoveQuery are computed\n // from scratch, based on the old remote query results, here.\n this.unpause();\n\n this.outstandingQueriesOlderThanRestart.clear();\n const modifications = [];\n for (const localQuery of this.querySet.values()) {\n const add: AddQuery = {\n type: \"Add\",\n queryId: localQuery.id,\n udfPath: localQuery.canonicalizedUdfPath,\n args: [convexToJson(localQuery.args)],\n journal: localQuery.journal,\n componentPath: localQuery.componentPath,\n };\n modifications.push(add);\n\n // Track all re-sent queries as outstanding so the backoff retry\n // counter doesn't reset until the server has re-confirmed results\n // for every active query.\n this.outstandingQueriesOlderThanRestart.add(localQuery.id);\n }\n this.querySetVersion = 1;\n const querySet: QuerySetModification = {\n type: \"ModifyQuerySet\",\n baseVersion: 0,\n newVersion: 1,\n modifications,\n };\n // If there's no auth, no need to send an update as the server will also start with an unknown identity.\n if (!this.auth) {\n this.identityVersion = 0;\n return [querySet, undefined];\n }\n this.outstandingAuthOlderThanRestart = true;\n const authenticate: Authenticate = {\n type: \"Authenticate\",\n baseVersion: 0,\n ...this.auth,\n };\n this.identityVersion = 1;\n return [querySet, authenticate];\n }\n\n pause() {\n this.paused = true;\n }\n\n resume(): [QuerySetModification | undefined, Authenticate | undefined] {\n const querySet: QuerySetModification | undefined =\n this.pendingQuerySetModifications.size > 0\n ? {\n type: \"ModifyQuerySet\",\n baseVersion: this.querySetVersion,\n newVersion: ++this.querySetVersion,\n modifications: Array.from(\n this.pendingQuerySetModifications.values(),\n ),\n }\n : undefined;\n const authenticate: Authenticate | undefined =\n this.auth !== undefined\n ? {\n type: \"Authenticate\",\n baseVersion: this.identityVersion++,\n ...this.auth,\n }\n : undefined;\n\n this.unpause();\n\n return [querySet, authenticate];\n }\n\n private unpause() {\n this.paused = false;\n this.pendingQuerySetModifications.clear();\n }\n\n private removeSubscriber(\n queryToken: QueryToken,\n ): QuerySetModification | null {\n const localQuery = this.querySet.get(queryToken)!;\n\n if (localQuery.numSubscribers > 1) {\n localQuery.numSubscribers -= 1;\n return null;\n } else {\n this.querySet.delete(queryToken);\n this.queryIdToToken.delete(localQuery.id);\n this.outstandingQueriesOlderThanRestart.delete(localQuery.id);\n const baseVersion = this.querySetVersion;\n const newVersion = this.querySetVersion + 1;\n const remove: RemoveQuery = {\n type: \"Remove\",\n queryId: localQuery.id,\n };\n if (this.paused) {\n if (this.pendingQuerySetModifications.has(localQuery.id)) {\n this.pendingQuerySetModifications.delete(localQuery.id);\n } else {\n this.pendingQuerySetModifications.set(localQuery.id, remove);\n }\n } else {\n this.querySetVersion = newVersion;\n }\n return {\n type: \"ModifyQuerySet\",\n baseVersion,\n newVersion,\n modifications: [remove],\n };\n }\n }\n}\n", "import { jsonToConvex } from \"../../values/index.js\";\nimport { logForFunction, Logger } from \"../logging.js\";\nimport { Long } from \"../../vendor/long.js\";\nimport { FunctionResult } from \"./function_result.js\";\nimport {\n ActionRequest,\n ActionResponse,\n ClientMessage,\n MutationRequest,\n MutationResponse,\n RequestId,\n} from \"./protocol.js\";\n\ntype RequestStatus =\n | {\n status: \"Requested\" | \"NotSent\";\n onResult: (result: FunctionResult) => void;\n requestedAt: Date;\n }\n | {\n status: \"Completed\";\n result: FunctionResult;\n onResolve: () => void;\n ts: Long;\n };\n\nexport class RequestManager {\n private inflightRequests: Map<\n RequestId,\n {\n message: MutationRequest | ActionRequest;\n status: RequestStatus;\n }\n >;\n private requestsOlderThanRestart: Set<RequestId>;\n private inflightMutationsCount: number = 0;\n private inflightActionsCount: number = 0;\n constructor(\n private readonly logger: Logger,\n private readonly markConnectionStateDirty: () => void,\n ) {\n this.inflightRequests = new Map();\n this.requestsOlderThanRestart = new Set();\n }\n\n request(\n message: MutationRequest | ActionRequest,\n sent: boolean,\n ): Promise<FunctionResult> {\n const result = new Promise<FunctionResult>((resolve) => {\n const status = sent ? \"Requested\" : \"NotSent\";\n this.inflightRequests.set(message.requestId, {\n message,\n status: { status, requestedAt: new Date(), onResult: resolve },\n });\n\n if (message.type === \"Mutation\") {\n this.inflightMutationsCount++;\n } else if (message.type === \"Action\") {\n this.inflightActionsCount++;\n }\n });\n\n this.markConnectionStateDirty();\n return result;\n }\n\n /**\n * Update the state after receiving a response.\n *\n * @returns A RequestId if the request is complete and its optimistic update\n * can be dropped, null otherwise.\n */\n onResponse(\n response: MutationResponse | ActionResponse,\n ): { requestId: RequestId; result: FunctionResult } | null {\n const requestInfo = this.inflightRequests.get(response.requestId);\n if (requestInfo === undefined) {\n // Annoyingly we can occasionally get responses to mutations that we're no\n // longer tracking. One flow where this happens is:\n // 1. Client sends mutation 1\n // 2. Client gets response for mutation 1. The sever says that it was committed at ts=10.\n // 3. Client is disconnected\n // 4. Client reconnects and re-issues queries and this mutation.\n // 5. Server sends transition message to ts=20\n // 6. Client drops mutation because it's already been observed.\n // 7. Client receives a second response for mutation 1 but doesn't know about it anymore.\n\n // The right fix for this is probably to add a reconciliation phase on\n // reconnection where we receive responses to all the mutations before\n // the transition message so this flow could never happen (CX-1513).\n\n // For now though, we can just ignore this message.\n return null;\n }\n\n // Because `.restart()` re-requests completed requests, we may get some\n // responses for requests that are already in the \"Completed\" state.\n // We can safely ignore those because we've already notified the UI about\n // their results.\n if (requestInfo.status.status === \"Completed\") {\n return null;\n }\n\n const udfType =\n requestInfo.message.type === \"Mutation\" ? \"mutation\" : \"action\";\n const udfPath = requestInfo.message.udfPath;\n\n for (const line of response.logLines) {\n logForFunction(this.logger, \"info\", udfType, udfPath, line);\n }\n\n const status = requestInfo.status;\n let result: FunctionResult;\n let onResolve;\n if (response.success) {\n result = {\n success: true,\n logLines: response.logLines,\n value: jsonToConvex(response.result),\n };\n onResolve = () => status.onResult(result);\n } else {\n const errorMessage = response.result as string;\n const { errorData } = response;\n logForFunction(this.logger, \"error\", udfType, udfPath, errorMessage);\n result = {\n success: false,\n errorMessage,\n errorData:\n errorData !== undefined ? jsonToConvex(errorData) : undefined,\n logLines: response.logLines,\n };\n onResolve = () => status.onResult(result);\n }\n\n // We can resolve Mutation failures immediately since they don't have any\n // side effects. Actions are intentionally decoupled from\n // queries/mutations here on the sync protocol since they have different\n // guarantees.\n if (response.type === \"ActionResponse\" || !response.success) {\n onResolve();\n this.inflightRequests.delete(response.requestId);\n this.requestsOlderThanRestart.delete(response.requestId);\n\n if (requestInfo.message.type === \"Action\") {\n this.inflightActionsCount--;\n } else if (requestInfo.message.type === \"Mutation\") {\n this.inflightMutationsCount--;\n }\n\n this.markConnectionStateDirty();\n return { requestId: response.requestId, result };\n }\n\n // We have to wait to resolve the request promise until after we transition\n // past this timestamp so clients can read their own writes.\n requestInfo.status = {\n status: \"Completed\",\n result,\n ts: response.ts,\n onResolve,\n };\n\n return null;\n }\n\n // Remove and returns completed requests.\n removeCompleted(ts: Long): Map<RequestId, FunctionResult> {\n const completeRequests: Map<RequestId, FunctionResult> = new Map();\n for (const [requestId, requestInfo] of this.inflightRequests.entries()) {\n const status = requestInfo.status;\n if (status.status === \"Completed\" && status.ts.lessThanOrEqual(ts)) {\n status.onResolve();\n completeRequests.set(requestId, status.result);\n\n if (requestInfo.message.type === \"Mutation\") {\n this.inflightMutationsCount--;\n } else if (requestInfo.message.type === \"Action\") {\n this.inflightActionsCount--;\n }\n\n this.inflightRequests.delete(requestId);\n this.requestsOlderThanRestart.delete(requestId);\n }\n }\n if (completeRequests.size > 0) {\n this.markConnectionStateDirty();\n }\n return completeRequests;\n }\n\n restart(): ClientMessage[] {\n // When we reconnect to the backend, re-request all requests that are safe\n // to be resend.\n\n this.requestsOlderThanRestart = new Set(this.inflightRequests.keys());\n const allMessages = [];\n for (const [requestId, value] of this.inflightRequests) {\n if (value.status.status === \"NotSent\") {\n value.status.status = \"Requested\";\n allMessages.push(value.message);\n continue;\n }\n\n if (value.message.type === \"Mutation\") {\n // This includes ones that have already been completed because we still\n // want to tell the backend to transition the client past the completed\n // timestamp. This is safe since mutations are idempotent.\n allMessages.push(value.message);\n } else if (value.message.type === \"Action\") {\n // Unlike mutations, actions are not idempotent. When we reconnect to the\n // backend, we don't know if it is safe to resend in-flight actions, so we\n // cancel them and consider them failed.\n this.inflightRequests.delete(requestId);\n this.requestsOlderThanRestart.delete(requestId);\n this.inflightActionsCount--;\n if (value.status.status === \"Completed\") {\n throw new Error(\"Action should never be in 'Completed' state\");\n }\n value.status.onResult({\n success: false,\n errorMessage: \"Connection lost while action was in flight\",\n logLines: [],\n });\n }\n }\n this.markConnectionStateDirty();\n return allMessages;\n }\n\n resume(): ClientMessage[] {\n const allMessages = [];\n for (const [, value] of this.inflightRequests) {\n if (value.status.status === \"NotSent\") {\n value.status.status = \"Requested\";\n allMessages.push(value.message);\n continue;\n }\n }\n return allMessages;\n }\n\n /**\n * @returns true if there are any requests that have been requested but have\n * not be completed yet.\n */\n hasIncompleteRequests(): boolean {\n for (const requestInfo of this.inflightRequests.values()) {\n if (requestInfo.status.status === \"Requested\") {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @returns true if there are any inflight requests, including ones that have\n * completed on the server, but have not been applied.\n */\n hasInflightRequests(): boolean {\n return this.inflightRequests.size > 0;\n }\n\n /**\n * @returns true if there are any inflight requests, that have been hanging around\n * since prior to the most recent restart.\n */\n hasSyncedPastLastReconnect(): boolean {\n return this.requestsOlderThanRestart.size === 0;\n }\n\n timeOfOldestInflightRequest(): Date | null {\n if (this.inflightRequests.size === 0) {\n return null;\n }\n let oldestInflightRequest = Date.now();\n for (const request of this.inflightRequests.values()) {\n if (request.status.status !== \"Completed\") {\n if (request.status.requestedAt.getTime() < oldestInflightRequest) {\n oldestInflightRequest = request.status.requestedAt.getTime();\n }\n }\n }\n return new Date(oldestInflightRequest);\n }\n\n /**\n * @returns The number of mutations currently in flight.\n */\n inflightMutations(): number {\n return this.inflightMutationsCount;\n }\n\n /**\n * @returns The number of actions currently in flight.\n */\n inflightActions(): number {\n return this.inflightActionsCount;\n }\n}\n", "/**\n * A symbol for accessing the name of a {@link FunctionReference} at runtime.\n */\nexport const functionName = Symbol.for(\"functionName\");\n", "import { functionName } from \"../functionName.js\";\n\nexport const toReferencePath = Symbol.for(\"toReferencePath\");\n\n// Multiple instances of the same Symbol.for() are equal at runtime but not\n// at type-time, so `[toReferencePath]` properties aren't used in types.\n// Use this function to set the property invisibly.\nexport function setReferencePath<T>(obj: T, value: string) {\n (obj as any)[toReferencePath] = value;\n}\n\nexport function extractReferencePath(reference: any): string | null {\n return reference[toReferencePath] ?? null;\n}\n\nexport function isFunctionHandle(s: string): boolean {\n return s.startsWith(\"function://\");\n}\n\nexport function getFunctionAddress(functionReference: any) {\n // The `run*` syscalls expect either a UDF path at \"name\" or a serialized\n // reference at \"reference\". Dispatch on `functionReference` to coerce\n // it to one or the other.\n let functionAddress;\n\n // Legacy path for passing in UDF paths directly as function references.\n if (typeof functionReference === \"string\") {\n if (isFunctionHandle(functionReference)) {\n functionAddress = { functionHandle: functionReference };\n } else {\n functionAddress = { name: functionReference };\n }\n }\n // Path for passing in a `FunctionReference`, either from `api` or directly\n // created from a UDF path with `makeFunctionReference`.\n else if (functionReference[functionName]) {\n functionAddress = { name: functionReference[functionName] };\n }\n // Reference to a component's function derived from `app` or `component`.\n else {\n const referencePath = extractReferencePath(functionReference);\n if (!referencePath) {\n throw new Error(`${functionReference} is not a functionReference`);\n }\n functionAddress = { reference: referencePath };\n }\n return functionAddress;\n}\n", "import {\n EmptyObject,\n DefaultFunctionArgs,\n FunctionVisibility,\n RegisteredAction,\n RegisteredMutation,\n RegisteredQuery,\n} from \"./registration.js\";\nimport { Expand, UnionToIntersection } from \"../type_utils.js\";\nimport { PaginationOptions, PaginationResult } from \"./pagination.js\";\nimport { functionName } from \"./functionName.js\";\nimport { getFunctionAddress } from \"./components/paths.js\";\n\n/**\n * The type of a Convex function.\n *\n * @public\n */\nexport type FunctionType = \"query\" | \"mutation\" | \"action\";\n\n/**\n * A reference to a registered Convex function.\n *\n * You can create a {@link FunctionReference} using the generated `api` utility:\n * ```js\n * import { api } from \"../convex/_generated/api\";\n *\n * const reference = api.myModule.myFunction;\n * ```\n *\n * If you aren't using code generation, you can create references using\n * {@link anyApi}:\n * ```js\n * import { anyApi } from \"convex/server\";\n *\n * const reference = anyApi.myModule.myFunction;\n * ```\n *\n * Function references can be used to invoke functions from the client. For\n * example, in React you can pass references to the {@link react.useQuery} hook:\n * ```js\n * const result = useQuery(api.myModule.myFunction);\n * ```\n *\n * @typeParam Type - The type of the function (\"query\", \"mutation\", or \"action\").\n * @typeParam Visibility - The visibility of the function (\"public\" or \"internal\").\n * @typeParam Args - The arguments to this function. This is an object mapping\n * argument names to their types.\n * @typeParam ReturnType - The return type of this function.\n * @public\n */\nexport type FunctionReference<\n Type extends FunctionType,\n Visibility extends FunctionVisibility = \"public\",\n Args extends DefaultFunctionArgs = any,\n ReturnType = any,\n ComponentPath = string | undefined,\n> = {\n _type: Type;\n _visibility: Visibility;\n _args: Args;\n _returnType: ReturnType;\n _componentPath: ComponentPath;\n};\n\n/**\n * Get the name of a function from a {@link FunctionReference}.\n *\n * The name is a string like \"myDir/myModule:myFunction\". If the exported name\n * of the function is `\"default\"`, the function name is omitted\n * (e.g. \"myDir/myModule\").\n *\n * @param functionReference - A {@link FunctionReference} to get the name of.\n * @returns A string of the function's name.\n *\n * @public\n */\nexport function getFunctionName(\n functionReference: AnyFunctionReference,\n): string {\n const address = getFunctionAddress(functionReference);\n\n if (address.name === undefined) {\n if (address.functionHandle !== undefined) {\n throw new Error(\n `Expected function reference like \"api.file.func\" or \"internal.file.func\", but received function handle ${address.functionHandle}`,\n );\n } else if (address.reference !== undefined) {\n throw new Error(\n `Expected function reference in the current component like \"api.file.func\" or \"internal.file.func\", but received reference ${address.reference}`,\n );\n }\n throw new Error(\n `Expected function reference like \"api.file.func\" or \"internal.file.func\", but received ${JSON.stringify(address)}`,\n );\n }\n // Both a legacy thing and also a convenience for interactive use:\n // the types won't check but a string is always allowed at runtime.\n if (typeof functionReference === \"string\") return functionReference;\n\n // Two different runtime values for FunctionReference implement this\n // interface: api objects returned from `createApi()` and standalone\n // function reference objects returned from makeFunctionReference.\n const name = (functionReference as any)[functionName];\n if (!name) {\n throw new Error(`${functionReference as any} is not a functionReference`);\n }\n return name;\n}\n\n/**\n * FunctionReferences generally come from generated code, but in custom clients\n * it may be useful to be able to build one manually.\n *\n * Real function references are empty objects at runtime, but the same interface\n * can be implemented with an object for tests and clients which don't use\n * code generation.\n *\n * @param name - The identifier of the function. E.g. `path/to/file:functionName`\n * @public\n */\nexport function makeFunctionReference<\n type extends FunctionType,\n args extends DefaultFunctionArgs = any,\n ret = any,\n>(name: string): FunctionReference<type, \"public\", args, ret> {\n return { [functionName]: name } as unknown as FunctionReference<\n type,\n \"public\",\n args,\n ret\n >;\n}\n\n/**\n * Create a runtime API object that implements {@link AnyApi}.\n *\n * This allows accessing any path regardless of what directories, modules,\n * or functions are defined.\n *\n * @param pathParts - The path to the current node in the API.\n * @returns An {@link AnyApi}\n * @public\n */\nfunction createApi(pathParts: string[] = []): AnyApi {\n const handler: ProxyHandler<object> = {\n get(_, prop: string | symbol) {\n if (typeof prop === \"string\") {\n const newParts = [...pathParts, prop];\n return createApi(newParts);\n } else if (prop === functionName) {\n if (pathParts.length < 2) {\n const found = [\"api\", ...pathParts].join(\".\");\n throw new Error(\n `API path is expected to be of the form \\`api.moduleName.functionName\\`. Found: \\`${found}\\``,\n );\n }\n const path = pathParts.slice(0, -1).join(\"/\");\n const exportName = pathParts[pathParts.length - 1];\n if (exportName === \"default\") {\n return path;\n } else {\n return path + \":\" + exportName;\n }\n } else if (prop === Symbol.toStringTag) {\n return \"FunctionReference\";\n } else {\n return undefined;\n }\n },\n };\n\n return new Proxy({}, handler);\n}\n\n/**\n * Given an export from a module, convert it to a {@link FunctionReference}\n * if it is a Convex function.\n */\nexport type FunctionReferenceFromExport<Export> =\n Export extends RegisteredQuery<\n infer Visibility,\n infer Args,\n infer ReturnValue\n >\n ? FunctionReference<\n \"query\",\n Visibility,\n Args,\n ConvertReturnType<ReturnValue>\n >\n : Export extends RegisteredMutation<\n infer Visibility,\n infer Args,\n infer ReturnValue\n >\n ? FunctionReference<\n \"mutation\",\n Visibility,\n Args,\n ConvertReturnType<ReturnValue>\n >\n : Export extends RegisteredAction<\n infer Visibility,\n infer Args,\n infer ReturnValue\n >\n ? FunctionReference<\n \"action\",\n Visibility,\n Args,\n ConvertReturnType<ReturnValue>\n >\n : never;\n\n/**\n * Given a module, convert all the Convex functions into\n * {@link FunctionReference}s and remove the other exports.\n *\n * BE CAREFUL WHEN EDITING THIS!\n *\n * This is written carefully to preserve jumping to function definitions using\n * cmd+click. If you edit it, please test that cmd+click still works.\n */\ntype FunctionReferencesInModule<Module extends Record<string, any>> = {\n -readonly [ExportName in keyof Module as Module[ExportName][\"isConvexFunction\"] extends true\n ? ExportName\n : never]: FunctionReferenceFromExport<Module[ExportName]>;\n};\n\n/**\n * Given a path to a module and it's type, generate an API type for this module.\n *\n * This is a nested object according to the module's path.\n */\ntype ApiForModule<\n ModulePath extends string,\n Module extends object,\n> = ModulePath extends `${infer First}/${infer Second}`\n ? {\n [_ in First]: ApiForModule<Second, Module>;\n }\n : { [_ in ModulePath]: FunctionReferencesInModule<Module> };\n\n/**\n * Given the types of all modules in the `convex/` directory, construct the type\n * of `api`.\n *\n * `api` is a utility for constructing {@link FunctionReference}s.\n *\n * @typeParam AllModules - A type mapping module paths (like `\"dir/myModule\"`) to\n * the types of the modules.\n * @public\n */\nexport type ApiFromModules<AllModules extends Record<string, object>> =\n FilterApi<\n ApiFromModulesAllowEmptyNodes<AllModules>,\n FunctionReference<any, any, any, any>\n >;\n\ntype ApiFromModulesAllowEmptyNodes<AllModules extends Record<string, object>> =\n ExpandModulesAndDirs<\n UnionToIntersection<\n {\n [ModulePath in keyof AllModules]: ApiForModule<\n ModulePath & string,\n AllModules[ModulePath]\n >;\n }[keyof AllModules]\n >\n >;\n\ntype FilterKeysInApi<key, API, Predicate> = API extends Predicate\n ? key\n : API extends FunctionReference<any, any, any, any>\n ? never\n : FilterApi<API, Predicate> extends Record<string, never>\n ? never\n : key;\n\n/**\n * @public\n *\n * Filter a Convex deployment api object for functions which meet criteria,\n * for example all public queries.\n */\nexport type FilterApi<API, Predicate> = Expand<{\n [mod in keyof API as FilterKeysInApi<\n mod,\n API[mod],\n Predicate\n >]: API[mod] extends Predicate ? API[mod] : FilterApi<API[mod], Predicate>;\n}>;\n\n/**\n * Given an api of type API and a FunctionReference subtype, return an api object\n * containing only the function references that match.\n *\n * ```ts\n * const q = filterApi<typeof api, FunctionReference<\"query\">>(api)\n * ```\n *\n * @public\n */\nexport function filterApi<API, Predicate>(api: API): FilterApi<API, Predicate> {\n return api as any;\n}\n\n// These just* API filter helpers require no type parameters so are useable from JavaScript.\n/** @public */\nexport function justInternal<API>(\n api: API,\n): FilterApi<API, FunctionReference<any, \"internal\", any, any>> {\n return api as any;\n}\n\n/** @public */\nexport function justPublic<API>(\n api: API,\n): FilterApi<API, FunctionReference<any, \"public\", any, any>> {\n return api as any;\n}\n\n/** @public */\nexport function justQueries<API>(\n api: API,\n): FilterApi<API, FunctionReference<\"query\", any, any, any>> {\n return api as any;\n}\n\n/** @public */\nexport function justMutations<API>(\n api: API,\n): FilterApi<API, FunctionReference<\"mutation\", any, any, any>> {\n return api as any;\n}\n\n/** @public */\nexport function justActions<API>(\n api: API,\n): FilterApi<API, FunctionReference<\"action\", any, any, any>> {\n return api as any;\n}\n\n/** @public */\nexport function justPaginatedQueries<API>(\n api: API,\n): FilterApi<\n API,\n FunctionReference<\n \"query\",\n any,\n { paginationOpts: PaginationOptions },\n PaginationResult<any>\n >\n> {\n return api as any;\n}\n\n/** @public */\nexport function justSchedulable<API>(\n api: API,\n): FilterApi<API, FunctionReference<\"mutation\" | \"action\", any, any, any>> {\n return api as any;\n}\n\n/**\n * Like {@link Expand}, this simplifies how TypeScript displays object types.\n * The differences are:\n * 1. This version is recursive.\n * 2. This stops recursing when it hits a {@link FunctionReference}.\n */\ntype ExpandModulesAndDirs<ObjectType> = ObjectType extends AnyFunctionReference\n ? ObjectType\n : {\n [Key in keyof ObjectType]: ExpandModulesAndDirs<ObjectType[Key]>;\n };\n\n/**\n * A {@link FunctionReference} of any type and any visibility with any\n * arguments and any return type.\n *\n * @public\n */\nexport type AnyFunctionReference = FunctionReference<any, any>;\n\ntype AnyModuleDirOrFunc = {\n [key: string]: AnyModuleDirOrFunc;\n} & AnyFunctionReference;\n\n/**\n * The type that Convex api objects extend. If you were writing an api from\n * scratch it should extend this type.\n *\n * @public\n */\nexport type AnyApi = Record<string, Record<string, AnyModuleDirOrFunc>>;\n\n/**\n * Recursive partial API, useful for defining a subset of an API when mocking\n * or building custom api objects.\n *\n * @public\n */\nexport type PartialApi<API> = {\n [mod in keyof API]?: API[mod] extends FunctionReference<any, any, any, any>\n ? API[mod]\n : PartialApi<API[mod]>;\n};\n\n/**\n * A utility for constructing {@link FunctionReference}s in projects that\n * are not using code generation.\n *\n * You can create a reference to a function like:\n * ```js\n * const reference = anyApi.myModule.myFunction;\n * ```\n *\n * This supports accessing any path regardless of what directories and modules\n * are in your project. All function references are typed as\n * {@link AnyFunctionReference}.\n *\n *\n * If you're using code generation, use `api` from `convex/_generated/api`\n * instead. It will be more type-safe and produce better auto-complete\n * in your editor.\n *\n * @public\n */\nexport const anyApi: AnyApi = createApi() as any;\n\n/**\n * Given a {@link FunctionReference}, get the return type of the function.\n *\n * This is represented as an object mapping argument names to values.\n * @public\n */\nexport type FunctionArgs<FuncRef extends AnyFunctionReference> =\n FuncRef[\"_args\"];\n\n/**\n * A tuple type of the (maybe optional) arguments to `FuncRef`.\n *\n * This type is used to make methods involving arguments type safe while allowing\n * skipping the arguments for functions that don't require arguments.\n *\n * @public\n */\nexport type OptionalRestArgs<FuncRef extends AnyFunctionReference> =\n FuncRef[\"_args\"] extends EmptyObject\n ? [args?: EmptyObject]\n : [args: FuncRef[\"_args\"]];\n\n/**\n * A tuple type of the (maybe optional) arguments to `FuncRef`, followed by an options\n * object of type `Options`.\n *\n * This type is used to make methods like `useQuery` type-safe while allowing\n * 1. Skipping arguments for functions that don't require arguments.\n * 2. Skipping the options object.\n * @public\n */\nexport type ArgsAndOptions<\n FuncRef extends AnyFunctionReference,\n Options,\n> = FuncRef[\"_args\"] extends EmptyObject\n ? [args?: EmptyObject, options?: Options]\n : [args: FuncRef[\"_args\"], options?: Options];\n\n/**\n * Given a {@link FunctionReference}, get the return type of the function.\n *\n * @public\n */\nexport type FunctionReturnType<FuncRef extends AnyFunctionReference> =\n FuncRef[\"_returnType\"];\n\ntype UndefinedToNull<T> = T extends void ? null : T;\n\ntype NullToUndefinedOrNull<T> = T extends null ? T | undefined | void : T;\n\n/**\n * Convert the return type of a function to it's client-facing format.\n *\n * This means:\n * - Converting `undefined` and `void` to `null`\n * - Removing all `Promise` wrappers\n */\nexport type ConvertReturnType<T> = UndefinedToNull<Awaited<T>>;\n\nexport type ValidatorTypeToReturnType<T> =\n | Promise<NullToUndefinedOrNull<T>>\n | NullToUndefinedOrNull<T>;\n", "import {\n FunctionArgs,\n FunctionReference,\n FunctionReturnType,\n OptionalRestArgs,\n getFunctionName,\n} from \"../../server/api.js\";\nimport { parseArgs } from \"../../common/index.js\";\nimport { Value } from \"../../values/index.js\";\nimport { createHybridErrorStacktrace, forwardData } from \"../logging.js\";\nimport { FunctionResult } from \"./function_result.js\";\nimport { OptimisticLocalStore } from \"./optimistic_updates.js\";\nimport { RequestId } from \"./protocol.js\";\nimport {\n canonicalizeUdfPath,\n QueryToken,\n serializePathAndArgs,\n} from \"./udf_path_utils.js\";\nimport { ConvexError } from \"../../values/errors.js\";\n\n/**\n * An optimistic update function that has been curried over its arguments.\n */\ntype WrappedOptimisticUpdate = (locaQueryStore: OptimisticLocalStore) => void;\n\n/**\n * The implementation of `OptimisticLocalStore`.\n *\n * This class provides the interface for optimistic updates to modify query results.\n */\nclass OptimisticLocalStoreImpl implements OptimisticLocalStore {\n // A references of the query results in OptimisticQueryResults\n private readonly queryResults: QueryResultsMap;\n\n // All of the queries modified by this class\n readonly modifiedQueries: QueryToken[];\n\n constructor(queryResults: QueryResultsMap) {\n this.queryResults = queryResults;\n this.modifiedQueries = [];\n }\n\n getQuery<Query extends FunctionReference<\"query\">>(\n query: Query,\n ...args: OptionalRestArgs<Query>\n ): undefined | FunctionReturnType<Query> {\n const queryArgs = parseArgs(args[0]);\n const name = getFunctionName(query);\n const queryResult = this.queryResults.get(\n serializePathAndArgs(name, queryArgs),\n );\n if (queryResult === undefined) {\n return undefined;\n }\n return OptimisticLocalStoreImpl.queryValue(queryResult.result);\n }\n\n getAllQueries<Query extends FunctionReference<\"query\">>(\n query: Query,\n ): {\n args: FunctionArgs<Query>;\n value: undefined | FunctionReturnType<Query>;\n }[] {\n const queriesWithName: {\n args: FunctionArgs<Query>;\n value: undefined | FunctionReturnType<Query>;\n }[] = [];\n const name = getFunctionName(query);\n for (const queryResult of this.queryResults.values()) {\n if (queryResult.udfPath === canonicalizeUdfPath(name)) {\n queriesWithName.push({\n args: queryResult.args as FunctionArgs<Query>,\n value: OptimisticLocalStoreImpl.queryValue(queryResult.result),\n });\n }\n }\n return queriesWithName;\n }\n\n setQuery<QueryReference extends FunctionReference<\"query\">>(\n queryReference: QueryReference,\n args: FunctionArgs<QueryReference>,\n value: undefined | FunctionReturnType<QueryReference>,\n ): void {\n const queryArgs = parseArgs(args);\n const name = getFunctionName(queryReference);\n const queryToken = serializePathAndArgs(name, queryArgs);\n\n let result: FunctionResult | undefined;\n if (value === undefined) {\n result = undefined;\n } else {\n result = {\n success: true,\n value,\n // It's an optimistic update, so there are no function logs to show.\n logLines: [],\n };\n }\n const query: Query = {\n udfPath: name,\n args: queryArgs,\n result,\n };\n this.queryResults.set(queryToken, query);\n this.modifiedQueries.push(queryToken);\n }\n\n private static queryValue(\n result: FunctionResult | undefined,\n ): Value | undefined {\n if (result === undefined) {\n return undefined;\n } else if (result.success) {\n return result.value;\n } else {\n // If the query is an error state, just return `undefined` as though\n // it's loading. Optimistic updates should already handle `undefined` well\n // and there isn't a need to break the whole update because it tried\n // to load a single query that errored.\n return undefined;\n }\n }\n}\n\ntype OptimisticUpdateAndId = {\n update: WrappedOptimisticUpdate;\n mutationId: RequestId;\n};\n\ntype Query = {\n // undefined means the query was set to be loading (undefined) in an optimistic update.\n // Note that we can also have queries not present in the QueryResultMap\n // at all because they are still loading from the server and have no optimistic update\n // setting an optimistic value in advance.\n result: FunctionResult | undefined;\n udfPath: string;\n args: Record<string, Value>;\n};\nexport type QueryResultsMap = Map<QueryToken, Query>;\n\ntype ChangedQueries = QueryToken[];\n\n/**\n * A view of all of our query results with optimistic updates applied on top.\n */\nexport class OptimisticQueryResults {\n private queryResults: QueryResultsMap;\n private optimisticUpdates: OptimisticUpdateAndId[];\n\n constructor() {\n this.queryResults = new Map();\n this.optimisticUpdates = [];\n }\n\n /**\n * Apply all optimistic updates on top of server query results\n */\n ingestQueryResultsFromServer(\n serverQueryResults: QueryResultsMap,\n optimisticUpdatesToDrop: Set<RequestId>,\n ): ChangedQueries {\n this.optimisticUpdates = this.optimisticUpdates.filter((updateAndId) => {\n return !optimisticUpdatesToDrop.has(updateAndId.mutationId);\n });\n\n const oldQueryResults = this.queryResults;\n this.queryResults = new Map(serverQueryResults);\n const localStore = new OptimisticLocalStoreImpl(this.queryResults);\n for (const updateAndId of this.optimisticUpdates) {\n updateAndId.update(localStore);\n }\n\n // To find the changed queries, just do a shallow comparison\n // TODO(CX-733): Change this so we avoid unnecessary rerenders\n const changedQueries: ChangedQueries = [];\n for (const [queryToken, query] of this.queryResults) {\n const oldQuery = oldQueryResults.get(queryToken);\n if (oldQuery === undefined || oldQuery.result !== query.result) {\n changedQueries.push(queryToken);\n }\n }\n\n return changedQueries;\n }\n\n applyOptimisticUpdate(\n update: WrappedOptimisticUpdate,\n mutationId: RequestId,\n ): ChangedQueries {\n // Apply the update to our store\n this.optimisticUpdates.push({\n update,\n mutationId,\n });\n const localStore = new OptimisticLocalStoreImpl(this.queryResults);\n update(localStore);\n\n // Notify about any query results that changed\n // TODO(CX-733): Change this so we avoid unnecessary rerenders\n return localStore.modifiedQueries;\n }\n\n /**\n * \"Raw\" with respect to errors vs values, but query results still have\n * optimistic updates applied.\n *\n * @internal\n */\n rawQueryResult(queryToken: QueryToken): FunctionResult | undefined {\n const query = this.queryResults.get(queryToken);\n if (query === undefined) {\n return undefined;\n }\n return query.result;\n }\n\n queryResult(queryToken: QueryToken): Value | undefined {\n const query = this.queryResults.get(queryToken);\n if (query === undefined) {\n return undefined;\n }\n const result = query.result;\n if (result === undefined) {\n return undefined;\n } else if (result.success) {\n return result.value;\n } else {\n if (result.errorData !== undefined) {\n throw forwardData(\n result,\n new ConvexError(\n createHybridErrorStacktrace(\"query\", query.udfPath, result),\n ),\n );\n }\n throw new Error(\n createHybridErrorStacktrace(\"query\", query.udfPath, result),\n );\n }\n }\n\n hasQueryResult(queryToken: QueryToken): boolean {\n return this.queryResults.get(queryToken) !== undefined;\n }\n\n /**\n * @internal\n */\n queryLogs(queryToken: QueryToken): string[] | undefined {\n const query = this.queryResults.get(queryToken);\n return query?.result?.logLines;\n }\n}\n", "// Implements an unsigned long.\n// This is a subset of https://github.com/dcodeIO/Long.js,\n// vendored to decrease bundle size.\n// Copyright Daniel Wirtz <dcode@dcode.io>\n// License: Apache Version 2.0\n/*\n\n Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright 2023 Daniel Wirtz <dcode@dcode.io>\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n*/\n\n// This works... but don't try to compare one to a real Long.js Long!\n// For internal use only.\n// `| 0` assures the runtime that we are using integer arithmetic\nexport class Long {\n low: number;\n high: number;\n __isUnsignedLong__: boolean;\n\n static isLong(obj: Long) {\n return (obj && obj.__isUnsignedLong__) === true;\n }\n\n constructor(low: number, high: number) {\n this.low = low | 0;\n this.high = high | 0;\n this.__isUnsignedLong__ = true;\n }\n\n // prettier-ignore\n static fromBytesLE(bytes: number[]): Long {\n return new Long(\n bytes[0] |\n bytes[1] << 8 |\n bytes[2] << 16 |\n bytes[3] << 24,\n bytes[4] |\n bytes[5] << 8 |\n bytes[6] << 16 |\n bytes[7] << 24,\n );\n }\n\n // prettier-ignore\n toBytesLE() {\n const hi = this.high;\n const lo = this.low;\n return [\n lo & 0xff,\n lo >>> 8 & 0xff,\n lo >>> 16 & 0xff,\n lo >>> 24,\n hi & 0xff,\n hi >>> 8 & 0xff,\n hi >>> 16 & 0xff,\n hi >>> 24\n ];\n }\n\n static fromNumber(value: number) {\n if (isNaN(value)) return UZERO;\n if (value < 0) return UZERO;\n if (value >= TWO_PWR_64_DBL) return MAX_UNSIGNED_VALUE;\n return new Long(value % TWO_PWR_32_DBL | 0, (value / TWO_PWR_32_DBL) | 0);\n }\n\n toString() {\n return (\n BigInt(this.high) * BigInt(TWO_PWR_32_DBL) +\n BigInt(this.low)\n ).toString();\n }\n\n equals(other: Long) {\n if (!Long.isLong(other)) other = Long.fromValue(other);\n if (this.high >>> 31 === 1 && other.high >>> 31 === 1) return false;\n return this.high === other.high && this.low === other.low;\n }\n\n notEquals(other: Long) {\n return !this.equals(other);\n }\n\n comp(other: Long) {\n if (!Long.isLong(other)) other = Long.fromValue(other);\n if (this.equals(other)) return 0;\n return other.high >>> 0 > this.high >>> 0 ||\n (other.high === this.high && other.low >>> 0 > this.low >>> 0)\n ? -1\n : 1;\n }\n\n lessThanOrEqual(other: Long) {\n return this.comp(/* validates */ other) <= 0;\n }\n\n static fromValue(val: any) {\n if (typeof val === \"number\") return Long.fromNumber(val);\n // Throws for non-objects, converts non-instanceof Long:\n return new Long(val.low, val.high);\n }\n}\n\nconst UZERO = new Long(0, 0);\nconst TWO_PWR_16_DBL = 1 << 16;\nconst TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;\nconst TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;\nconst MAX_UNSIGNED_VALUE = new Long(0xffffffff | 0, 0xffffffff | 0);\n", "import { jsonToConvex } from \"../../values/index.js\";\nimport { Long } from \"../../vendor/long.js\";\nimport { logForFunction, Logger } from \"../logging.js\";\nimport { QueryId, StateVersion, Transition } from \"./protocol.js\";\nimport { FunctionResult } from \"./function_result.js\";\n\n/**\n * A represention of the query results we've received on the current WebSocket\n * connection.\n *\n * Queries you won't find here include:\n * - queries which have been requested, but no query transition has been received yet for\n * - queries which are populated only though active optimistic updates, but are not subscribed to\n * - queries which have already been removed by the server (which it shouldn't do unless that's\n * been requested by the client)\n */\nexport class RemoteQuerySet {\n private version: StateVersion;\n private readonly remoteQuerySet: Map<QueryId, FunctionResult>;\n private readonly queryPath: (queryId: QueryId) => string | null;\n private readonly logger: Logger;\n\n constructor(queryPath: (queryId: QueryId) => string | null, logger: Logger) {\n this.version = { querySet: 0, ts: Long.fromNumber(0), identity: 0 };\n this.remoteQuerySet = new Map();\n this.queryPath = queryPath;\n this.logger = logger;\n }\n\n transition(transition: Transition): void {\n const start = transition.startVersion;\n if (\n this.version.querySet !== start.querySet ||\n this.version.ts.notEquals(start.ts) ||\n this.version.identity !== start.identity\n ) {\n throw new Error(\n `Invalid start version: ${start.ts.toString()}:${start.querySet}:${start.identity}, transitioning from ${this.version.ts.toString()}:${this.version.querySet}:${this.version.identity}`,\n );\n }\n for (const modification of transition.modifications) {\n switch (modification.type) {\n case \"QueryUpdated\": {\n const queryPath = this.queryPath(modification.queryId);\n if (queryPath) {\n for (const line of modification.logLines) {\n logForFunction(this.logger, \"info\", \"query\", queryPath, line);\n }\n }\n const value = jsonToConvex(modification.value ?? null);\n this.remoteQuerySet.set(modification.queryId, {\n success: true,\n value,\n logLines: modification.logLines,\n });\n break;\n }\n case \"QueryFailed\": {\n const queryPath = this.queryPath(modification.queryId);\n if (queryPath) {\n for (const line of modification.logLines) {\n logForFunction(this.logger, \"info\", \"query\", queryPath, line);\n }\n }\n const { errorData } = modification;\n this.remoteQuerySet.set(modification.queryId, {\n success: false,\n errorMessage: modification.errorMessage,\n errorData:\n errorData !== undefined ? jsonToConvex(errorData) : undefined,\n logLines: modification.logLines,\n });\n break;\n }\n case \"QueryRemoved\": {\n this.remoteQuerySet.delete(modification.queryId);\n break;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n modification satisfies never;\n throw new Error(`Invalid modification ${(modification as any).type}`);\n }\n }\n }\n this.version = transition.endVersion;\n }\n\n remoteQueryResults(): Map<QueryId, FunctionResult> {\n return this.remoteQuerySet;\n }\n\n timestamp(): Long {\n return this.version.ts;\n }\n}\n", "import type { UserIdentityAttributes } from \"../../server/authentication.js\";\nexport type { UserIdentityAttributes } from \"../../server/authentication.js\";\nimport { JSONValue, Base64 } from \"../../values/index.js\";\nimport { Long } from \"../../vendor/long.js\";\n\n/**\n * Shared schema\n */\n\nexport function u64ToLong(encoded: EncodedU64): U64 {\n const integerBytes = Base64.toByteArray(encoded);\n return Long.fromBytesLE(Array.from(integerBytes));\n}\n\nexport function longToU64(raw: U64): EncodedU64 {\n const integerBytes = new Uint8Array(raw.toBytesLE());\n return Base64.fromByteArray(integerBytes);\n}\n\nexport function parseServerMessage(\n encoded: EncodedServerMessage,\n): WireServerMessage {\n switch (encoded.type) {\n case \"FatalError\":\n case \"AuthError\":\n case \"ActionResponse\":\n case \"TransitionChunk\":\n case \"Ping\": {\n return { ...encoded };\n }\n case \"MutationResponse\": {\n if (encoded.success) {\n return { ...encoded, ts: u64ToLong(encoded.ts) };\n } else {\n return { ...encoded };\n }\n }\n case \"Transition\": {\n return {\n ...encoded,\n startVersion: {\n ...encoded.startVersion,\n ts: u64ToLong(encoded.startVersion.ts),\n },\n endVersion: {\n ...encoded.endVersion,\n ts: u64ToLong(encoded.endVersion.ts),\n },\n };\n }\n default: {\n encoded satisfies never;\n }\n }\n return undefined as never;\n}\n\nexport function encodeClientMessage(\n message: ClientMessage,\n): EncodedClientMessage {\n switch (message.type) {\n case \"Authenticate\":\n case \"ModifyQuerySet\":\n case \"Mutation\":\n case \"Action\":\n case \"Event\": {\n return { ...message };\n }\n case \"Connect\": {\n if (message.maxObservedTimestamp !== undefined) {\n return {\n ...message,\n maxObservedTimestamp: longToU64(message.maxObservedTimestamp),\n };\n } else {\n return { ...message, maxObservedTimestamp: undefined };\n }\n }\n default: {\n message satisfies never;\n }\n }\n return undefined as never;\n}\n\ntype U64 = Long;\ntype EncodedU64 = string;\n\n/**\n * Unique nonnegative integer identifying a single query.\n */\nexport type QueryId = number; // nonnegative int\n\nexport type QuerySetVersion = number; // nonnegative int\n\nexport type RequestId = number; // nonnegative int\n\nexport type IdentityVersion = number; // nonnegative int\n\n/**\n * A serialized representation of decisions made during a query's execution.\n *\n * A journal is produced when a query function first executes and is re-used\n * when a query is re-executed.\n *\n * Currently this is used to store pagination end cursors to ensure\n * that pages of paginated queries will always end at the same cursor. This\n * enables gapless, reactive pagination.\n *\n * `null` is used to represent empty journals.\n * @public\n */\nexport type QueryJournal = string | null;\n\n/**\n * Client message schema\n */\n\ntype Connect = {\n type: \"Connect\";\n sessionId: string;\n connectionCount: number;\n lastCloseReason: string | null;\n maxObservedTimestamp?: TS | undefined;\n clientTs: number;\n};\n\nexport type AddQuery = {\n type: \"Add\";\n queryId: QueryId;\n udfPath: string;\n args: JSONValue[];\n journal?: QueryJournal | undefined;\n /**\n * @internal\n */\n componentPath?: string | undefined;\n};\n\nexport type RemoveQuery = {\n type: \"Remove\";\n queryId: QueryId;\n};\n\nexport type QuerySetModification = {\n type: \"ModifyQuerySet\";\n baseVersion: QuerySetVersion;\n newVersion: QuerySetVersion;\n modifications: (AddQuery | RemoveQuery)[];\n};\n\nexport type MutationRequest = {\n type: \"Mutation\";\n requestId: RequestId;\n udfPath: string;\n args: JSONValue[];\n // Execute the mutation on a specific component.\n // Only admin auth is allowed to run mutations on non-root components.\n componentPath?: string | undefined;\n};\n\nexport type ActionRequest = {\n type: \"Action\";\n requestId: RequestId;\n udfPath: string;\n args: JSONValue[];\n // Execute the action on a specific component.\n // Only admin auth is allowed to run actions on non-root components.\n componentPath?: string | undefined;\n};\n\nexport type AdminAuthentication = {\n type: \"Authenticate\";\n tokenType: \"Admin\";\n value: string;\n baseVersion: IdentityVersion;\n impersonating?: UserIdentityAttributes | undefined;\n};\n\nexport type Authenticate =\n | AdminAuthentication\n | {\n type: \"Authenticate\";\n tokenType: \"User\";\n value: string;\n baseVersion: IdentityVersion;\n }\n | {\n type: \"Authenticate\";\n tokenType: \"None\";\n baseVersion: IdentityVersion;\n };\n\nexport type Event = {\n type: \"Event\";\n eventType: string;\n event: any;\n};\nexport type ClientMessage =\n | Connect\n | Authenticate\n | QuerySetModification\n | MutationRequest\n | ActionRequest\n | Event;\n\ntype EncodedConnect = Omit<Connect, \"maxObservedTimestamp\"> & {\n maxObservedTimestamp?: EncodedTS | undefined;\n};\n\n// It's not a big deal to add `| undefined` to any optional properties here because\n// these messages are bound for JSON.stringify() serialization, which removes properties\n// that are undefined.\ntype EncodedClientMessage =\n | EncodedConnect\n | Authenticate\n | QuerySetModification\n | MutationRequest\n | ActionRequest\n | Event;\n\n/**\n * Server message schema\n */\nexport type TS = U64;\ntype EncodedTS = EncodedU64;\ntype LogLines = string[];\n\nexport type StateVersion = {\n querySet: QuerySetVersion;\n ts: TS;\n identity: IdentityVersion;\n};\ntype EncodedStateVersion = Omit<StateVersion, \"ts\"> & { ts: EncodedTS };\n\ntype StateModification =\n | {\n type: \"QueryUpdated\";\n queryId: QueryId;\n value: JSONValue;\n logLines: LogLines;\n journal: QueryJournal;\n }\n | {\n type: \"QueryFailed\";\n queryId: QueryId;\n errorMessage: string;\n logLines: LogLines;\n errorData: JSONValue;\n journal: QueryJournal;\n }\n | {\n type: \"QueryRemoved\";\n queryId: QueryId;\n };\n\nexport type Transition = {\n type: \"Transition\";\n startVersion: StateVersion;\n endVersion: StateVersion;\n modifications: StateModification[];\n clientClockSkew?: number;\n serverTs?: number;\n};\n\nexport type TransitionChunk = {\n type: \"TransitionChunk\";\n chunk: string;\n partNumber: number;\n totalParts: number;\n transitionId: string;\n};\n\ntype MutationSuccess = {\n type: \"MutationResponse\";\n requestId: RequestId;\n success: true;\n result: JSONValue;\n ts: TS;\n logLines: LogLines;\n};\ntype MutationFailed = {\n type: \"MutationResponse\";\n requestId: RequestId;\n success: false;\n result: string;\n logLines: LogLines;\n errorData?: JSONValue;\n};\nexport type MutationResponse = MutationSuccess | MutationFailed;\ntype ActionSuccess = {\n type: \"ActionResponse\";\n requestId: RequestId;\n success: true;\n result: JSONValue;\n logLines: LogLines;\n};\ntype ActionFailed = {\n type: \"ActionResponse\";\n requestId: RequestId;\n success: false;\n result: string;\n logLines: LogLines;\n errorData?: JSONValue;\n};\nexport type ActionResponse = ActionSuccess | ActionFailed;\nexport type AuthError = {\n type: \"AuthError\";\n error: string;\n baseVersion: IdentityVersion;\n // True if this error is in response to processing a new `Authenticate` message.\n // Other AuthErrors may occur due to executing a function with expired auth and\n // should be handled differently.\n authUpdateAttempted: boolean;\n};\ntype FatalError = {\n type: \"FatalError\";\n error: string;\n};\ntype Ping = {\n type: \"Ping\";\n};\n\n// Server Messages without the messages only visible to WebSocketManager\nexport type ServerMessage =\n | Transition\n | MutationResponse\n | ActionResponse\n | FatalError\n | AuthError;\n\nexport type WireServerMessage =\n | Transition\n | TransitionChunk\n | MutationResponse\n | ActionResponse\n | FatalError\n | AuthError\n | Ping;\n\ntype EncodedTransition = Omit<Transition, \"startVersion\" | \"endVersion\"> & {\n startVersion: EncodedStateVersion;\n endVersion: EncodedStateVersion;\n};\ntype EncodedMutationSuccess = Omit<MutationSuccess, \"ts\"> & { ts: EncodedTS };\ntype EncodedMutationResponse = MutationFailed | EncodedMutationSuccess;\n\ntype EncodedServerMessage =\n | EncodedTransition\n | TransitionChunk\n | EncodedMutationResponse\n | ActionResponse\n | FatalError\n | AuthError\n | Ping;\n", "import { Logger } from \"../logging.js\";\nimport {\n ClientMessage,\n encodeClientMessage,\n parseServerMessage,\n ServerMessage,\n Transition,\n TransitionChunk,\n} from \"./protocol.js\";\n\nconst CLOSE_NORMAL = 1000;\nconst CLOSE_GOING_AWAY = 1001;\nconst CLOSE_NO_STATUS = 1005;\n/** Convex-specific close code representing a \"404 Not Found\".\n * The edge Onramp accepts websocket upgrades before confirming that the\n * intended destination exists, so this code is sent once we've discovered that\n * the destination does not exist.\n */\nconst CLOSE_NOT_FOUND = 4040;\n\n/**\n * The various states our WebSocket can be in:\n *\n * - \"disconnected\": We don't have a WebSocket, but plan to create one.\n * - \"connecting\": We have created the WebSocket and are waiting for the\n * `onOpen` callback.\n * - \"ready\": We have an open WebSocket.\n * - \"stopped\": The WebSocket was closed and a new one can be created via `.restart()`.\n * - \"terminated\": We have closed the WebSocket and will never create a new one.\n *\n *\n * WebSocket State Machine\n * -----------------------\n * initialState: disconnected\n * validTransitions:\n * disconnected:\n * new WebSocket() -> connecting\n * terminate() -> terminated\n * connecting:\n * onopen -> ready\n * close() -> disconnected\n * terminate() -> terminated\n * ready:\n * close() -> disconnected\n * stop() -> stopped\n * terminate() -> terminated\n * stopped:\n * restart() -> connecting\n * terminate() -> terminated\n * terminalStates:\n * terminated\n *\n *\n *\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u250C\u2500\u2500\u2500\u2500terminate()\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2502 disconnected \u2502\u25C0\u2500\u2510\n * \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n * \u25BC \u2502 \u25B2 \u2502\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 new WebSocket() \u2502 \u2502\n * \u250C\u2500\u25B6\u2502 terminated \u2502\u25C0\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502 \u2502 \u2502\n * \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502 \u2502 \u2502 \u2502\n * \u2502 \u25B2 terminate() \u2502 close() close()\n * \u2502 terminate() \u2502 \u2502 \u2502 \u2502\n * \u2502 \u2502 \u2502 \u25BC \u2502 \u2502\n * \u2502 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\n * \u2502 \u2502 stopped \u2502\u2500\u2500restart()\u2500\u2500\u2500\u25B6\u2502 connecting \u2502 \u2502\n * \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n * \u2502 \u25B2 \u2502 \u2502\n * \u2502 \u2502 onopen \u2502\n * \u2502 \u2502 \u2502 \u2502\n * \u2502 \u2502 \u25BC \u2502\n * terminate() \u2502 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\n * \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500stop()\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2502 ready \u2502\u2500\u2500\u2518\n * \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n * \u2502 \u2502\n * \u2502 \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n *\n * The `connecting` and `ready` state have a sub-state-machine for pausing.\n */\n\ntype Socket =\n | { state: \"disconnected\" }\n | { state: \"connecting\"; ws: WebSocket; paused: \"yes\" | \"no\" }\n | { state: \"ready\"; ws: WebSocket; paused: \"yes\" | \"no\" | \"uninitialized\" }\n | { state: \"stopped\" }\n | { state: \"terminated\" };\n\nexport type ReconnectMetadata = {\n connectionCount: number;\n lastCloseReason: string | null;\n clientTs: number;\n};\n\nexport type OnMessageResponse = {\n hasSyncedPastLastReconnect: boolean;\n};\n\nlet firstTime: number | undefined;\nfunction monotonicMillis() {\n if (firstTime === undefined) {\n firstTime = Date.now();\n }\n if (typeof performance === \"undefined\" || !performance.now) {\n return Date.now();\n }\n return Math.round(firstTime + performance.now());\n}\n\nfunction prettyNow() {\n return `t=${Math.round((monotonicMillis() - firstTime!) / 100) / 10}s`;\n}\n\nconst serverDisconnectErrors = {\n // A known error, e.g. during a restart or push\n InternalServerError: { timeout: 1000 },\n // ErrorMetadata::overloaded() messages that we realy should back off\n SubscriptionsWorkerFullError: { timeout: 3000 },\n TooManyConcurrentRequests: { timeout: 3000 },\n CommitterFullError: { timeout: 3000 },\n AwsTooManyRequestsException: { timeout: 3000 },\n ExecuteFullError: { timeout: 3000 },\n SystemTimeoutError: { timeout: 3000 },\n ExpiredInQueue: { timeout: 3000 },\n // ErrorMetadata::feature_temporarily_unavailable() that typically indicate a deploy just happened\n VectorIndexesUnavailable: { timeout: 1000 },\n SearchIndexesUnavailable: { timeout: 1000 },\n TableSummariesUnavailable: { timeout: 1000 },\n // More ErrorMetadata::overloaded()\n VectorIndexTooLarge: { timeout: 3000 },\n SearchIndexTooLarge: { timeout: 3000 },\n TooManyWritesInTimePeriod: { timeout: 3000 },\n} as const satisfies Record<string, { timeout: number }>;\n\ntype ServerDisconnectError = keyof typeof serverDisconnectErrors | \"Unknown\";\n\nfunction classifyDisconnectError(s?: string): ServerDisconnectError {\n if (s === undefined) return \"Unknown\";\n // startsWith so more info could be at the end (although currently there isn't)\n\n for (const prefix of Object.keys(\n serverDisconnectErrors,\n ) as ServerDisconnectError[]) {\n if (s.startsWith(prefix)) {\n return prefix;\n }\n }\n return \"Unknown\";\n}\n\n/**\n * A wrapper around a websocket that handles errors, reconnection, and message\n * parsing.\n */\nexport class WebSocketManager {\n private socket: Socket;\n\n private connectionCount: number;\n private _hasEverConnected: boolean = false;\n private lastCloseReason:\n | \"InitialConnect\"\n | \"OnCloseInvoked\"\n | (string & {}) // a full serverErrorReason (not just the prefix) or a new one\n | null;\n\n // State for assembling the split-up Transition currently being received.\n private transitionChunkBuffer: {\n chunks: string[];\n totalParts: number;\n transitionId: string;\n } | null = null;\n\n /** Upon HTTPS/WSS failure, the first jittered backoff duration, in ms. */\n private readonly defaultInitialBackoff: number;\n\n /** We backoff exponentially, but we need to cap that--this is the jittered max. */\n private readonly maxBackoff: number;\n\n /** How many times have we failed consecutively? */\n private retries: number;\n\n /** How long before lack of server response causes us to initiate a reconnect,\n * in ms */\n private readonly serverInactivityThreshold: number;\n\n private reconnectDueToServerInactivityTimeout: ReturnType<\n typeof setTimeout\n > | null;\n\n /** Scheduled reconnect state: timeout handle and timing info */\n private scheduledReconnect: {\n timeout: ReturnType<typeof setTimeout>;\n scheduledAt: number;\n backoffMs: number;\n } | null = null;\n\n private networkOnlineHandler: (() => void) | null = null;\n\n /** Pending event to send after reconnecting due to network recovery */\n private pendingNetworkRecoveryInfo: { timeSavedMs: number } | null = null;\n\n private readonly uri: string;\n private readonly onOpen: (reconnectMetadata: ReconnectMetadata) => void;\n private readonly onResume: () => void;\n private readonly onMessage: (message: ServerMessage) => OnMessageResponse;\n private readonly webSocketConstructor: typeof WebSocket;\n private readonly logger: Logger;\n private readonly onServerDisconnectError:\n | ((message: string) => void)\n | undefined;\n\n constructor(\n uri: string,\n callbacks: {\n onOpen: (reconnectMetadata: ReconnectMetadata) => void;\n onResume: () => void;\n onMessage: (message: ServerMessage) => OnMessageResponse;\n onServerDisconnectError?: ((message: string) => void) | undefined;\n },\n webSocketConstructor: typeof WebSocket,\n logger: Logger,\n private readonly markConnectionStateDirty: () => void,\n private readonly debug: boolean,\n ) {\n this.webSocketConstructor = webSocketConstructor;\n this.socket = { state: \"disconnected\" };\n this.connectionCount = 0;\n this.lastCloseReason = \"InitialConnect\";\n\n // backoff for unknown errors\n this.defaultInitialBackoff = 1000;\n this.maxBackoff = 16000;\n this.retries = 0;\n\n // Ping messages (sync protocol Pings, not WebSocket protocol Pings) are\n // sent every 15s in the absence of other messages. But a single large\n // Transition or other downstream message can hog the line so this\n // threshold is set higher to prevent clients from giving up.\n this.serverInactivityThreshold = 60000;\n this.reconnectDueToServerInactivityTimeout = null;\n\n this.uri = uri;\n this.onOpen = callbacks.onOpen;\n this.onResume = callbacks.onResume;\n this.onMessage = callbacks.onMessage;\n this.onServerDisconnectError = callbacks.onServerDisconnectError;\n this.logger = logger;\n\n // Set up network online event listener\n this.setupNetworkListener();\n\n this.connect();\n }\n\n private setSocketState(state: Socket) {\n this.socket = state;\n this._logVerbose(\n `socket state changed: ${this.socket.state}, paused: ${\n \"paused\" in this.socket ? this.socket.paused : undefined\n }`,\n );\n this.markConnectionStateDirty();\n }\n\n private setupNetworkListener() {\n // Only set up listener if we're in a browser environment with addEventListener\n // (React Native has window but not addEventListener)\n if (\n typeof window === \"undefined\" ||\n typeof window.addEventListener !== \"function\"\n ) {\n return;\n }\n // Avoid registering duplicate listeners\n if (this.networkOnlineHandler !== null) {\n return;\n }\n\n this.networkOnlineHandler = () => {\n this._logVerbose(\"network online event detected\");\n this.tryReconnectImmediately();\n };\n\n window.addEventListener(\"online\", this.networkOnlineHandler);\n this._logVerbose(\"network online event listener registered\");\n }\n\n private cleanupNetworkListener() {\n if (\n this.networkOnlineHandler &&\n typeof window !== \"undefined\" &&\n typeof window.removeEventListener === \"function\"\n ) {\n window.removeEventListener(\"online\", this.networkOnlineHandler);\n this.networkOnlineHandler = null;\n this._logVerbose(\"network online event listener removed\");\n }\n }\n\n private assembleTransition(chunk: TransitionChunk): Transition | null {\n if (\n chunk.partNumber < 0 ||\n chunk.partNumber >= chunk.totalParts ||\n chunk.totalParts === 0 ||\n (this.transitionChunkBuffer &&\n (this.transitionChunkBuffer.totalParts !== chunk.totalParts ||\n this.transitionChunkBuffer.transitionId !== chunk.transitionId))\n ) {\n // Throwing an error doesn't crash the client, so clear the buffer.\n this.transitionChunkBuffer = null;\n throw new Error(\"Invalid TransitionChunk\");\n }\n\n if (this.transitionChunkBuffer === null) {\n this.transitionChunkBuffer = {\n chunks: [],\n totalParts: chunk.totalParts,\n transitionId: chunk.transitionId,\n };\n }\n\n if (chunk.partNumber !== this.transitionChunkBuffer.chunks.length) {\n // Throwing an error doesn't crash the client, so clear the buffer.\n const expectedLength = this.transitionChunkBuffer.chunks.length;\n this.transitionChunkBuffer = null;\n throw new Error(\n `TransitionChunk received out of order: expected part ${expectedLength}, got ${chunk.partNumber}`,\n );\n }\n\n this.transitionChunkBuffer.chunks.push(chunk.chunk);\n\n if (this.transitionChunkBuffer.chunks.length === chunk.totalParts) {\n const fullJson = this.transitionChunkBuffer.chunks.join(\"\");\n this.transitionChunkBuffer = null;\n\n const transition = parseServerMessage(JSON.parse(fullJson));\n if (transition.type !== \"Transition\") {\n throw new Error(\n `Expected Transition, got ${transition.type} after assembling chunks`,\n );\n }\n return transition;\n }\n\n return null;\n }\n\n private connect() {\n if (this.socket.state === \"terminated\") {\n return;\n }\n if (\n this.socket.state !== \"disconnected\" &&\n this.socket.state !== \"stopped\"\n ) {\n throw new Error(\n \"Didn't start connection from disconnected state: \" + this.socket.state,\n );\n }\n\n const ws = new this.webSocketConstructor(this.uri);\n this._logVerbose(\"constructed WebSocket\");\n this.setSocketState({\n state: \"connecting\",\n ws,\n paused: \"no\",\n });\n\n // Kick off server inactivity timer before WebSocket connection is established\n // so we can detect cases where handshake fails.\n // The `onopen` event only fires after the connection is established:\n // Source: https://datatracker.ietf.org/doc/html/rfc6455#page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and\n this.resetServerInactivityTimeout();\n\n ws.onopen = () => {\n this.logger.logVerbose(\"begin ws.onopen\");\n if (this.socket.state !== \"connecting\") {\n throw new Error(\"onopen called with socket not in connecting state\");\n }\n this.setSocketState({\n state: \"ready\",\n ws,\n paused: this.socket.paused === \"yes\" ? \"uninitialized\" : \"no\",\n });\n this.resetServerInactivityTimeout();\n if (this.socket.paused === \"no\") {\n this._hasEverConnected = true;\n this.onOpen({\n connectionCount: this.connectionCount,\n lastCloseReason: this.lastCloseReason,\n clientTs: monotonicMillis(),\n });\n }\n\n if (this.lastCloseReason !== \"InitialConnect\") {\n if (this.lastCloseReason) {\n this.logger.log(\n \"WebSocket reconnected at\",\n prettyNow(),\n \"after disconnect due to\",\n this.lastCloseReason,\n );\n } else {\n this.logger.log(\"WebSocket reconnected at\", prettyNow());\n }\n }\n\n this.connectionCount += 1;\n this.lastCloseReason = null;\n\n // Send event for network recovery reconnect if applicable\n if (this.pendingNetworkRecoveryInfo !== null) {\n const { timeSavedMs } = this.pendingNetworkRecoveryInfo;\n this.pendingNetworkRecoveryInfo = null;\n this.sendMessage({\n type: \"Event\",\n eventType: \"NetworkRecoveryReconnect\",\n event: { timeSavedMs },\n });\n this.logger.log(\n `Network recovery reconnect saved ~${Math.round(timeSavedMs / 1000)}s of waiting`,\n );\n }\n };\n // NB: The WebSocket API calls `onclose` even if connection fails, so we can route all error paths through `onclose`.\n ws.onerror = (error) => {\n this.transitionChunkBuffer = null;\n const message = (error as ErrorEvent).message;\n if (message) {\n this.logger.log(`WebSocket error message: ${message}`);\n }\n };\n ws.onmessage = (message) => {\n this.resetServerInactivityTimeout();\n const messageLength = message.data.length;\n let serverMessage = parseServerMessage(JSON.parse(message.data));\n this._logVerbose(`received ws message with type ${serverMessage.type}`);\n\n // Ping's only purpose is to reset the server inactivity timer.\n if (serverMessage.type === \"Ping\") {\n return;\n }\n\n // TransitionChunks never reach the main client logic.\n if (serverMessage.type === \"TransitionChunk\") {\n const transition = this.assembleTransition(serverMessage);\n if (!transition) {\n return;\n }\n serverMessage = transition;\n this._logVerbose(\n `assembled full ws message of type ${serverMessage.type}`,\n );\n }\n\n if (this.transitionChunkBuffer !== null) {\n this.transitionChunkBuffer = null;\n this.logger.log(\n `Received unexpected ${serverMessage.type} while buffering TransitionChunks`,\n );\n }\n\n if (serverMessage.type === \"Transition\") {\n this.reportLargeTransition({\n messageLength,\n transition: serverMessage,\n });\n }\n const response = this.onMessage(serverMessage);\n if (response.hasSyncedPastLastReconnect) {\n // Reset backoff to 0 once all outstanding requests are complete.\n this.retries = 0;\n this.markConnectionStateDirty();\n }\n };\n ws.onclose = (event) => {\n this._logVerbose(\"begin ws.onclose\");\n this.transitionChunkBuffer = null;\n if (this.lastCloseReason === null) {\n // event.reason is often an empty string\n this.lastCloseReason = event.reason || `closed with code ${event.code}`;\n }\n if (\n event.code !== CLOSE_NORMAL &&\n event.code !== CLOSE_GOING_AWAY && // This commonly gets fired on mobile apps when the app is backgrounded\n event.code !== CLOSE_NO_STATUS &&\n event.code !== CLOSE_NOT_FOUND // Note that we want to retry on a 404, as it can be transient during a push.\n ) {\n let msg = `WebSocket closed with code ${event.code}`;\n if (event.reason) {\n msg += `: ${event.reason}`;\n }\n this.logger.log(msg);\n if (this.onServerDisconnectError && event.reason) {\n // This callback is a unstable API, InternalServerErrors in particular may be removed\n // since they reflect expected temporary downtime. But until a quantitative measure\n // of uptime is reported this unstable API errs on the inclusive side.\n this.onServerDisconnectError(msg);\n }\n }\n const reason = classifyDisconnectError(event.reason);\n this.scheduleReconnect(reason);\n return;\n };\n }\n\n /**\n * @returns The state of the {@link Socket}.\n */\n socketState(): string {\n return this.socket.state;\n }\n\n /**\n * @param message - A ClientMessage to send.\n * @returns Whether the message (might have been) sent.\n */\n sendMessage(message: ClientMessage) {\n const messageForLog = {\n type: message.type,\n ...(message.type === \"Authenticate\" && message.tokenType === \"User\"\n ? {\n value: `...${message.value.slice(-7)}`,\n }\n : {}),\n };\n if (this.socket.state === \"ready\" && this.socket.paused === \"no\") {\n const encodedMessage = encodeClientMessage(message);\n const request = JSON.stringify(encodedMessage);\n let sent = false;\n try {\n this.socket.ws.send(request);\n sent = true;\n } catch (error: any) {\n this.logger.log(\n `Failed to send message on WebSocket, reconnecting: ${error}`,\n );\n this.closeAndReconnect(\"FailedToSendMessage\");\n }\n this._logVerbose(\n `${sent ? \"sent\" : \"failed to send\"} message with type ${message.type}: ${JSON.stringify(\n messageForLog,\n )}`,\n );\n return true;\n }\n this._logVerbose(\n `message not sent (socket state: ${this.socket.state}, paused: ${\"paused\" in this.socket ? this.socket.paused : undefined}): ${JSON.stringify(\n messageForLog,\n )}`,\n );\n\n return false;\n }\n\n private resetServerInactivityTimeout() {\n if (this.socket.state === \"terminated\") {\n // Don't reset any timers if we were trying to terminate.\n return;\n }\n if (this.reconnectDueToServerInactivityTimeout !== null) {\n clearTimeout(this.reconnectDueToServerInactivityTimeout);\n this.reconnectDueToServerInactivityTimeout = null;\n }\n this.reconnectDueToServerInactivityTimeout = setTimeout(() => {\n this.closeAndReconnect(\"InactiveServer\");\n }, this.serverInactivityThreshold);\n }\n\n private scheduleReconnect(reason: \"client\" | ServerDisconnectError) {\n // Cancel any existing scheduled reconnect to avoid multiple reconnects\n if (this.scheduledReconnect) {\n clearTimeout(this.scheduledReconnect.timeout);\n this.scheduledReconnect = null;\n }\n\n this.socket = { state: \"disconnected\" };\n const backoff = this.nextBackoff(reason);\n this.markConnectionStateDirty();\n this.logger.log(`Attempting reconnect in ${Math.round(backoff)}ms`);\n\n const scheduledAt = monotonicMillis();\n const timeoutId = setTimeout(() => {\n // Only proceed if this timeout hasn't been cleared\n if (this.scheduledReconnect?.timeout === timeoutId) {\n this.scheduledReconnect = null;\n this.connect();\n }\n }, backoff);\n\n this.scheduledReconnect = {\n timeout: timeoutId,\n scheduledAt,\n backoffMs: backoff,\n };\n }\n\n /**\n * Close the WebSocket and schedule a reconnect.\n *\n * This should be used when we hit an error and would like to restart the session.\n */\n private closeAndReconnect(closeReason: string) {\n this._logVerbose(`begin closeAndReconnect with reason ${closeReason}`);\n switch (this.socket.state) {\n case \"disconnected\":\n case \"terminated\":\n case \"stopped\":\n // Nothing to do if we don't have a WebSocket.\n return;\n case \"connecting\":\n case \"ready\": {\n this.lastCloseReason = closeReason;\n // Close the old socket asynchronously, we'll open a new socket in reconnect.\n void this.close();\n this.scheduleReconnect(\"client\");\n return;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n }\n }\n }\n\n /**\n * Close the WebSocket, being careful to clear the onclose handler to avoid re-entrant\n * calls. Use this instead of directly calling `ws.close()`\n *\n * It is the callers responsibility to update the state after this method is called so that the\n * closed socket is not accessible or used again after this method is called\n */\n private close(): Promise<void> {\n this.transitionChunkBuffer = null;\n switch (this.socket.state) {\n case \"disconnected\":\n case \"terminated\":\n case \"stopped\":\n // Nothing to do if we don't have a WebSocket.\n return Promise.resolve();\n case \"connecting\": {\n const ws = this.socket.ws;\n // Messages can still be received after close but we're not interested.\n ws.onmessage = (_message) => {\n this._logVerbose(\"Ignoring message received after close\");\n };\n return new Promise((r) => {\n ws.onclose = () => {\n this._logVerbose(\"Closed after connecting\");\n r();\n };\n ws.onopen = () => {\n this._logVerbose(\"Opened after connecting\");\n ws.close();\n };\n });\n }\n case \"ready\": {\n this._logVerbose(\"ws.close called\");\n const ws = this.socket.ws;\n // Messages can still be received after close but we're not interested.\n ws.onmessage = (_message) => {\n this._logVerbose(\"Ignoring message received after close\");\n };\n const result: Promise<void> = new Promise((r) => {\n ws.onclose = () => {\n r();\n };\n });\n ws.close();\n return result;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n return Promise.resolve();\n }\n }\n }\n\n /**\n * Close the WebSocket and do not reconnect.\n * @returns A Promise that resolves when the WebSocket `onClose` callback is called.\n */\n terminate(): Promise<void> {\n if (this.reconnectDueToServerInactivityTimeout) {\n clearTimeout(this.reconnectDueToServerInactivityTimeout);\n }\n if (this.scheduledReconnect) {\n clearTimeout(this.scheduledReconnect.timeout);\n this.scheduledReconnect = null;\n }\n this.cleanupNetworkListener();\n switch (this.socket.state) {\n case \"terminated\":\n case \"stopped\":\n case \"disconnected\":\n case \"connecting\":\n case \"ready\": {\n const result = this.close();\n this.setSocketState({ state: \"terminated\" });\n return result;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n throw new Error(\n `Invalid websocket state: ${(this.socket as any).state}`,\n );\n }\n }\n }\n\n stop(): Promise<void> {\n switch (this.socket.state) {\n case \"terminated\":\n // If we're terminating we ignore stop\n return Promise.resolve();\n case \"connecting\":\n case \"stopped\":\n case \"disconnected\":\n case \"ready\": {\n this.cleanupNetworkListener();\n const result = this.close();\n this.socket = { state: \"stopped\" };\n return result;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n return Promise.resolve();\n }\n }\n }\n\n /**\n * Create a new WebSocket after a previous `stop()`, unless `terminate()` was\n * called before.\n */\n tryRestart(): void {\n switch (this.socket.state) {\n case \"stopped\":\n break;\n case \"terminated\":\n case \"connecting\":\n case \"ready\":\n case \"disconnected\":\n this.logger.logVerbose(\"Restart called without stopping first\");\n return;\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n }\n }\n this.setupNetworkListener();\n this.connect();\n }\n\n pause(): void {\n switch (this.socket.state) {\n case \"disconnected\":\n case \"stopped\":\n case \"terminated\":\n // If already stopped or stopping ignore.\n return;\n case \"connecting\":\n case \"ready\": {\n this.socket = { ...this.socket, paused: \"yes\" };\n return;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n return;\n }\n }\n }\n\n /**\n * Try to reconnect immediately, canceling any scheduled reconnect.\n * This is useful when detecting network recovery.\n * Only takes action if we're in disconnected state (waiting to reconnect).\n */\n tryReconnectImmediately(): void {\n this._logVerbose(\"tryReconnectImmediately called\");\n\n // Only reconnect if we're in disconnected state (waiting to reconnect)\n if (this.socket.state !== \"disconnected\") {\n this._logVerbose(\n `tryReconnectImmediately called but socket state is ${this.socket.state}, no action taken`,\n );\n return;\n }\n\n // Track how much time we saved by reconnecting immediately\n let timeSavedMs: number | null = null;\n if (this.scheduledReconnect) {\n const elapsed = monotonicMillis() - this.scheduledReconnect.scheduledAt;\n timeSavedMs = Math.max(0, this.scheduledReconnect.backoffMs - elapsed);\n this._logVerbose(\n `would have waited ${Math.round(timeSavedMs)}ms more (backoff was ${Math.round(this.scheduledReconnect.backoffMs)}ms, elapsed ${Math.round(elapsed)}ms)`,\n );\n // Cancel the scheduled reconnect\n clearTimeout(this.scheduledReconnect.timeout);\n this.scheduledReconnect = null;\n this._logVerbose(\"canceled scheduled reconnect\");\n }\n\n this.logger.log(\"Network recovery detected, reconnecting immediately\");\n // Store the time saved to send as an event after we connect\n this.pendingNetworkRecoveryInfo =\n timeSavedMs !== null ? { timeSavedMs } : null;\n this.connect();\n }\n\n /**\n * Resume the state machine if previously paused.\n */\n resume(): void {\n switch (this.socket.state) {\n case \"connecting\":\n this.socket = { ...this.socket, paused: \"no\" };\n return;\n case \"ready\":\n if (this.socket.paused === \"uninitialized\") {\n this.socket = { ...this.socket, paused: \"no\" };\n this._hasEverConnected = true;\n this.onOpen({\n connectionCount: this.connectionCount,\n lastCloseReason: this.lastCloseReason,\n clientTs: monotonicMillis(),\n });\n } else if (this.socket.paused === \"yes\") {\n this.socket = { ...this.socket, paused: \"no\" };\n this.onResume();\n }\n return;\n case \"terminated\":\n case \"stopped\":\n case \"disconnected\":\n // Ignore resume if not paused, perhaps we already resumed.\n return;\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n }\n }\n this.connect();\n }\n\n connectionState(): {\n isConnected: boolean;\n hasEverConnected: boolean;\n connectionCount: number;\n connectionRetries: number;\n } {\n return {\n isConnected: this.socket.state === \"ready\",\n hasEverConnected: this._hasEverConnected,\n connectionCount: this.connectionCount,\n connectionRetries: this.retries,\n };\n }\n\n private _logVerbose(message: string) {\n this.logger.logVerbose(message);\n }\n\n private nextBackoff(reason: \"client\" | ServerDisconnectError): number {\n const initialBackoff: number =\n reason === \"client\"\n ? 100 // There's no evidence of a server problem, retry quickly\n : reason === \"Unknown\"\n ? this.defaultInitialBackoff\n : serverDisconnectErrors[reason].timeout;\n\n const baseBackoff = initialBackoff * Math.pow(2, this.retries);\n this.retries += 1;\n const actualBackoff = Math.min(baseBackoff, this.maxBackoff);\n const jitter = actualBackoff * (Math.random() - 0.5);\n return actualBackoff + jitter;\n }\n\n private reportLargeTransition({\n transition,\n messageLength,\n }: {\n transition: Transition;\n messageLength: number;\n }) {\n if (\n transition.clientClockSkew === undefined ||\n transition.serverTs === undefined\n ) {\n return;\n }\n\n const transitionTransitTime =\n monotonicMillis() - // client time now\n // clientClockSkew = (server time + upstream latency) - client time\n // clientClockSkew is \"how many milliseconds behind (slow) is the client clock\"\n // but the latency of the Connect message inflates this, making it appear further behind\n transition.clientClockSkew -\n transition.serverTs / 1_000_000; // server time when transition was sent\n const prettyTransitionTime = `${Math.round(transitionTransitTime)}ms`;\n const prettyMessageMB = `${Math.round(messageLength / 10_000) / 100}MB`;\n const bytesPerSecond = messageLength / (transitionTransitTime / 1000);\n const prettyBytesPerSecond = `${Math.round(bytesPerSecond / 10_000) / 100}MB per second`;\n this._logVerbose(\n `received ${prettyMessageMB} transition in ${prettyTransitionTime} at ${prettyBytesPerSecond}`,\n );\n\n // Warnings that will show up for *all users*, so don't be too aggressive.\n // These can be silenced (along with reconnection messages) by setting `logger: false` in client options.\n if (messageLength > 20_000_000) {\n // Big enough that the developer should be made aware of this.\n this.logger.log(\n `received query results totaling more that 20MB (${prettyMessageMB}) which will take a long time to download on slower connections`,\n );\n } else if (transitionTransitTime > 20_000) {\n // Long enough that a pattern of these should be interesting to a developer, but be aware that\n // weak connections, putting clients to sleep, backgrounding etc. could all cause this too.\n this.logger.log(\n `received query results totaling ${prettyMessageMB} which took more than 20s to arrive (${prettyTransitionTime})`,\n );\n }\n\n if (this.debug) {\n // debug means \"reportDebugInfoToConvex\" is set so this can be aggressive.\n this.sendMessage({\n type: \"Event\",\n eventType: \"ClientReceivedTransition\",\n event: { transitionTransitTime, messageLength },\n });\n }\n }\n}\n", "export function newSessionId() {\n return uuidv4();\n}\n\n// From https://stackoverflow.com/a/2117523\nfunction uuidv4() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0,\n v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n", "export interface JwtDecodeOptions {\n header?: boolean;\n}\n\nexport interface JwtHeader {\n typ?: string;\n alg?: string;\n kid?: string;\n}\n\nexport interface JwtPayload {\n iss?: string;\n sub?: string;\n aud?: string[] | string;\n exp?: number;\n nbf?: number;\n iat?: number;\n jti?: string;\n}\n\nexport class InvalidTokenError extends Error {}\n\nInvalidTokenError.prototype.name = \"InvalidTokenError\";\n\nfunction b64DecodeUnicode(str: string) {\n return decodeURIComponent(\n atob(str).replace(/(.)/g, (_m, p) => {\n let code = (p as string).charCodeAt(0).toString(16).toUpperCase();\n if (code.length < 2) {\n code = \"0\" + code;\n }\n return \"%\" + code;\n }),\n );\n}\n\nfunction base64UrlDecode(str: string) {\n let output = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n switch (output.length % 4) {\n case 0:\n break;\n case 2:\n output += \"==\";\n break;\n case 3:\n output += \"=\";\n break;\n default:\n throw new Error(\"base64 string is not of the correct length\");\n }\n\n try {\n return b64DecodeUnicode(output);\n } catch {\n return atob(output);\n }\n}\n\nexport function jwtDecode<T = JwtHeader>(\n token: string,\n options: JwtDecodeOptions & { header: true },\n): T;\nexport function jwtDecode<T = JwtPayload>(\n token: string,\n options?: JwtDecodeOptions,\n): T;\nexport function jwtDecode<T = JwtHeader | JwtPayload>(\n token: string,\n options?: JwtDecodeOptions,\n): T {\n if (typeof token !== \"string\") {\n throw new InvalidTokenError(\"Invalid token specified: must be a string\");\n }\n\n options ||= {};\n\n const pos = options.header === true ? 0 : 1;\n const part = token.split(\".\")[pos];\n\n if (typeof part !== \"string\") {\n throw new InvalidTokenError(\n `Invalid token specified: missing part #${pos + 1}`,\n );\n }\n\n let decoded: string;\n try {\n decoded = base64UrlDecode(part);\n } catch (e) {\n throw new InvalidTokenError(\n `Invalid token specified: invalid base64 for part #${pos + 1} (${(e as Error).message})`,\n );\n }\n\n try {\n return JSON.parse(decoded) as T;\n } catch (e) {\n throw new InvalidTokenError(\n `Invalid token specified: invalid json for part #${pos + 1} (${(e as Error).message})`,\n );\n }\n}\n", "import { Logger } from \"../logging.js\";\nimport { LocalSyncState } from \"./local_state.js\";\nimport { AuthError, IdentityVersion, Transition } from \"./protocol.js\";\nimport { jwtDecode } from \"../../vendor/jwt-decode/index.js\";\n\n// setTimout uses 32 bit integer, so it can only\n// schedule about 24 days in the future.\nconst MAXIMUM_REFRESH_DELAY = 20 * 24 * 60 * 60 * 1000; // 20 days\n\nconst MAX_TOKEN_CONFIRMATION_ATTEMPTS = 2;\n\n/**\n * An async function returning a JWT. Depending on the auth providers\n * configured in convex/auth.config.ts, this may be a JWT-encoded OpenID\n * Connect Identity Token or a traditional JWT.\n *\n * `forceRefreshToken` is `true` if the server rejected a previously\n * returned token or the token is anticipated to expiring soon\n * based on its `exp` time.\n *\n * See {@link ConvexReactClient.setAuth}.\n *\n * @public\n */\nexport type AuthTokenFetcher = (args: {\n forceRefreshToken: boolean;\n}) => Promise<string | null | undefined>;\n\n/**\n * What is provided to the client.\n */\ntype AuthConfig = {\n fetchToken: AuthTokenFetcher;\n onAuthChange: (isAuthenticated: boolean) => void;\n};\n\n/**\n * In general we take 3 steps:\n * 1. Fetch a possibly cached token\n * 2. Immediately fetch a fresh token without using a cache\n * 3. Repeat step 2 before the end of the fresh token's lifetime\n *\n * When we fetch without using a cache we know when the token\n * will expire, and can schedule refetching it.\n *\n * If we get an error before a scheduled refetch, we go back\n * to step 2.\n */\ntype AuthState =\n | { state: \"noAuth\" }\n | {\n state: \"waitingForServerConfirmationOfCachedToken\";\n config: AuthConfig;\n hasRetried: boolean;\n }\n | {\n state: \"initialRefetch\";\n config: AuthConfig;\n }\n | {\n state: \"waitingForServerConfirmationOfFreshToken\";\n config: AuthConfig;\n hadAuth: boolean;\n token: string;\n }\n | {\n state: \"waitingForScheduledRefetch\";\n config: AuthConfig;\n refetchTokenTimeoutId: ReturnType<typeof setTimeout>;\n }\n // Special/weird state when we got a valid token\n // but could not fetch a new one.\n | {\n state: \"notRefetching\";\n config: AuthConfig;\n };\n\n/**\n * Handles the state transitions for auth. The server is the source\n * of truth.\n */\nexport class AuthenticationManager {\n private authState: AuthState = { state: \"noAuth\" };\n // Used to detect races involving `setConfig` calls\n // while a token is being fetched.\n private configVersion = 0;\n // Shared by the BaseClient so that the auth manager can easily inspect it\n private readonly syncState: LocalSyncState;\n // Passed down by BaseClient, sends a message to the server\n private readonly authenticate: (token: string) => IdentityVersion;\n private readonly stopSocket: () => Promise<void>;\n private readonly tryRestartSocket: () => void;\n private readonly pauseSocket: () => void;\n private readonly resumeSocket: () => void;\n // Passed down by BaseClient, sends a message to the server\n private readonly clearAuth: () => void;\n private readonly logger: Logger;\n private readonly refreshTokenLeewaySeconds: number;\n // Number of times we have attempted to confirm the latest token. We retry up\n // to `MAX_TOKEN_CONFIRMATION_ATTEMPTS` times.\n private tokenConfirmationAttempts = 0;\n constructor(\n syncState: LocalSyncState,\n callbacks: {\n authenticate: (token: string) => IdentityVersion;\n stopSocket: () => Promise<void>;\n tryRestartSocket: () => void;\n pauseSocket: () => void;\n resumeSocket: () => void;\n clearAuth: () => void;\n },\n config: {\n refreshTokenLeewaySeconds: number;\n logger: Logger;\n },\n ) {\n this.syncState = syncState;\n this.authenticate = callbacks.authenticate;\n this.stopSocket = callbacks.stopSocket;\n this.tryRestartSocket = callbacks.tryRestartSocket;\n this.pauseSocket = callbacks.pauseSocket;\n this.resumeSocket = callbacks.resumeSocket;\n this.clearAuth = callbacks.clearAuth;\n this.logger = config.logger;\n this.refreshTokenLeewaySeconds = config.refreshTokenLeewaySeconds;\n }\n\n async setConfig(\n fetchToken: AuthTokenFetcher,\n onChange: (isAuthenticated: boolean) => void,\n ) {\n this.resetAuthState();\n this._logVerbose(\"pausing WS for auth token fetch\");\n this.pauseSocket();\n const token = await this.fetchTokenAndGuardAgainstRace(fetchToken, {\n forceRefreshToken: false,\n });\n if (token.isFromOutdatedConfig) {\n return;\n }\n if (token.value) {\n this.setAuthState({\n state: \"waitingForServerConfirmationOfCachedToken\",\n config: { fetchToken, onAuthChange: onChange },\n hasRetried: false,\n });\n this.authenticate(token.value);\n } else {\n this.setAuthState({\n state: \"initialRefetch\",\n config: { fetchToken, onAuthChange: onChange },\n });\n // Try again with `forceRefreshToken: true`\n await this.refetchToken();\n }\n this._logVerbose(\"resuming WS after auth token fetch\");\n this.resumeSocket();\n }\n\n onTransition(serverMessage: Transition) {\n if (\n !this.syncState.isCurrentOrNewerAuthVersion(\n serverMessage.endVersion.identity,\n )\n ) {\n // This is a stale transition - client has moved on to\n // a newer auth version.\n return;\n }\n if (\n serverMessage.endVersion.identity <= serverMessage.startVersion.identity\n ) {\n // This transition did not change auth - it is not a response to Authenticate.\n return;\n }\n\n this._logVerbose(\n `auth state is ${this.authState.state} when handling transition`,\n );\n\n // This transition advanced the auth version, which means the token used was valid\n // and the client and server auth states are in sync.\n this.syncState.markAuthCompletion();\n\n if (this.authState.state === \"waitingForServerConfirmationOfCachedToken\") {\n this._logVerbose(\"server confirmed auth token is valid\");\n void this.refetchToken();\n this.authState.config.onAuthChange(true);\n return;\n }\n if (this.authState.state === \"waitingForServerConfirmationOfFreshToken\") {\n this._logVerbose(\"server confirmed new auth token is valid\");\n this.scheduleTokenRefetch(this.authState.token);\n this.tokenConfirmationAttempts = 0;\n if (!this.authState.hadAuth) {\n this.authState.config.onAuthChange(true);\n }\n }\n }\n\n onAuthError(serverMessage: AuthError) {\n // If the AuthError is not due to updating the token, and we're currently\n // waiting on the result of a token update, ignore.\n if (\n serverMessage.authUpdateAttempted === false &&\n (this.authState.state === \"waitingForServerConfirmationOfFreshToken\" ||\n this.authState.state === \"waitingForServerConfirmationOfCachedToken\")\n ) {\n this._logVerbose(\"ignoring non-auth token expired error\");\n return;\n }\n const { baseVersion } = serverMessage;\n // Versioned AuthErrors are ignored if the client advanced to\n // a newer auth identity\n // Error are reporting the previous version, since the server\n // didn't advance, hence `+ 1`.\n if (!this.syncState.isCurrentOrNewerAuthVersion(baseVersion + 1)) {\n this._logVerbose(\"ignoring auth error for previous auth attempt\");\n return;\n }\n void this.tryToReauthenticate(serverMessage);\n return;\n }\n\n // This is similar to `refetchToken` defined below, in fact we\n // don't represent them as different states, but it is different\n // in that we pause the WebSocket so that mutations\n // don't retry with bad auth.\n private async tryToReauthenticate(serverMessage: AuthError) {\n this._logVerbose(`attempting to reauthenticate: ${serverMessage.error}`);\n if (\n // No way to fetch another token, kaboom\n this.authState.state === \"noAuth\" ||\n // We failed on a fresh token. After a small number of retries, we give up\n // and clear the auth state to avoid infinite retries.\n (this.authState.state === \"waitingForServerConfirmationOfFreshToken\" &&\n this.tokenConfirmationAttempts >= MAX_TOKEN_CONFIRMATION_ATTEMPTS)\n ) {\n this.logger.error(\n `Failed to authenticate: \"${serverMessage.error}\", check your server auth config`,\n );\n if (this.syncState.hasAuth()) {\n this.syncState.clearAuth();\n }\n if (this.authState.state !== \"noAuth\") {\n this.setAndReportAuthFailed(this.authState.config.onAuthChange);\n }\n return;\n }\n if (this.authState.state === \"waitingForServerConfirmationOfFreshToken\") {\n this.tokenConfirmationAttempts++;\n this._logVerbose(\n `retrying reauthentication, ${MAX_TOKEN_CONFIRMATION_ATTEMPTS - this.tokenConfirmationAttempts} attempts remaining`,\n );\n }\n\n await this.stopSocket();\n const token = await this.fetchTokenAndGuardAgainstRace(\n this.authState.config.fetchToken,\n {\n forceRefreshToken: true,\n },\n );\n if (token.isFromOutdatedConfig) {\n return;\n }\n\n if (token.value && this.syncState.isNewAuth(token.value)) {\n this.authenticate(token.value);\n this.setAuthState({\n state: \"waitingForServerConfirmationOfFreshToken\",\n config: this.authState.config,\n token: token.value,\n hadAuth:\n this.authState.state === \"notRefetching\" ||\n this.authState.state === \"waitingForScheduledRefetch\",\n });\n } else {\n this._logVerbose(\"reauthentication failed, could not fetch a new token\");\n if (this.syncState.hasAuth()) {\n this.syncState.clearAuth();\n }\n this.setAndReportAuthFailed(this.authState.config.onAuthChange);\n }\n this.tryRestartSocket();\n }\n\n // Force refetch the token and schedule another refetch\n // before the token expires - an active client should never\n // need to reauthenticate.\n private async refetchToken() {\n if (this.authState.state === \"noAuth\") {\n return;\n }\n this._logVerbose(\"refetching auth token\");\n const token = await this.fetchTokenAndGuardAgainstRace(\n this.authState.config.fetchToken,\n {\n forceRefreshToken: true,\n },\n );\n if (token.isFromOutdatedConfig) {\n return;\n }\n\n if (token.value) {\n if (this.syncState.isNewAuth(token.value)) {\n this.setAuthState({\n state: \"waitingForServerConfirmationOfFreshToken\",\n hadAuth: this.syncState.hasAuth(),\n token: token.value,\n config: this.authState.config,\n });\n this.authenticate(token.value);\n } else {\n this.setAuthState({\n state: \"notRefetching\",\n config: this.authState.config,\n });\n }\n } else {\n this._logVerbose(\"refetching token failed\");\n if (this.syncState.hasAuth()) {\n this.clearAuth();\n }\n this.setAndReportAuthFailed(this.authState.config.onAuthChange);\n }\n // Restart in case this refetch was triggered via schedule during\n // a reauthentication attempt.\n this._logVerbose(\n \"restarting WS after auth token fetch (if currently stopped)\",\n );\n this.tryRestartSocket();\n }\n\n private scheduleTokenRefetch(token: string) {\n if (this.authState.state === \"noAuth\") {\n return;\n }\n const decodedToken = this.decodeToken(token);\n if (!decodedToken) {\n // This is no longer really possible, because\n // we wait on server response before scheduling token refetch,\n // and the server currently requires JWT tokens.\n this.logger.error(\n \"Auth token is not a valid JWT, cannot refetch the token\",\n );\n return;\n }\n // iat: issued at time, UTC seconds timestamp at which the JWT was issued\n // exp: expiration time, UTC seconds timestamp at which the JWT will expire\n const { iat, exp } = decodedToken as { iat?: number; exp?: number };\n if (!iat || !exp) {\n this.logger.error(\n \"Auth token does not have required fields, cannot refetch the token\",\n );\n return;\n }\n // Because the client and server clocks may be out of sync,\n // we only know that the token will expire after `exp - iat`,\n // and since we just fetched a fresh one we know when that\n // will happen.\n const tokenValiditySeconds = exp - iat;\n if (tokenValiditySeconds <= 2) {\n this.logger.error(\n \"Auth token does not live long enough, cannot refetch the token\",\n );\n return;\n }\n // Attempt to refresh the token `refreshTokenLeewaySeconds` before it expires,\n // or immediately if the token is already expiring soon.\n let delay = Math.min(\n MAXIMUM_REFRESH_DELAY,\n (tokenValiditySeconds - this.refreshTokenLeewaySeconds) * 1000,\n );\n if (delay <= 0) {\n // Refetch immediately, but this might be due to configuring a `refreshTokenLeewaySeconds`\n // that is too large compared to the token's actual lifetime.\n this.logger.warn(\n `Refetching auth token immediately, configured leeway ${this.refreshTokenLeewaySeconds}s is larger than the token's lifetime ${tokenValiditySeconds}s`,\n );\n delay = 0;\n }\n const refetchTokenTimeoutId = setTimeout(() => {\n this._logVerbose(\"running scheduled token refetch\");\n void this.refetchToken();\n }, delay);\n this.setAuthState({\n state: \"waitingForScheduledRefetch\",\n refetchTokenTimeoutId,\n config: this.authState.config,\n });\n this._logVerbose(\n `scheduled preemptive auth token refetching in ${delay}ms`,\n );\n }\n\n // Protects against simultaneous calls to `setConfig`\n // while we're fetching a token\n private async fetchTokenAndGuardAgainstRace(\n fetchToken: AuthTokenFetcher,\n fetchArgs: {\n forceRefreshToken: boolean;\n },\n ) {\n const originalConfigVersion = ++this.configVersion;\n this._logVerbose(\n `fetching token with config version ${originalConfigVersion}`,\n );\n const token = await fetchToken(fetchArgs);\n if (this.configVersion !== originalConfigVersion) {\n // This is a stale config\n this._logVerbose(\n `stale config version, expected ${originalConfigVersion}, got ${this.configVersion}`,\n );\n return { isFromOutdatedConfig: true };\n }\n return { isFromOutdatedConfig: false, value: token };\n }\n\n stop() {\n this.resetAuthState();\n // Bump this in case we are mid-token-fetch when we get stopped\n this.configVersion++;\n this._logVerbose(`config version bumped to ${this.configVersion}`);\n }\n\n private setAndReportAuthFailed(\n onAuthChange: (authenticated: boolean) => void,\n ) {\n onAuthChange(false);\n this.resetAuthState();\n }\n\n private resetAuthState() {\n this.setAuthState({ state: \"noAuth\" });\n }\n\n private setAuthState(newAuth: AuthState) {\n const authStateForLog =\n newAuth.state === \"waitingForServerConfirmationOfFreshToken\"\n ? {\n hadAuth: newAuth.hadAuth,\n state: newAuth.state,\n token: `...${newAuth.token.slice(-7)}`,\n }\n : { state: newAuth.state };\n this._logVerbose(\n `setting auth state to ${JSON.stringify(authStateForLog)}`,\n );\n switch (newAuth.state) {\n case \"waitingForScheduledRefetch\":\n case \"notRefetching\":\n case \"noAuth\":\n this.tokenConfirmationAttempts = 0;\n break;\n case \"waitingForServerConfirmationOfFreshToken\":\n case \"waitingForServerConfirmationOfCachedToken\":\n case \"initialRefetch\":\n break;\n default: {\n newAuth satisfies never;\n }\n }\n if (this.authState.state === \"waitingForScheduledRefetch\") {\n // TODO: this side-effect would be better situated with scheduling refetch\n clearTimeout(this.authState.refetchTokenTimeoutId);\n }\n this.authState = newAuth;\n }\n\n private decodeToken(token: string) {\n try {\n return jwtDecode(token);\n } catch (e) {\n this._logVerbose(\n `Error decoding token: ${e instanceof Error ? e.message : \"Unknown error\"}`,\n );\n return null;\n }\n }\n\n private _logVerbose(message: string) {\n this.logger.logVerbose(`${message} [v${this.configVersion}]`);\n }\n}\n", "// Marks share a global namespace with other developer code.\nconst markNames = [\n \"convexClientConstructed\",\n \"convexWebSocketOpen\",\n \"convexFirstMessageReceived\",\n] as const;\nexport type MarkName = (typeof markNames)[number];\n\n// Mark details are not reported to the server.\ntype MarkDetail = {\n sessionId: string;\n};\n\n// `PerformanceMark`s are efficient and show up in browser's performance\n// timeline. They can be cleared with `performance.clearMarks()`.\n// This is a memory leak, but a worthwhile one: automatic\n// cleanup would make in-browser debugging more difficult.\nexport function mark(name: MarkName, sessionId: string) {\n const detail: MarkDetail = { sessionId };\n // `performance` APIs exists in browsers, Node.js, Deno, and more but it\n // is not required by the Convex client.\n if (typeof performance === \"undefined\" || !performance.mark) return;\n performance.mark(name, { detail });\n}\n\n// `PerfomanceMark` has a built-in toJSON() but the return type varies\n// between implementations, e.g. Node.js returns details but Chrome does not.\nfunction performanceMarkToJson(mark: PerformanceMark): MarkJson {\n // Remove \"convex\" prefix\n let name = mark.name.slice(\"convex\".length);\n // lowercase the first letter\n name = name.charAt(0).toLowerCase() + name.slice(1);\n return {\n name,\n startTime: mark.startTime,\n };\n}\n\n// Similar to the return type of `PerformanceMark.toJson()`.\nexport type MarkJson = {\n name: string;\n // `startTime` is in milliseconds since the time origin like `performance.now()`.\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#the_time_origin\n startTime: number;\n};\n\nexport function getMarksReport(sessionId: string): MarkJson[] {\n if (typeof performance === \"undefined\" || !performance.getEntriesByName) {\n return [];\n }\n const allMarks: PerformanceMark[] = [];\n for (const name of markNames) {\n const marks = (\n performance\n .getEntriesByName(name)\n .filter((entry) => entry.entryType === \"mark\") as PerformanceMark[]\n ).filter((mark) => mark.detail.sessionId === sessionId);\n allMarks.push(...marks);\n }\n return allMarks.map(performanceMarkToJson);\n}\n", "/**\n * BaseConvexClient should not be used directly and does not provide a stable\n * interface. It is a \"Base\" client not because it expects to be inherited from\n * but because other clients are built around it.\n *\n * BaseConvexClient is not Convex Function type-aware: it deals\n * with queries as functions that return Value, not the specific value.\n * Use a higher-level library to get types.\n */\nimport { version } from \"../../index.js\";\nimport { convexToJson, Value } from \"../../values/index.js\";\nimport {\n createHybridErrorStacktrace,\n forwardData,\n instantiateDefaultLogger,\n instantiateNoopLogger,\n logFatalError,\n Logger,\n} from \"../logging.js\";\nimport { LocalSyncState } from \"./local_state.js\";\nimport { RequestManager } from \"./request_manager.js\";\nimport {\n OptimisticLocalStore,\n OptimisticUpdate,\n} from \"./optimistic_updates.js\";\nimport {\n OptimisticQueryResults,\n QueryResultsMap,\n} from \"./optimistic_updates_impl.js\";\nimport {\n ActionRequest,\n MutationRequest,\n QueryId,\n QueryJournal,\n ServerMessage,\n RequestId,\n TS,\n UserIdentityAttributes,\n} from \"./protocol.js\";\nimport { RemoteQuerySet } from \"./remote_query_set.js\";\nimport { QueryToken, serializePathAndArgs } from \"./udf_path_utils.js\";\nimport { ReconnectMetadata, WebSocketManager } from \"./web_socket_manager.js\";\nimport { newSessionId } from \"./session.js\";\nimport { FunctionResult } from \"./function_result.js\";\nimport {\n AuthenticationManager,\n AuthTokenFetcher,\n} from \"./authentication_manager.js\";\nexport { type AuthTokenFetcher } from \"./authentication_manager.js\";\nimport { getMarksReport, mark, MarkName } from \"./metrics.js\";\nimport { parseArgs, validateDeploymentUrl } from \"../../common/index.js\";\nimport { ConvexError } from \"../../values/errors.js\";\nimport { jwtDecode } from \"../../vendor/jwt-decode/index.js\";\n\n/**\n * Options for {@link BaseConvexClient}.\n *\n * @public\n */\nexport interface BaseConvexClientOptions {\n /**\n * Whether to prompt the user if they have unsaved changes pending\n * when navigating away or closing a web page.\n *\n * This is only possible when the `window` object exists, i.e. in a browser.\n *\n * The default value is `true` in browsers.\n */\n unsavedChangesWarning?: boolean;\n /**\n * Specifies an alternate\n * [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)\n * constructor to use for client communication with the Convex cloud.\n * The default behavior is to use `WebSocket` from the global environment.\n */\n webSocketConstructor?: typeof WebSocket;\n /**\n * Adds additional logging for debugging purposes.\n *\n * The default value is `false`.\n */\n verbose?: boolean;\n /**\n * A logger, `true`, or `false`. If not provided or `true`, logs to the console.\n * If `false`, logs are not printed anywhere.\n *\n * You can construct your own logger to customize logging to log elsewhere.\n * A logger is an object with 4 methods: log(), warn(), error(), and logVerbose().\n * These methods can receive multiple arguments of any types, like console.log().\n */\n logger?: Logger | boolean;\n /**\n * Sends additional metrics to Convex for debugging purposes.\n *\n * The default value is `false`.\n */\n reportDebugInfoToConvex?: boolean;\n /**\n * This API is experimental: it may change or disappear.\n *\n * A function to call on receiving abnormal WebSocket close messages from the\n * connected Convex deployment. The content of these messages is not stable,\n * it is an implementation detail that may change.\n *\n * Consider this API an observability stopgap until higher level codes with\n * recommendations on what to do are available, which could be a more stable\n * interface instead of `string`.\n *\n * Check `connectionState` for more quantitative metrics about connection status.\n */\n onServerDisconnectError?: (message: string) => void;\n /**\n * Skip validating that the Convex deployment URL looks like\n * `https://happy-animal-123.convex.cloud` or localhost.\n *\n * This can be useful if running a self-hosted Convex backend that uses a different\n * URL.\n *\n * The default value is `false`\n */\n skipConvexDeploymentUrlCheck?: boolean;\n /**\n * If using auth, the number of seconds before a token expires that we should refresh it.\n *\n * The default value is `10`.\n */\n authRefreshTokenLeewaySeconds?: number;\n /**\n * This API is experimental: it may change or disappear.\n *\n * Whether query, mutation, and action requests should be held back\n * until the first auth token can be sent.\n *\n * Opting into this behavior works well for pages that should\n * only be viewed by authenticated clients.\n *\n * Defaults to false, not waiting for an auth token.\n */\n expectAuth?: boolean;\n}\n\n/**\n * State describing the client's connection with the Convex backend.\n *\n * @public\n */\nexport type ConnectionState = {\n hasInflightRequests: boolean;\n isWebSocketConnected: boolean;\n timeOfOldestInflightRequest: Date | null;\n /**\n * True if the client has ever opened a WebSocket to the \"ready\" state.\n */\n hasEverConnected: boolean;\n /**\n * The number of times this client has connected to the Convex backend.\n *\n * A number of things can cause the client to reconnect -- server errors,\n * bad internet, auth expiring. But this number being high is an indication\n * that the client is having trouble keeping a stable connection.\n */\n connectionCount: number;\n /**\n * The number of times this client has tried (and failed) to connect to the Convex backend.\n */\n connectionRetries: number;\n /**\n * The number of mutations currently in flight.\n */\n inflightMutations: number;\n /**\n * The number of actions currently in flight.\n */\n inflightActions: number;\n};\n\n/**\n * Options for {@link BaseConvexClient.subscribe}.\n *\n * @public\n */\nexport interface SubscribeOptions {\n /**\n * An (optional) journal produced from a previous execution of this query\n * function.\n *\n * If there is an existing subscription to a query function with the same\n * name and arguments, this journal will have no effect.\n */\n journal?: QueryJournal;\n\n /**\n * @internal\n */\n componentPath?: string | undefined;\n}\n\n/**\n * Options for {@link BaseConvexClient.mutation}.\n *\n * @public\n */\nexport interface MutationOptions {\n /**\n * An optimistic update to apply along with this mutation.\n *\n * An optimistic update locally updates queries while a mutation is pending.\n * Once the mutation completes, the update will be rolled back.\n */\n optimisticUpdate?: OptimisticUpdate<any> | undefined;\n}\n\n/**\n * Type describing updates to a query within a `Transition`.\n *\n * @public\n */\nexport type QueryModification =\n // `undefined` generally comes from an optimistic update setting the query to be loading\n { kind: \"Updated\"; result: FunctionResult | undefined } | { kind: \"Removed\" };\n\n/**\n * Object describing a transition passed into the `onTransition` handler.\n *\n * These can be from receiving a transition from the server, or from applying an\n * optimistic update locally.\n *\n * @public\n */\nexport type Transition = {\n queries: Array<{ token: QueryToken; modification: QueryModification }>;\n reflectedMutations: Array<{ requestId: RequestId; result: FunctionResult }>;\n timestamp: TS;\n};\n\n/**\n * Low-level client for directly integrating state management libraries\n * with Convex.\n *\n * Most developers should use higher level clients, like\n * the {@link ConvexHttpClient} or the React hook based {@link react.ConvexReactClient}.\n *\n * @public\n */\nexport class BaseConvexClient {\n private readonly address: string;\n private readonly state: LocalSyncState;\n private readonly requestManager: RequestManager;\n private readonly webSocketManager: WebSocketManager;\n private readonly authenticationManager: AuthenticationManager;\n private remoteQuerySet: RemoteQuerySet;\n private readonly optimisticQueryResults: OptimisticQueryResults;\n private _transitionHandlerCounter = 0;\n private _nextRequestId: RequestId;\n private _onTransitionFns: Map<number, (transition: Transition) => void> =\n new Map();\n private readonly _sessionId: string;\n private firstMessageReceived = false;\n private readonly debug: boolean;\n private readonly logger: Logger;\n private maxObservedTimestamp: TS | undefined;\n private connectionStateSubscribers = new Map<\n number,\n (connectionState: ConnectionState) => void\n >();\n private nextConnectionStateSubscriberId: number = 0;\n private _lastPublishedConnectionState: ConnectionState | undefined;\n\n /**\n * @param address - The url of your Convex deployment, often provided\n * by an environment variable. E.g. `https://small-mouse-123.convex.cloud`.\n * @param onTransition - A callback receiving an array of query tokens\n * corresponding to query results that have changed -- additional handlers\n * can be added via `addOnTransitionHandler`.\n * @param options - See {@link BaseConvexClientOptions} for a full description.\n */\n constructor(\n address: string,\n onTransition: (updatedQueries: QueryToken[]) => void,\n options?: BaseConvexClientOptions,\n ) {\n if (typeof address === \"object\") {\n throw new Error(\n \"Passing a ClientConfig object is no longer supported. Pass the URL of the Convex deployment as a string directly.\",\n );\n }\n if (options?.skipConvexDeploymentUrlCheck !== true) {\n validateDeploymentUrl(address);\n }\n options = { ...options };\n const authRefreshTokenLeewaySeconds =\n options.authRefreshTokenLeewaySeconds ?? 10;\n let webSocketConstructor = options.webSocketConstructor;\n if (!webSocketConstructor && typeof WebSocket === \"undefined\") {\n throw new Error(\n \"No WebSocket global variable defined! To use Convex in an environment without WebSocket try the HTTP client: https://docs.convex.dev/api/classes/browser.ConvexHttpClient\",\n );\n }\n webSocketConstructor = webSocketConstructor || WebSocket;\n this.debug = options.reportDebugInfoToConvex ?? false;\n this.address = address;\n this.logger =\n options.logger === false\n ? instantiateNoopLogger({ verbose: options.verbose ?? false })\n : options.logger !== true && options.logger\n ? options.logger\n : instantiateDefaultLogger({ verbose: options.verbose ?? false });\n // Substitute http(s) with ws(s)\n const i = address.search(\"://\");\n if (i === -1) {\n throw new Error(\"Provided address was not an absolute URL.\");\n }\n const origin = address.substring(i + 3); // move past the double slash\n const protocol = address.substring(0, i);\n let wsProtocol;\n if (protocol === \"http\") {\n wsProtocol = \"ws\";\n } else if (protocol === \"https\") {\n wsProtocol = \"wss\";\n } else {\n throw new Error(`Unknown parent protocol ${protocol}`);\n }\n const wsUri = `${wsProtocol}://${origin}/api/${version}/sync`;\n\n this.state = new LocalSyncState();\n this.remoteQuerySet = new RemoteQuerySet(\n (queryId) => this.state.queryPath(queryId),\n this.logger,\n );\n this.requestManager = new RequestManager(\n this.logger,\n this.markConnectionStateDirty,\n );\n\n // This is a callback for AuthenticationManager (which can't call\n // this synchronously, the callback wouldn't work) so the initial\n // pause for expectAuth we call it at the end of this constructor.\n const pauseSocket = () => {\n this.webSocketManager.pause();\n this.state.pause();\n };\n this.authenticationManager = new AuthenticationManager(\n this.state,\n {\n authenticate: (token) => {\n const message = this.state.setAuth(token);\n this.webSocketManager.sendMessage(message);\n return message.baseVersion;\n },\n stopSocket: () => this.webSocketManager.stop(),\n tryRestartSocket: () => this.webSocketManager.tryRestart(),\n pauseSocket,\n resumeSocket: () => this.webSocketManager.resume(),\n clearAuth: () => {\n this.clearAuth();\n },\n },\n {\n logger: this.logger,\n refreshTokenLeewaySeconds: authRefreshTokenLeewaySeconds,\n },\n );\n this.optimisticQueryResults = new OptimisticQueryResults();\n this.addOnTransitionHandler((transition) => {\n onTransition(transition.queries.map((q) => q.token));\n });\n this._nextRequestId = 0;\n this._sessionId = newSessionId();\n\n const { unsavedChangesWarning } = options;\n if (\n typeof window === \"undefined\" ||\n typeof window.addEventListener === \"undefined\"\n ) {\n if (unsavedChangesWarning === true) {\n throw new Error(\n \"unsavedChangesWarning requested, but window.addEventListener not found! Remove {unsavedChangesWarning: true} from Convex client options.\",\n );\n }\n } else if (unsavedChangesWarning !== false) {\n // Listen for tab close events and notify the user on unsaved changes.\n window.addEventListener(\"beforeunload\", (e) => {\n if (this.requestManager.hasIncompleteRequests()) {\n // There are 3 different ways to trigger this pop up so just try all of\n // them.\n\n e.preventDefault();\n // This confirmation message doesn't actually appear in most modern\n // browsers but we tried.\n const confirmationMessage =\n \"Are you sure you want to leave? Your changes may not be saved.\";\n // Recommended method for legacy (IE) browsers.\n // casts to avoid deprecation notices\n ((e || (window as any).event) as any).returnValue =\n confirmationMessage;\n return confirmationMessage;\n }\n });\n }\n\n this.webSocketManager = new WebSocketManager(\n wsUri,\n {\n onOpen: (reconnectMetadata: ReconnectMetadata) => {\n // We have a new WebSocket!\n this.mark(\"convexWebSocketOpen\");\n this.webSocketManager.sendMessage({\n ...reconnectMetadata,\n type: \"Connect\",\n sessionId: this._sessionId,\n maxObservedTimestamp: this.maxObservedTimestamp,\n });\n\n // Throw out our remote query, reissue queries\n // and outstanding mutations, and reauthenticate.\n this.remoteQuerySet = new RemoteQuerySet(\n (queryId) => this.state.queryPath(queryId),\n this.logger,\n );\n const [querySetModification, authModification] = this.state.restart();\n if (authModification) {\n this.webSocketManager.sendMessage(authModification);\n }\n this.webSocketManager.sendMessage(querySetModification);\n for (const message of this.requestManager.restart()) {\n this.webSocketManager.sendMessage(message);\n }\n },\n onResume: () => {\n const [querySetModification, authModification] = this.state.resume();\n if (authModification) {\n this.webSocketManager.sendMessage(authModification);\n }\n if (querySetModification) {\n this.webSocketManager.sendMessage(querySetModification);\n }\n for (const message of this.requestManager.resume()) {\n this.webSocketManager.sendMessage(message);\n }\n },\n onMessage: (serverMessage: ServerMessage) => {\n // Metrics events grow linearly with reconnection attempts so this\n // conditional prevents n^2 metrics reporting.\n if (!this.firstMessageReceived) {\n this.firstMessageReceived = true;\n this.mark(\"convexFirstMessageReceived\");\n this.reportMarks();\n }\n switch (serverMessage.type) {\n case \"Transition\": {\n this.observedTimestamp(serverMessage.endVersion.ts);\n this.authenticationManager.onTransition(serverMessage);\n this.remoteQuerySet.transition(serverMessage);\n this.state.transition(serverMessage);\n const completedRequests = this.requestManager.removeCompleted(\n this.remoteQuerySet.timestamp(),\n );\n this.notifyOnQueryResultChanges(completedRequests);\n break;\n }\n case \"MutationResponse\": {\n if (serverMessage.success) {\n this.observedTimestamp(serverMessage.ts);\n }\n const completedMutationInfo =\n this.requestManager.onResponse(serverMessage);\n if (completedMutationInfo !== null) {\n this.notifyOnQueryResultChanges(\n new Map([\n [\n completedMutationInfo.requestId,\n completedMutationInfo.result,\n ],\n ]),\n );\n }\n break;\n }\n case \"ActionResponse\": {\n this.requestManager.onResponse(serverMessage);\n break;\n }\n case \"AuthError\": {\n this.authenticationManager.onAuthError(serverMessage);\n break;\n }\n case \"FatalError\": {\n const error = logFatalError(this.logger, serverMessage.error);\n void this.webSocketManager.terminate();\n throw error;\n }\n default: {\n serverMessage satisfies never;\n }\n }\n\n return {\n hasSyncedPastLastReconnect: this.hasSyncedPastLastReconnect(),\n };\n },\n onServerDisconnectError: options.onServerDisconnectError,\n },\n webSocketConstructor,\n this.logger,\n this.markConnectionStateDirty,\n this.debug,\n );\n this.mark(\"convexClientConstructed\");\n\n // Begin client in a paused state waiting for an auth token.\n if (options.expectAuth) {\n pauseSocket();\n }\n }\n\n /**\n * Return true if there is outstanding work from prior to the time of the most recent restart.\n * This indicates that the client has not proven itself to have gotten past the issue that\n * potentially led to the restart. Use this to influence when to reset backoff after a failure.\n */\n private hasSyncedPastLastReconnect() {\n const hasSyncedPastLastReconnect =\n this.requestManager.hasSyncedPastLastReconnect() &&\n this.state.hasSyncedPastLastReconnect();\n return hasSyncedPastLastReconnect;\n }\n\n private observedTimestamp(observedTs: TS) {\n if (\n this.maxObservedTimestamp === undefined ||\n this.maxObservedTimestamp.lessThanOrEqual(observedTs)\n ) {\n this.maxObservedTimestamp = observedTs;\n }\n }\n\n getMaxObservedTimestamp() {\n return this.maxObservedTimestamp;\n }\n\n /**\n * Compute the current query results based on the remoteQuerySet and the\n * current optimistic updates and call `onTransition` for all the changed\n * queries.\n *\n * @param completedMutations - A set of mutation IDs whose optimistic updates\n * are no longer needed.\n */\n private notifyOnQueryResultChanges(\n completedRequests: Map<RequestId, FunctionResult>,\n ) {\n const remoteQueryResults: Map<QueryId, FunctionResult> =\n this.remoteQuerySet.remoteQueryResults();\n const queryTokenToValue: QueryResultsMap = new Map();\n for (const [queryId, result] of remoteQueryResults) {\n const queryToken = this.state.queryToken(queryId);\n // It's possible that we've already unsubscribed to this query but\n // the server hasn't learned about that yet. If so, ignore this one.\n\n if (queryToken !== null) {\n const query = {\n result,\n udfPath: this.state.queryPath(queryId)!,\n args: this.state.queryArgs(queryId)!,\n };\n queryTokenToValue.set(queryToken, query);\n }\n }\n\n // Query tokens that are new (because of new server results or new local optimistic updates)\n // or differ from old values (because of changes from local optimistic updates or new results\n // from the server).\n const changedQueryTokens =\n this.optimisticQueryResults.ingestQueryResultsFromServer(\n queryTokenToValue,\n new Set(completedRequests.keys()),\n );\n\n this.handleTransition({\n queries: changedQueryTokens.map((token) => {\n const optimisticResult =\n this.optimisticQueryResults.rawQueryResult(token);\n return {\n token,\n modification: {\n kind: \"Updated\" as const,\n result: optimisticResult,\n },\n };\n }),\n reflectedMutations: Array.from(completedRequests).map(\n ([requestId, result]) => ({\n requestId,\n result,\n }),\n ),\n timestamp: this.remoteQuerySet.timestamp(),\n });\n }\n\n private handleTransition(transition: Transition) {\n for (const fn of this._onTransitionFns.values()) {\n fn(transition);\n }\n }\n\n /**\n * Add a handler that will be called on a transition.\n *\n * Any external side effects (e.g. setting React state) should be handled here.\n *\n * @param fn\n *\n * @returns\n */\n addOnTransitionHandler(fn: (transition: Transition) => void) {\n const id = this._transitionHandlerCounter++;\n this._onTransitionFns.set(id, fn);\n return () => this._onTransitionFns.delete(id);\n }\n\n /**\n * Get the current JWT auth token and decoded claims.\n */\n getCurrentAuthClaims():\n | { token: string; decoded: Record<string, any> }\n | undefined {\n const authToken = this.state.getAuth();\n let decoded: Record<string, any> = {};\n if (authToken && authToken.tokenType === \"User\") {\n try {\n decoded = authToken ? jwtDecode(authToken.value) : {};\n } catch {\n decoded = {};\n }\n } else {\n return undefined;\n }\n return { token: authToken.value, decoded };\n }\n\n /**\n * Set the authentication token to be used for subsequent queries and mutations.\n * `fetchToken` will be called automatically again if a token expires.\n * `fetchToken` should return `null` if the token cannot be retrieved, for example\n * when the user's rights were permanently revoked.\n * @param fetchToken - an async function returning the JWT-encoded OpenID Connect Identity Token\n * @param onChange - a callback that will be called when the authentication status changes\n */\n setAuth(\n fetchToken: AuthTokenFetcher,\n onChange: (isAuthenticated: boolean) => void,\n ) {\n void this.authenticationManager.setConfig(fetchToken, onChange);\n }\n\n hasAuth() {\n return this.state.hasAuth();\n }\n\n /** @internal */\n setAdminAuth(value: string, fakeUserIdentity?: UserIdentityAttributes) {\n const message = this.state.setAdminAuth(value, fakeUserIdentity);\n this.webSocketManager.sendMessage(message);\n }\n\n clearAuth() {\n const message = this.state.clearAuth();\n this.webSocketManager.sendMessage(message);\n }\n\n /**\n * Subscribe to a query function.\n *\n * Whenever this query's result changes, the `onTransition` callback\n * passed into the constructor will be called.\n *\n * @param name - The name of the query.\n * @param args - An arguments object for the query. If this is omitted, the\n * arguments will be `{}`.\n * @param options - A {@link SubscribeOptions} options object for this query.\n\n * @returns An object containing a {@link QueryToken} corresponding to this\n * query and an `unsubscribe` callback.\n */\n subscribe(\n name: string,\n args?: Record<string, Value>,\n options?: SubscribeOptions,\n ): { queryToken: QueryToken; unsubscribe: () => void } {\n const argsObject = parseArgs(args);\n\n const { modification, queryToken, unsubscribe } = this.state.subscribe(\n name,\n argsObject,\n options?.journal,\n options?.componentPath,\n );\n if (modification !== null) {\n this.webSocketManager.sendMessage(modification);\n }\n return {\n queryToken,\n unsubscribe: () => {\n const modification = unsubscribe();\n if (modification) {\n this.webSocketManager.sendMessage(modification);\n }\n },\n };\n }\n\n /**\n * A query result based only on the current, local state.\n *\n * The only way this will return a value is if we're already subscribed to the\n * query or its value has been set optimistically.\n */\n localQueryResult(\n udfPath: string,\n args?: Record<string, Value>,\n ): Value | undefined {\n const argsObject = parseArgs(args);\n const queryToken = serializePathAndArgs(udfPath, argsObject);\n return this.optimisticQueryResults.queryResult(queryToken);\n }\n\n /**\n * Get query result by query token based on current, local state\n *\n * The only way this will return a value is if we're already subscribed to the\n * query or its value has been set optimistically.\n *\n * @internal\n */\n localQueryResultByToken(queryToken: QueryToken): Value | undefined {\n return this.optimisticQueryResults.queryResult(queryToken);\n }\n\n /**\n * Whether local query result is available for a token.\n *\n * This method does not throw if the result is an error.\n *\n * @internal\n */\n hasLocalQueryResultByToken(queryToken: QueryToken): boolean {\n return this.optimisticQueryResults.hasQueryResult(queryToken);\n }\n\n /**\n * @internal\n */\n localQueryLogs(\n udfPath: string,\n args?: Record<string, Value>,\n ): string[] | undefined {\n const argsObject = parseArgs(args);\n const queryToken = serializePathAndArgs(udfPath, argsObject);\n return this.optimisticQueryResults.queryLogs(queryToken);\n }\n\n /**\n * Retrieve the current {@link QueryJournal} for this query function.\n *\n * If we have not yet received a result for this query, this will be `undefined`.\n *\n * @param name - The name of the query.\n * @param args - The arguments object for this query.\n * @returns The query's {@link QueryJournal} or `undefined`.\n */\n queryJournal(\n name: string,\n args?: Record<string, Value>,\n ): QueryJournal | undefined {\n const argsObject = parseArgs(args);\n const queryToken = serializePathAndArgs(name, argsObject);\n return this.state.queryJournal(queryToken);\n }\n\n /**\n * Get the current {@link ConnectionState} between the client and the Convex\n * backend.\n *\n * @returns The {@link ConnectionState} with the Convex backend.\n */\n connectionState(): ConnectionState {\n const wsConnectionState = this.webSocketManager.connectionState();\n return {\n hasInflightRequests: this.requestManager.hasInflightRequests(),\n isWebSocketConnected: wsConnectionState.isConnected,\n hasEverConnected: wsConnectionState.hasEverConnected,\n connectionCount: wsConnectionState.connectionCount,\n connectionRetries: wsConnectionState.connectionRetries,\n timeOfOldestInflightRequest:\n this.requestManager.timeOfOldestInflightRequest(),\n inflightMutations: this.requestManager.inflightMutations(),\n inflightActions: this.requestManager.inflightActions(),\n };\n }\n\n /**\n * Call this whenever the connection state may have changed in a way that could\n * require publishing it. Schedules a possibly update.\n */\n private markConnectionStateDirty = () => {\n void Promise.resolve().then(() => {\n const curConnectionState = this.connectionState();\n if (\n JSON.stringify(curConnectionState) !==\n JSON.stringify(this._lastPublishedConnectionState)\n ) {\n this._lastPublishedConnectionState = curConnectionState;\n for (const cb of this.connectionStateSubscribers.values()) {\n // One of these callback throwing will prevent other callbacks\n // from running but will not leave the client in a undefined state.\n cb(curConnectionState);\n }\n }\n });\n };\n\n /**\n * Subscribe to the {@link ConnectionState} between the client and the Convex\n * backend, calling a callback each time it changes.\n *\n * Subscribed callbacks will be called when any part of ConnectionState changes.\n * ConnectionState may grow in future versions (e.g. to provide a array of\n * inflight requests) in which case callbacks would be called more frequently.\n *\n * @returns An unsubscribe function to stop listening.\n */\n subscribeToConnectionState(\n cb: (connectionState: ConnectionState) => void,\n ): () => void {\n const id = this.nextConnectionStateSubscriberId++;\n this.connectionStateSubscribers.set(id, cb);\n return () => {\n this.connectionStateSubscribers.delete(id);\n };\n }\n\n /**\n * Execute a mutation function.\n *\n * @param name - The name of the mutation.\n * @param args - An arguments object for the mutation. If this is omitted,\n * the arguments will be `{}`.\n * @param options - A {@link MutationOptions} options object for this mutation.\n\n * @returns - A promise of the mutation's result.\n */\n async mutation(\n name: string,\n args?: Record<string, Value>,\n options?: MutationOptions,\n ): Promise<any> {\n const result = await this.mutationInternal(name, args, options);\n if (!result.success) {\n if (result.errorData !== undefined) {\n throw forwardData(\n result,\n new ConvexError(\n createHybridErrorStacktrace(\"mutation\", name, result),\n ),\n );\n }\n throw new Error(createHybridErrorStacktrace(\"mutation\", name, result));\n }\n return result.value;\n }\n\n /**\n * @internal\n */\n async mutationInternal(\n udfPath: string,\n args?: Record<string, Value>,\n options?: MutationOptions,\n componentPath?: string,\n ): Promise<FunctionResult> {\n const { mutationPromise } = this.enqueueMutation(\n udfPath,\n args,\n options,\n componentPath,\n );\n return mutationPromise;\n }\n\n /**\n * @internal\n */\n enqueueMutation(\n udfPath: string,\n args?: Record<string, Value>,\n options?: MutationOptions,\n componentPath?: string,\n ): { requestId: RequestId; mutationPromise: Promise<FunctionResult> } {\n const mutationArgs = parseArgs(args);\n this.tryReportLongDisconnect();\n const requestId = this.nextRequestId;\n this._nextRequestId++;\n\n if (options !== undefined) {\n const optimisticUpdate = options.optimisticUpdate;\n if (optimisticUpdate !== undefined) {\n const wrappedUpdate = (localQueryStore: OptimisticLocalStore) => {\n const result: unknown = optimisticUpdate(\n localQueryStore,\n mutationArgs,\n );\n if (result instanceof Promise) {\n this.logger.warn(\n \"Optimistic update handler returned a Promise. Optimistic updates should be synchronous.\",\n );\n }\n };\n\n const changedQueryTokens =\n this.optimisticQueryResults.applyOptimisticUpdate(\n wrappedUpdate,\n requestId,\n );\n\n const changedQueries = changedQueryTokens.map((token) => {\n const localResult = this.localQueryResultByToken(token);\n return {\n token,\n modification: {\n kind: \"Updated\" as const,\n result:\n localResult === undefined\n ? undefined\n : {\n success: true as const,\n value: localResult,\n logLines: [],\n },\n },\n };\n });\n this.handleTransition({\n queries: changedQueries,\n reflectedMutations: [],\n timestamp: this.remoteQuerySet.timestamp(),\n });\n }\n }\n\n const message: MutationRequest = {\n type: \"Mutation\",\n requestId,\n udfPath,\n componentPath,\n args: [convexToJson(mutationArgs)],\n };\n const mightBeSent = this.webSocketManager.sendMessage(message);\n const mutationPromise = this.requestManager.request(message, mightBeSent);\n return {\n requestId,\n mutationPromise,\n };\n }\n\n /**\n * Execute an action function.\n *\n * @param name - The name of the action.\n * @param args - An arguments object for the action. If this is omitted,\n * the arguments will be `{}`.\n * @returns A promise of the action's result.\n */\n async action(name: string, args?: Record<string, Value>): Promise<any> {\n const result = await this.actionInternal(name, args);\n if (!result.success) {\n if (result.errorData !== undefined) {\n throw forwardData(\n result,\n new ConvexError(createHybridErrorStacktrace(\"action\", name, result)),\n );\n }\n throw new Error(createHybridErrorStacktrace(\"action\", name, result));\n }\n return result.value;\n }\n\n /**\n * @internal\n */\n async actionInternal(\n udfPath: string,\n args?: Record<string, Value>,\n componentPath?: string,\n ): Promise<FunctionResult> {\n const actionArgs = parseArgs(args);\n const requestId = this.nextRequestId;\n this._nextRequestId++;\n this.tryReportLongDisconnect();\n\n const message: ActionRequest = {\n type: \"Action\",\n requestId,\n udfPath,\n componentPath,\n args: [convexToJson(actionArgs)],\n };\n\n const mightBeSent = this.webSocketManager.sendMessage(message);\n return this.requestManager.request(message, mightBeSent);\n }\n\n /**\n * Close any network handles associated with this client and stop all subscriptions.\n *\n * Call this method when you're done with an {@link BaseConvexClient} to\n * dispose of its sockets and resources.\n *\n * @returns A `Promise` fulfilled when the connection has been completely closed.\n */\n async close(): Promise<void> {\n this.authenticationManager.stop();\n return this.webSocketManager.terminate();\n }\n\n /**\n * Return the address for this client, useful for creating a new client.\n *\n * Not guaranteed to match the address with which this client was constructed:\n * it may be canonicalized.\n */\n get url() {\n return this.address;\n }\n\n /**\n * @internal\n */\n get nextRequestId() {\n return this._nextRequestId;\n }\n\n /**\n * @internal\n */\n get sessionId() {\n return this._sessionId;\n }\n\n // Instance property so that `mark()` doesn't need to be called as a method.\n private mark = (name: MarkName) => {\n if (this.debug) {\n mark(name, this.sessionId);\n }\n };\n\n /**\n * Reports performance marks to the server. This should only be called when\n * we have a functional websocket.\n */\n private reportMarks() {\n if (this.debug) {\n const report = getMarksReport(this.sessionId);\n this.webSocketManager.sendMessage({\n type: \"Event\",\n eventType: \"ClientConnect\",\n event: report,\n });\n }\n }\n\n private tryReportLongDisconnect() {\n if (!this.debug) {\n return;\n }\n const timeOfOldestRequest =\n this.connectionState().timeOfOldestInflightRequest;\n if (\n timeOfOldestRequest === null ||\n Date.now() - timeOfOldestRequest.getTime() <= 60 * 1000\n ) {\n return;\n }\n const endpoint = `${this.address}/api/debug_event`;\n fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Convex-Client\": `npm-${version}`,\n },\n body: JSON.stringify({ event: \"LongWebsocketDisconnect\" }),\n })\n .then((response) => {\n if (!response.ok) {\n this.logger.warn(\n \"Analytics request failed with response:\",\n response.body,\n );\n }\n })\n .catch((error) => {\n this.logger.warn(\"Analytics response failed with error:\", error);\n });\n }\n}\n", "import type { PaginationResult } from \"../../server/index.js\";\nimport type { Infer, Value } from \"../../values/index.js\";\nimport type { paginationOptsValidator } from \"../../server/index.js\";\n\nexport type PaginationStatus =\n | \"LoadingFirstPage\"\n | \"CanLoadMore\"\n | \"LoadingMore\"\n | \"Exhausted\";\n\nexport type PaginatedQueryResult<T> = {\n results: T[];\n status: PaginationStatus;\n loadMore: LoadMoreOfPaginatedQuery;\n};\n\n/**\n * Returns whether loading more was actually initiated; in cases where\n * a paginated query is already loading more items or there are no more\n * items available, calling loadMore() may do nothing.\n */\nexport type LoadMoreOfPaginatedQuery = (numItems: number) => boolean;\n\n// The arguments for each page query.\nexport function asPaginationArgs(value: Value): Record<string, Value> & {\n paginationOpts: Infer<typeof paginationOptsValidator>;\n} {\n if (typeof (value as any).paginationOpts.numItems !== \"number\") {\n throw new Error(`Not valid paginated query args: ${JSON.stringify(value)}`);\n }\n return value as unknown as Record<string, Value> & {\n paginationOpts: Infer<typeof paginationOptsValidator>;\n };\n}\n\n/**\n * Validates that a Value is a valid pagination result and returns it cast to PaginationResult.\n */\nexport function asPaginationResult(value: Value): PaginationResult<Value> {\n if (\n typeof value !== \"object\" ||\n value === null ||\n !Array.isArray((value as any).page) ||\n typeof (value as any).isDone !== \"boolean\" ||\n typeof (value as any).continueCursor !== \"string\"\n ) {\n throw new Error(`Not a valid paginated query result: ${value?.toString()}`);\n }\n return value as unknown as PaginationResult<Value>;\n}\n", "/**\n * PaginatedQueryClient maps subscriptions to paginated queries to the\n * individual page queries and handles page splits.\n *\n * In order to process all modified queries, paginated and normal, in the same\n * synchronous call the PaginatedQueryClient transition should be used exclusively.\n *\n * Like the BaseConvexClient, this client is not Convex Function type-aware: it deals\n * with queries as functions that return Value, not the specific value.\n * Use a higher-level library to get types.\n */\n\nimport { Value } from \"../../values/index.js\";\nimport {\n PaginatedQueryToken,\n QueryToken,\n serializePaginatedPathAndArgs,\n canonicalizeUdfPath,\n} from \"./udf_path_utils.js\";\nimport { BaseConvexClient, Transition } from \"./client.js\";\nimport {\n PaginatedQueryResult,\n PaginationStatus,\n asPaginationResult,\n} from \"./pagination.js\";\nimport { TS } from \"./protocol.js\";\nimport { Long } from \"../../vendor/long.js\";\n\ntype QueryPageKey = number;\n\n/**\n * Represents a paginated query subscription with multiple pages.\n *\n * To know the order of pages it's necessary to consult `pageKeys`.\n * The pages in this array are active, they constitute a gapless sequence of results.\n * Some pages are not in this array: they may be waiting for data for a page split.\n */\ntype LocalPaginatedQuery = {\n token: PaginatedQueryToken;\n canonicalizedUdfPath: string;\n args: Record<string, Value>; // WITHOUT paginationOpts\n numSubscribers: number;\n options: { initialNumItems: number };\n nextPageKey: QueryPageKey;\n pageKeys: QueryPageKey[]; // These pages make up the active page queries.\n // Map page keys to their query subscriptions\n pageKeyToQuery: Map<\n QueryPageKey,\n { queryToken: QueryToken; unsubscribe: () => void }\n >;\n ongoingSplits: Map<QueryPageKey, [QueryPageKey, QueryPageKey]>;\n skip: boolean;\n\n // Give separate uses of the query separate identities,\n // which may be removed in the future to improve caching.\n id: number;\n};\n\nexport interface SubscribeToPaginatedQueryOptions {\n initialNumItems: number;\n id: number;\n}\n\ntype AnyPaginatedQueryResult = PaginatedQueryResult<Value>;\n\nexport type PaginatedQueryModification =\n | { kind: \"Updated\"; result: AnyPaginatedQueryResult | undefined }\n | { kind: \"Removed\" };\n\nexport type ExtendedTransition = Transition & {\n paginatedQueries: Array<{\n token: PaginatedQueryToken;\n modification: PaginatedQueryModification;\n }>;\n};\n\nexport class PaginatedQueryClient {\n private paginatedQuerySet: Map<PaginatedQueryToken, LocalPaginatedQuery> =\n new Map();\n // hold onto a real Transition so we can construct synthetic ones with that timestamp\n private lastTransitionTs: TS;\n\n constructor(\n private client: BaseConvexClient,\n private onTransition: (transition: ExtendedTransition) => void,\n ) {\n // Nonsense initial value to construct synthetic Transitions\n this.lastTransitionTs = Long.fromNumber(0);\n this.client.addOnTransitionHandler((transition: Transition) =>\n this.onBaseTransition(transition),\n );\n }\n\n /**\n * Subscribe to a paginated query.\n *\n * @param name - The name of the paginated query function\n * @param args - Arguments for the query (excluding paginationOpts)\n * @param options - Pagination options including initialNumItems\n * @returns Object with paginatedQueryToken and unsubscribe function\n */\n subscribe(\n name: string,\n args: Record<string, Value>,\n options: SubscribeToPaginatedQueryOptions,\n ): {\n paginatedQueryToken: PaginatedQueryToken;\n unsubscribe: () => void;\n } {\n const canonicalizedUdfPath = canonicalizeUdfPath(name);\n // Note that only the expected options are included in the serialization.\n const token = serializePaginatedPathAndArgs(\n canonicalizedUdfPath,\n args,\n options,\n );\n\n const unsubscribe = () => this.removePaginatedQuerySubscriber(token);\n\n const existingEntry = this.paginatedQuerySet.get(token);\n if (existingEntry) {\n existingEntry.numSubscribers += 1;\n return {\n paginatedQueryToken: token,\n unsubscribe,\n };\n }\n\n // Create new paginated query\n this.paginatedQuerySet.set(token, {\n token,\n canonicalizedUdfPath,\n args,\n numSubscribers: 1,\n options: { initialNumItems: options.initialNumItems },\n nextPageKey: 0,\n pageKeys: [],\n pageKeyToQuery: new Map(),\n ongoingSplits: new Map(),\n skip: false,\n id: options.id,\n });\n\n this.addPageToPaginatedQuery(token, null, options.initialNumItems);\n\n return {\n paginatedQueryToken: token,\n unsubscribe,\n };\n }\n\n /**\n * Get current results for a paginated query based on local state.\n *\n * Throws an error when one of the pages has errored.\n */\n localQueryResult(\n name: string,\n args: Record<string, Value>,\n options: { initialNumItems: number; id: number },\n ): AnyPaginatedQueryResult | undefined {\n const canonicalizedUdfPath = canonicalizeUdfPath(name);\n const token = serializePaginatedPathAndArgs(\n canonicalizedUdfPath,\n args,\n options,\n );\n return this.localQueryResultByToken(token);\n }\n\n /**\n * @internal\n */\n localQueryResultByToken(\n token: PaginatedQueryToken,\n ): AnyPaginatedQueryResult | undefined {\n // undefined is probably the wrong value! Should be a real paginated query result for loading!\n // Butit's confusing why we'd ever get this, I guess some flows call localQueryResult before\n // subscribing? That's proabbly fair but is it consistent with the normal client?\n // What is the invariant here, will a token always exist? Or can a lookup occur at any time?\n const paginatedQuery = this.paginatedQuerySet.get(token);\n if (!paginatedQuery) {\n return undefined;\n }\n\n const activePages = this.activePageQueryTokens(paginatedQuery);\n if (activePages.length === 0) {\n return {\n results: [],\n status: \"LoadingFirstPage\",\n loadMore: (numItems: number) => {\n return this.loadMoreOfPaginatedQuery(token, numItems);\n },\n };\n }\n\n let allResults: Value[] = [];\n\n // Some page is loading (this isn't supposed to happen to any page but the last)\n let hasUndefined = false;\n let isDone = false;\n\n for (const pageToken of activePages) {\n // This throws, don't catch it, it should bubble up.\n // It might be a InvalidCursor Error. If it is, this query\n // should be reset (for now, use a new ID to ensure new state).\n //\n // In the future this might be caught and dealt with here but\n // an ID-based solution won't work here, ID is an intrinsic property\n // of this paginated query.\n const result = this.client.localQueryResultByToken(pageToken);\n\n if (result === undefined) {\n hasUndefined = true;\n isDone = false;\n continue;\n }\n\n const paginationResult = asPaginationResult(result);\n allResults = allResults.concat(paginationResult.page);\n // logic only relevant to the last page, we just happen to run it each time\n isDone = !!paginationResult.isDone;\n }\n\n let status: PaginationStatus;\n if (hasUndefined) {\n status = allResults.length === 0 ? \"LoadingFirstPage\" : \"LoadingMore\";\n } else if (isDone) {\n status = \"Exhausted\";\n } else {\n status = \"CanLoadMore\";\n }\n\n return {\n results: allResults,\n status,\n loadMore: (numItems: number) => {\n return this.loadMoreOfPaginatedQuery(token, numItems);\n },\n };\n }\n\n private onBaseTransition(transition: Transition) {\n const changedBaseTokens = transition.queries.map((q) => q.token);\n const changed = this.queriesContainingTokens(changedBaseTokens);\n\n let paginatedQueries: Array<{\n token: PaginatedQueryToken;\n modification: PaginatedQueryModification;\n }> = [];\n\n if (changed.length > 0) {\n this.processPaginatedQuerySplits(changed, (token) =>\n this.client.localQueryResultByToken(token),\n );\n\n paginatedQueries = changed.map((token) => ({\n token,\n modification: {\n kind: \"Updated\" as const,\n result: this.localQueryResultByToken(token),\n },\n }));\n }\n\n const extendedTransition: ExtendedTransition = {\n ...transition,\n paginatedQueries,\n };\n\n this.onTransition(extendedTransition);\n }\n\n /**\n * Load more items for a paginated query.\n *\n * This *always* causes a transition, the status of the query\n * has probably changed from \"CanLoadMore\" to \"LoadingMore\".\n * Data might have changed too: maybe a subscription to this page\n * query already exists (unlikely but possible) or this page query\n * has an optimistic update providing some initial data.\n *\n * @internal\n */\n private loadMoreOfPaginatedQuery(\n token: PaginatedQueryToken,\n numItems: number,\n ): boolean {\n this.mustGetPaginatedQuery(token);\n\n const lastPageToken = this.queryTokenForLastPageOfPaginatedQuery(token);\n const lastPageResult = this.client.localQueryResultByToken(lastPageToken);\n\n if (!lastPageResult) {\n // Still loading a page and concurrent loads are not allowed\n return false;\n }\n\n const paginationResult = asPaginationResult(lastPageResult);\n if (paginationResult.isDone) {\n // No more pages available\n return false;\n }\n\n this.addPageToPaginatedQuery(\n token,\n paginationResult.continueCursor,\n numItems,\n );\n\n const loadMoreTransition: ExtendedTransition = {\n timestamp: this.lastTransitionTs,\n reflectedMutations: [],\n queries: [],\n paginatedQueries: [\n {\n token,\n modification: {\n kind: \"Updated\" as const,\n result: this.localQueryResultByToken(token),\n },\n },\n ],\n };\n this.onTransition(loadMoreTransition);\n\n return true;\n }\n\n /**\n * @internal\n */\n private queriesContainingTokens(\n queryTokens: QueryToken[],\n ): PaginatedQueryToken[] {\n if (queryTokens.length === 0) {\n return [];\n }\n\n const changed: PaginatedQueryToken[] = [];\n const queryTokenSet = new Set(queryTokens);\n\n for (const [paginatedToken, paginatedQuery] of this.paginatedQuerySet) {\n for (const pageToken of this.allQueryTokens(paginatedQuery)) {\n if (queryTokenSet.has(pageToken)) {\n changed.push(paginatedToken);\n break;\n }\n }\n }\n\n return changed;\n }\n\n /**\n * @internal\n */\n private processPaginatedQuerySplits(\n changed: PaginatedQueryToken[],\n getResult: (token: QueryToken) => Value | undefined,\n ): void {\n for (const paginatedQueryToken of changed) {\n const paginatedQuery = this.mustGetPaginatedQuery(paginatedQueryToken);\n\n // These properties are all mutable, the destructure here is optional.\n const { ongoingSplits, pageKeyToQuery, pageKeys } = paginatedQuery;\n\n // Check for any completed splits\n for (const [pageKey, [splitKey1, splitKey2]] of ongoingSplits) {\n const bothNewPagesLoaded =\n getResult(pageKeyToQuery.get(splitKey1)!.queryToken) !== undefined &&\n getResult(pageKeyToQuery.get(splitKey2)!.queryToken) !== undefined;\n\n if (bothNewPagesLoaded) {\n this.completePaginatedQuerySplit(\n paginatedQuery,\n pageKey,\n splitKey1,\n splitKey2,\n );\n }\n }\n\n // Check each active page for splits needed\n for (const pageKey of pageKeys) {\n if (ongoingSplits.has(pageKey)) {\n continue; // Already splitting\n }\n\n const pageToken = pageKeyToQuery.get(pageKey)!.queryToken;\n const pageResult = getResult(pageToken);\n if (!pageResult) {\n continue;\n }\n const result = asPaginationResult(pageResult);\n\n // Check if this page needs splitting\n const shouldSplit =\n result.splitCursor &&\n (result.pageStatus === \"SplitRecommended\" ||\n result.pageStatus === \"SplitRequired\" ||\n // This client-driven page splitting condition will change in the future.\n result.page.length > paginatedQuery.options.initialNumItems * 2);\n\n if (shouldSplit) {\n this.splitPaginatedQueryPage(\n paginatedQuery,\n pageKey,\n result.splitCursor!, // we just checked\n result.continueCursor,\n );\n }\n }\n }\n }\n\n private splitPaginatedQueryPage(\n paginatedQuery: LocalPaginatedQuery,\n pageKey: QueryPageKey,\n splitCursor: string,\n continueCursor: string | null,\n ): void {\n const splitKey1 = paginatedQuery.nextPageKey++;\n const splitKey2 = paginatedQuery.nextPageKey++;\n\n const paginationOpts: Value = {\n cursor: continueCursor,\n numItems: paginatedQuery.options.initialNumItems,\n id: paginatedQuery.id,\n };\n\n // First split page: same cursor as original, but add endCursor at splitCursor\n const firstSubscription = this.client.subscribe(\n paginatedQuery.canonicalizedUdfPath,\n {\n ...paginatedQuery.args,\n paginationOpts: {\n ...paginationOpts,\n cursor: null, // Start from beginning for first split\n endCursor: splitCursor,\n },\n },\n );\n paginatedQuery.pageKeyToQuery.set(splitKey1, firstSubscription);\n\n // Second split page: cursor starts at splitCursor, endCursor is the original continueCursor\n const secondSubscription = this.client.subscribe(\n paginatedQuery.canonicalizedUdfPath,\n {\n ...paginatedQuery.args,\n paginationOpts: {\n ...paginationOpts,\n cursor: splitCursor,\n endCursor: continueCursor,\n },\n },\n );\n paginatedQuery.pageKeyToQuery.set(splitKey2, secondSubscription);\n\n paginatedQuery.ongoingSplits.set(pageKey, [splitKey1, splitKey2]);\n }\n\n /**\n * @internal\n */\n private addPageToPaginatedQuery(\n token: PaginatedQueryToken,\n continueCursor: string | null,\n numItems: number,\n ): { queryToken: QueryToken; unsubscribe: () => void } {\n const paginatedQuery = this.mustGetPaginatedQuery(token);\n const pageKey = paginatedQuery.nextPageKey++;\n\n const paginationOpts: Value = {\n cursor: continueCursor,\n numItems,\n id: paginatedQuery.id,\n };\n\n const pageArgs = {\n ...paginatedQuery.args,\n paginationOpts,\n };\n\n const subscription = this.client.subscribe(\n paginatedQuery.canonicalizedUdfPath,\n pageArgs,\n );\n\n paginatedQuery.pageKeys.push(pageKey);\n paginatedQuery.pageKeyToQuery.set(pageKey, subscription);\n return subscription;\n }\n\n private removePaginatedQuerySubscriber(token: PaginatedQueryToken): void {\n const paginatedQuery = this.paginatedQuerySet.get(token);\n if (!paginatedQuery) {\n return;\n }\n\n paginatedQuery.numSubscribers -= 1;\n if (paginatedQuery.numSubscribers > 0) {\n return;\n }\n\n // Remove all page subscriptions by calling their unsubscribe callbacks\n for (const subscription of paginatedQuery.pageKeyToQuery.values()) {\n subscription.unsubscribe();\n }\n\n this.paginatedQuerySet.delete(token);\n }\n\n private completePaginatedQuerySplit(\n paginatedQuery: LocalPaginatedQuery,\n pageKey: QueryPageKey,\n splitKey1: QueryPageKey,\n splitKey2: QueryPageKey,\n ): void {\n const originalQuery = paginatedQuery.pageKeyToQuery.get(pageKey)!;\n paginatedQuery.pageKeyToQuery.delete(pageKey);\n const pageIndex = paginatedQuery.pageKeys.indexOf(pageKey);\n paginatedQuery.pageKeys.splice(pageIndex, 1, splitKey1, splitKey2);\n paginatedQuery.ongoingSplits.delete(pageKey);\n originalQuery.unsubscribe();\n }\n\n /** The query tokens for all active pages, in result order */\n private activePageQueryTokens(\n paginatedQuery: LocalPaginatedQuery,\n ): QueryToken[] {\n return paginatedQuery.pageKeys.map(\n (pageKey) => paginatedQuery.pageKeyToQuery.get(pageKey)!.queryToken,\n );\n }\n\n private allQueryTokens(paginatedQuery: LocalPaginatedQuery): QueryToken[] {\n return Array.from(paginatedQuery.pageKeyToQuery.values()).map(\n (sub) => sub.queryToken,\n );\n }\n\n private queryTokenForLastPageOfPaginatedQuery(\n token: PaginatedQueryToken,\n ): QueryToken {\n const paginatedQuery = this.mustGetPaginatedQuery(token);\n const lastPageKey =\n paginatedQuery.pageKeys[paginatedQuery.pageKeys.length - 1];\n if (lastPageKey === undefined) {\n throw new Error(`No pages for paginated query ${token}`);\n }\n return paginatedQuery.pageKeyToQuery.get(lastPageKey)!.queryToken;\n }\n\n private mustGetPaginatedQuery(\n token: PaginatedQueryToken,\n ): LocalPaginatedQuery {\n const paginatedQuery = this.paginatedQuerySet.get(token);\n if (!paginatedQuery) {\n throw new Error(\"paginated query no longer exists for token \" + token);\n }\n return paginatedQuery;\n }\n}\n", "// Inspired by https://tanstack.com/query/v5/docs/framework/react/guides/query-options\nimport type { FunctionArgs, FunctionReference } from \"../server/api.js\";\n\n/**\n * Options for a Convex query: the query function reference and its arguments.\n *\n * Used with the object-form overload of {@link useQuery}.\n *\n * @public\n */\nexport type QueryOptions<Query extends FunctionReference<\"query\">> = {\n /**\n * The query function to run.\n */\n query: Query;\n /**\n * The arguments to the query function.\n */\n args: FunctionArgs<Query>;\n};\n\n/**\n * Creates a type-safe {@link QueryOptions} object for a Convex query.\n *\n * This is an identity function that exists to provide type inference \u2014 passing\n * your query and args through this helper ensures TypeScript infers the correct\n * `Query` type parameter, which enables precise return types on hooks like\n * {@link useQuery}.\n *\n * ```typescript\n * const opts = convexQueryOptions({\n * query: api.users.getById,\n * args: { id: userId },\n * });\n * // opts is typed as QueryOptions<typeof api.users.getById>\n * client.prewarmQuery(opts);\n * ```\n *\n * @param options - The query and its arguments.\n * @returns The same object, typed as `QueryOptions<Query>`.\n * @internal\n */\nexport function convexQueryOptions<Query extends FunctionReference<\"query\">>(\n options: QueryOptions<Query>,\n): QueryOptions<Query> {\n return options;\n}\n", "import { BaseConvexClient } from \"../browser/index.js\";\nimport type {\n OptimisticUpdate,\n PaginatedQueryToken,\n QueryToken,\n PaginationStatus,\n} from \"../browser/index.js\";\nimport React, { useCallback, useContext, useMemo } from \"react\";\nimport { convexToJson, Value } from \"../values/index.js\";\nimport { QueryJournal } from \"../browser/sync/protocol.js\";\nimport {\n AuthTokenFetcher,\n BaseConvexClientOptions,\n ConnectionState,\n} from \"../browser/sync/client.js\";\nimport type { UserIdentityAttributes } from \"../browser/sync/protocol.js\";\nimport { RequestForQueries, useQueries } from \"./use_queries.js\";\nimport { useSubscription } from \"./use_subscription.js\";\nimport { parseArgs } from \"../common/index.js\";\nimport {\n ArgsAndOptions,\n FunctionArgs,\n FunctionReference,\n FunctionReturnType,\n OptionalRestArgs,\n getFunctionName,\n makeFunctionReference,\n} from \"../server/api.js\";\nimport { EmptyObject } from \"../server/registration.js\";\nimport {\n instantiateDefaultLogger,\n instantiateNoopLogger,\n Logger,\n} from \"../browser/logging.js\";\nimport type { QueryOptions } from \"../browser/query_options.js\";\nimport { LoadMoreOfPaginatedQuery } from \"../browser/sync/pagination.js\";\nimport {\n PaginatedQueryClient,\n ExtendedTransition,\n} from \"../browser/sync/paginated_query_client.js\";\n\n// When no arguments are passed, extend subscriptions (for APIs that do this by default)\n// for this amount after the subscription would otherwise be dropped.\nconst DEFAULT_EXTEND_SUBSCRIPTION_FOR = 5_000;\n\nif (typeof React === \"undefined\") {\n throw new Error(\"Required dependency 'react' not found\");\n}\n\n// TODO Typedoc doesn't generate documentation for the comment below perhaps\n// because it's a callable interface.\n/**\n * An interface to execute a Convex mutation function on the server.\n *\n * @public\n */\nexport interface ReactMutation<Mutation extends FunctionReference<\"mutation\">> {\n /**\n * Execute the mutation on the server, returning a `Promise` of its return value.\n *\n * @param args - Arguments for the mutation to pass up to the server.\n * @returns The return value of the server-side function call.\n */\n (...args: OptionalRestArgs<Mutation>): Promise<FunctionReturnType<Mutation>>;\n\n /**\n * Define an optimistic update to apply as part of this mutation.\n *\n * This is a temporary update to the local query results to facilitate a\n * fast, interactive UI. It enables query results to update before a mutation\n * executed on the server.\n *\n * When the mutation is invoked, the optimistic update will be applied.\n *\n * Optimistic updates can also be used to temporarily remove queries from the\n * client and create loading experiences until a mutation completes and the\n * new query results are synced.\n *\n * The update will be automatically rolled back when the mutation is fully\n * completed and queries have been updated.\n *\n * @param optimisticUpdate - The optimistic update to apply.\n * @returns A new `ReactMutation` with the update configured.\n *\n * @public\n */\n withOptimisticUpdate<T extends OptimisticUpdate<FunctionArgs<Mutation>>>(\n optimisticUpdate: T &\n (ReturnType<T> extends Promise<any>\n ? \"Optimistic update handlers must be synchronous\"\n : {}),\n ): ReactMutation<Mutation>;\n}\n\n// Exported only for testing.\nexport function createMutation(\n mutationReference: FunctionReference<\"mutation\">,\n client: ConvexReactClient,\n update?: OptimisticUpdate<any>,\n): ReactMutation<any> {\n function mutation(args?: Record<string, Value>): Promise<unknown> {\n assertNotAccidentalArgument(args);\n\n return client.mutation(mutationReference, args, {\n optimisticUpdate: update,\n });\n }\n mutation.withOptimisticUpdate = function withOptimisticUpdate(\n optimisticUpdate: OptimisticUpdate<any>,\n ): ReactMutation<any> {\n if (update !== undefined) {\n throw new Error(\n `Already specified optimistic update for mutation ${getFunctionName(\n mutationReference,\n )}`,\n );\n }\n return createMutation(mutationReference, client, optimisticUpdate);\n };\n return mutation as ReactMutation<any>;\n}\n\n/**\n * An interface to execute a Convex action on the server.\n *\n * @public\n */\nexport interface ReactAction<Action extends FunctionReference<\"action\">> {\n /**\n * Execute the function on the server, returning a `Promise` of its return value.\n *\n * @param args - Arguments for the function to pass up to the server.\n * @returns The return value of the server-side function call.\n * @public\n */\n (...args: OptionalRestArgs<Action>): Promise<FunctionReturnType<Action>>;\n}\n\nfunction createAction(\n actionReference: FunctionReference<\"action\">,\n client: ConvexReactClient,\n): ReactAction<any> {\n return function (args?: Record<string, Value>): Promise<unknown> {\n return client.action(actionReference, args);\n } as ReactAction<any>;\n}\n\n// Watches should be stateless: in QueriesObserver we create a watch just to get\n// the current value.\n/**\n * A watch on the output of a Convex query function.\n *\n * @public\n */\nexport interface Watch<T> {\n /**\n * Initiate a watch on the output of a query.\n *\n * This will subscribe to this query and call\n * the callback whenever the query result changes.\n *\n * **Important: If the client is already subscribed to this query with the\n * same arguments this callback will not be invoked until the query result is\n * updated.** To get the current, local result call\n * {@link react.Watch.localQueryResult}.\n *\n * @param callback - Function that is called whenever the query result changes.\n * @returns - A function that disposes of the subscription.\n */\n onUpdate(callback: () => void): () => void;\n\n /**\n * Get the current result of a query.\n *\n * This will only return a result if we're already subscribed to the query\n * and have received a result from the server or the query value has been set\n * optimistically.\n *\n * @returns The result of the query or `undefined` if it isn't known.\n * @throws An error if the query encountered an error on the server.\n */\n localQueryResult(): T | undefined;\n\n /**\n * @internal\n */\n localQueryLogs(): string[] | undefined;\n\n /**\n * Get the current {@link browser.QueryJournal} for this query.\n *\n * If we have not yet received a result for this query, this will be `undefined`.\n */\n journal(): QueryJournal | undefined;\n}\n\n/**\n * A watch on the output of a paginated Convex query function.\n *\n * @public\n */\nexport interface PaginatedWatch<T> {\n /**\n * Initiate a watch on the output of a paginated query.\n *\n * This will subscribe to this query and call\n * the callback whenever the query result changes.\n *\n * @param callback - Function that is called whenever the query result changes.\n * @returns - A function that disposes of the subscription.\n */\n onUpdate(callback: () => void): () => void;\n\n /**\n * Get the current result of a paginated query.\n *\n * @returns The current results, status, and loadMore function, or `undefined` if not loaded.\n */\n localQueryResult():\n | {\n results: T[];\n status: PaginationStatus;\n loadMore: LoadMoreOfPaginatedQuery;\n }\n | undefined;\n}\n\n/**\n * Options for {@link ConvexReactClient.watchQuery}.\n *\n * @public\n */\nexport interface WatchQueryOptions {\n /**\n * An (optional) journal produced from a previous execution of this query\n * function.\n *\n * If there is an existing subscription to a query function with the same\n * name and arguments, this journal will have no effect.\n */\n journal?: QueryJournal;\n\n /**\n * @internal\n */\n componentPath?: string;\n}\n\n/**\n * Options for {@link ConvexReactClient.watchPaginatedQuery}.\n *\n * @internal\n */\nexport interface WatchPaginatedQueryOptions {\n /**\n * The initial number of items to load.\n */\n initialNumItems: number;\n\n // We may be able to remove this in the future, but to preserve the existing behavior of\n // usePaginatedQuery() it's still here.\n id: number;\n\n /**\n * @internal\n */\n componentPath?: string;\n}\n\n/**\n * Options for {@link ConvexReactClient.mutation}.\n *\n * @public\n */\nexport interface MutationOptions<Args extends Record<string, Value>> {\n /**\n * An optimistic update to apply along with this mutation.\n *\n * An optimistic update locally updates queries while a mutation is pending.\n * Once the mutation completes, the update will be rolled back.\n */\n optimisticUpdate?: OptimisticUpdate<Args> | undefined;\n}\n\n/**\n * Options for {@link ConvexReactClient}.\n *\n * @public\n */\nexport interface ConvexReactClientOptions extends BaseConvexClientOptions {}\n\n/**\n * A Convex client for use within React.\n *\n * This loads reactive queries and executes mutations over a WebSocket.\n *\n * @public\n */\nexport class ConvexReactClient {\n private address: string;\n private cachedSync?: BaseConvexClient | undefined;\n private cachedPaginatedQueryClient?: PaginatedQueryClient | undefined;\n private listeners: Map<QueryToken | PaginatedQueryToken, Set<() => void>>;\n private options: ConvexReactClientOptions;\n // \"closed\" means this client is done, not just that the underlying WS connection is closed.\n private closed = false;\n private _logger: Logger;\n\n private adminAuth?: string;\n private fakeUserIdentity?: UserIdentityAttributes | undefined;\n\n /**\n * @param address - The url of your Convex deployment, often provided\n * by an environment variable. E.g. `https://small-mouse-123.convex.cloud`.\n * @param options - See {@link ConvexReactClientOptions} for a full description.\n */\n constructor(address: string, options?: ConvexReactClientOptions) {\n // Validate address immediately since validation by the lazily-instantiated\n // internal client does not occur synchronously.\n if (address === undefined) {\n throw new Error(\n \"No address provided to ConvexReactClient.\\n\" +\n \"If trying to deploy to production, make sure to follow all the instructions found at https://docs.convex.dev/production/hosting/\\n\" +\n \"If running locally, make sure to run `convex dev` and ensure the .env.local file is populated.\",\n );\n }\n if (typeof address !== \"string\") {\n throw new Error(\n `ConvexReactClient requires a URL like 'https://happy-otter-123.convex.cloud', received something of type ${typeof address} instead.`,\n );\n }\n if (!address.includes(\"://\")) {\n throw new Error(\"Provided address was not an absolute URL.\");\n }\n this.address = address;\n this.listeners = new Map();\n this._logger =\n options?.logger === false\n ? instantiateNoopLogger({ verbose: options?.verbose ?? false })\n : options?.logger !== true && options?.logger\n ? options.logger\n : instantiateDefaultLogger({ verbose: options?.verbose ?? false });\n this.options = { ...options, logger: this._logger };\n }\n\n /**\n * Return the address for this client, useful for creating a new client.\n *\n * Not guaranteed to match the address with which this client was constructed:\n * it may be canonicalized.\n */\n get url() {\n return this.address;\n }\n\n /**\n * Lazily instantiate the `BaseConvexClient` so we don't create the WebSocket\n * when server-side rendering.\n *\n * @internal\n */\n get sync() {\n if (this.closed) {\n throw new Error(\"ConvexReactClient has already been closed.\");\n }\n if (this.cachedSync) {\n return this.cachedSync;\n }\n // BaseConvexClient and paginated query client are always created together.\n this.cachedSync = new BaseConvexClient(\n this.address,\n () => {}, // Use the PaginatedQueryClient's transition instead.\n this.options,\n );\n if (this.adminAuth) {\n this.cachedSync.setAdminAuth(this.adminAuth, this.fakeUserIdentity);\n }\n this.cachedPaginatedQueryClient = new PaginatedQueryClient(\n this.cachedSync,\n (transition) => this.handleTransition(transition),\n );\n return this.cachedSync;\n }\n\n /**\n * Lazily instantiate the `PaginatedQueryClient` so we don't create it\n * when server-side rendering.\n *\n * @internal\n */\n get paginatedQueryClient() {\n // access sync to instantiate the clients\n this.sync;\n if (this.cachedPaginatedQueryClient) {\n return this.cachedPaginatedQueryClient;\n }\n throw new Error(\"Should already be instantiated\");\n }\n\n /**\n * Set the authentication token to be used for subsequent queries and mutations.\n * `fetchToken` will be called automatically again if a token expires.\n * `fetchToken` should return `null` if the token cannot be retrieved, for example\n * when the user's rights were permanently revoked.\n * @param fetchToken - an async function returning the JWT-encoded OpenID Connect Identity Token\n * @param onChange - a callback that will be called when the authentication status changes\n */\n setAuth(\n fetchToken: AuthTokenFetcher,\n onChange?: (isAuthenticated: boolean) => void,\n ) {\n if (typeof fetchToken === \"string\") {\n throw new Error(\n \"Passing a string to ConvexReactClient.setAuth is no longer supported, \" +\n \"please upgrade to passing in an async function to handle reauthentication.\",\n );\n }\n this.sync.setAuth(\n fetchToken,\n onChange ??\n (() => {\n // Do nothing\n }),\n );\n }\n\n /**\n * Clear the current authentication token if set.\n */\n clearAuth() {\n this.sync.clearAuth();\n }\n\n /**\n * @internal\n */\n setAdminAuth(token: string, identity?: UserIdentityAttributes) {\n this.adminAuth = token;\n this.fakeUserIdentity = identity;\n if (this.closed) {\n throw new Error(\"ConvexReactClient has already been closed.\");\n }\n if (this.cachedSync) {\n this.sync.setAdminAuth(token, identity);\n }\n }\n\n /**\n * Construct a new {@link Watch} on a Convex query function.\n *\n * **Most application code should not call this method directly. Instead use\n * the {@link useQuery} hook.**\n *\n * The act of creating a watch does nothing, a Watch is stateless.\n *\n * @param query - A {@link server.FunctionReference} for the public query to run.\n * @param args - An arguments object for the query. If this is omitted,\n * the arguments will be `{}`.\n * @param options - A {@link WatchQueryOptions} options object for this query.\n *\n * @returns The {@link Watch} object.\n */\n watchQuery<Query extends FunctionReference<\"query\">>(\n query: Query,\n ...argsAndOptions: ArgsAndOptions<Query, WatchQueryOptions>\n ): Watch<FunctionReturnType<Query>> {\n const [args, options] = argsAndOptions;\n const name = getFunctionName(query);\n\n return {\n onUpdate: (callback) => {\n const { queryToken, unsubscribe } = this.sync.subscribe(\n name as string,\n args,\n options,\n );\n\n const currentListeners = this.listeners.get(queryToken);\n if (currentListeners !== undefined) {\n currentListeners.add(callback);\n } else {\n this.listeners.set(queryToken, new Set([callback]));\n }\n\n return () => {\n if (this.closed) {\n return;\n }\n\n const currentListeners = this.listeners.get(queryToken)!;\n currentListeners.delete(callback);\n if (currentListeners.size === 0) {\n this.listeners.delete(queryToken);\n }\n unsubscribe();\n };\n },\n\n localQueryResult: () => {\n // Use the cached client because we can't have a query result if we don't\n // even have a client yet!\n if (this.cachedSync) {\n return this.cachedSync.localQueryResult(name, args);\n }\n return undefined;\n },\n\n localQueryLogs: () => {\n if (this.cachedSync) {\n return this.cachedSync.localQueryLogs(name, args);\n }\n return undefined;\n },\n\n journal: () => {\n if (this.cachedSync) {\n return this.cachedSync.queryJournal(name, args);\n }\n return undefined;\n },\n };\n }\n\n // Let's try out a queryOptions-style API.\n // This method is similar to the React Query API `queryClient.prefetchQuery()`.\n // In the future an ensureQueryData(): Promise<Data> method could exist.\n /**\n * Indicates likely future interest in a query subscription.\n *\n * The implementation currently immediately subscribes to a query. In the future this method\n * may prioritize some queries over others, fetch the query result without subscribing, or\n * do nothing in slow network connections or high load scenarios.\n *\n * To use this in a React component, call useQuery() and ignore the return value.\n *\n * @param queryOptions - A query (function reference from an api object) and its args, plus\n * an optional extendSubscriptionFor for how long to subscribe to the query.\n */\n prewarmQuery<Query extends FunctionReference<\"query\">>(\n queryOptions: QueryOptions<Query> & { extendSubscriptionFor?: number },\n ) {\n const extendSubscriptionFor =\n queryOptions.extendSubscriptionFor ?? DEFAULT_EXTEND_SUBSCRIPTION_FOR;\n const watch = this.watchQuery(queryOptions.query, queryOptions.args || {});\n const unsubscribe = watch.onUpdate(() => {});\n setTimeout(unsubscribe, extendSubscriptionFor);\n }\n\n /**\n * Construct a new {@link PaginatedWatch} on a Convex paginated query function.\n *\n * **Most application code should not call this method directly. Instead use\n * the {@link usePaginatedQuery} hook.**\n *\n * The act of creating a watch does nothing, a Watch is stateless.\n *\n * @param query - A {@link server.FunctionReference} for the public query to run.\n * @param args - An arguments object for the query. If this is omitted,\n * the arguments will be `{}`.\n * @param options - A {@link WatchPaginatedQueryOptions} options object for this query.\n *\n * @returns The {@link PaginatedWatch} object.\n *\n * @internal\n */\n watchPaginatedQuery<Query extends FunctionReference<\"query\">>(\n query: Query,\n args: Query[\"_args\"],\n options: WatchPaginatedQueryOptions,\n ): PaginatedWatch<FunctionReturnType<Query>> {\n const name = getFunctionName(query);\n\n return {\n onUpdate: (callback) => {\n const { paginatedQueryToken, unsubscribe } =\n this.paginatedQueryClient.subscribe(name, args || {}, options);\n\n const currentListeners = this.listeners.get(paginatedQueryToken);\n if (currentListeners !== undefined) {\n currentListeners.add(callback);\n } else {\n this.listeners.set(paginatedQueryToken, new Set([callback]));\n }\n\n return () => {\n if (this.closed) {\n return;\n }\n\n const currentListeners = this.listeners.get(paginatedQueryToken)!;\n currentListeners.delete(callback);\n if (currentListeners.size === 0) {\n this.listeners.delete(paginatedQueryToken);\n }\n unsubscribe();\n };\n },\n\n localQueryResult: () => {\n // Use our new paginated query client\n return this.paginatedQueryClient.localQueryResult(name, args, options);\n },\n };\n }\n\n /**\n * Execute a mutation function.\n *\n * @param mutation - A {@link server.FunctionReference} for the public mutation\n * to run.\n * @param args - An arguments object for the mutation. If this is omitted,\n * the arguments will be `{}`.\n * @param options - A {@link MutationOptions} options object for the mutation.\n * @returns A promise of the mutation's result.\n */\n mutation<Mutation extends FunctionReference<\"mutation\">>(\n mutation: Mutation,\n ...argsAndOptions: ArgsAndOptions<\n Mutation,\n MutationOptions<FunctionArgs<Mutation>>\n >\n ): Promise<FunctionReturnType<Mutation>> {\n const [args, options] = argsAndOptions;\n const name = getFunctionName(mutation);\n return this.sync.mutation(name, args, options);\n }\n\n /**\n * Execute an action function.\n *\n * @param action - A {@link server.FunctionReference} for the public action\n * to run.\n * @param args - An arguments object for the action. If this is omitted,\n * the arguments will be `{}`.\n * @returns A promise of the action's result.\n */\n action<Action extends FunctionReference<\"action\">>(\n action: Action,\n ...args: OptionalRestArgs<Action>\n ): Promise<FunctionReturnType<Action>> {\n const name = getFunctionName(action);\n return this.sync.action(name, ...args);\n }\n\n /**\n * Fetch a query result once.\n *\n * **Most application code should subscribe to queries instead, using\n * the {@link useQuery} hook.**\n *\n * @param query - A {@link server.FunctionReference} for the public query\n * to run.\n * @param args - An arguments object for the query. If this is omitted,\n * the arguments will be `{}`.\n * @returns A promise of the query's result.\n */\n query<Query extends FunctionReference<\"query\">>(\n query: Query,\n ...args: OptionalRestArgs<Query>\n ): Promise<FunctionReturnType<Query>> {\n const watch = this.watchQuery(query, ...args);\n const existingResult = watch.localQueryResult();\n if (existingResult !== undefined) {\n return Promise.resolve(existingResult);\n }\n return new Promise((resolve, reject) => {\n const unsubscribe = watch.onUpdate(() => {\n unsubscribe();\n try {\n resolve(watch.localQueryResult());\n } catch (e) {\n reject(e);\n }\n });\n });\n }\n\n /**\n * Get the current {@link ConnectionState} between the client and the Convex\n * backend.\n *\n * @returns The {@link ConnectionState} with the Convex backend.\n */\n connectionState(): ConnectionState {\n return this.sync.connectionState();\n }\n\n /**\n * Subscribe to the {@link ConnectionState} between the client and the Convex\n * backend, calling a callback each time it changes.\n *\n * Subscribed callbacks will be called when any part of ConnectionState changes.\n * ConnectionState may grow in future versions (e.g. to provide a array of\n * inflight requests) in which case callbacks would be called more frequently.\n * ConnectionState may also *lose* properties in future versions as we figure\n * out what information is most useful. As such this API is considered unstable.\n *\n * @returns An unsubscribe function to stop listening.\n */\n subscribeToConnectionState(\n cb: (connectionState: ConnectionState) => void,\n ): () => void {\n return this.sync.subscribeToConnectionState(cb);\n }\n\n /**\n * Get the logger for this client.\n *\n * @returns The {@link Logger} for this client.\n */\n get logger(): Logger {\n return this._logger;\n }\n\n /**\n * Close any network handles associated with this client and stop all subscriptions.\n *\n * Call this method when you're done with a {@link ConvexReactClient} to\n * dispose of its sockets and resources.\n *\n * @returns A `Promise` fulfilled when the connection has been completely closed.\n */\n async close(): Promise<void> {\n this.closed = true;\n // Prevent outstanding React batched updates from invoking listeners.\n this.listeners = new Map();\n if (this.cachedPaginatedQueryClient) {\n this.cachedPaginatedQueryClient = undefined;\n }\n if (this.cachedSync) {\n const sync = this.cachedSync;\n this.cachedSync = undefined;\n await sync.close();\n }\n }\n\n /**\n * Handle transitions from both base client and paginated client.\n * This ensures all transitions are processed synchronously and in order.\n */\n private handleTransition(transition: ExtendedTransition) {\n const simple = transition.queries.map((q) => q.token);\n const paginated = transition.paginatedQueries.map((q) => q.token);\n this.transition([...simple, ...paginated]);\n }\n\n private transition(updatedQueries: (QueryToken | PaginatedQueryToken)[]) {\n for (const queryToken of updatedQueries) {\n const callbacks = this.listeners.get(queryToken);\n if (callbacks) {\n for (const callback of callbacks) {\n callback();\n }\n }\n }\n }\n}\n\nconst ConvexContext = React.createContext<ConvexReactClient>(\n undefined as unknown as ConvexReactClient, // in the future this will be a mocked client for testing\n);\n\n/**\n * Get the {@link ConvexReactClient} within a React component.\n *\n * This relies on the {@link ConvexProvider} being above in the React component tree.\n *\n * @returns The active {@link ConvexReactClient} object, or `undefined`.\n *\n * @public\n */\nexport function useConvex(): ConvexReactClient {\n return useContext(ConvexContext);\n}\n\n/**\n * Provides an active Convex {@link ConvexReactClient} to descendants of this component.\n *\n * Wrap your app in this component to use Convex hooks `useQuery`,\n * `useMutation`, and `useConvex`.\n *\n * @param props - an object with a `client` property that refers to a {@link ConvexReactClient}.\n *\n * @public\n */\nexport const ConvexProvider: React.FC<{\n client: ConvexReactClient;\n children?: React.ReactNode;\n}> = ({ client, children }) => {\n return React.createElement(\n ConvexContext.Provider,\n { value: client },\n children,\n );\n};\n\nexport type OptionalRestArgsOrSkip<FuncRef extends FunctionReference<any>> =\n FuncRef[\"_args\"] extends EmptyObject\n ? [args?: EmptyObject | \"skip\"]\n : [args: FuncRef[\"_args\"] | \"skip\"];\n\n/**\n * Result returned by object-form {@link useQuery}.\n *\n * @internal\n */\nexport type UseQueryResult<QueryResult> =\n | {\n data: QueryResult;\n error: undefined;\n status: \"success\";\n }\n | {\n data: undefined;\n error: Error;\n status: \"error\";\n }\n | {\n data: undefined;\n error: undefined;\n status: \"pending\";\n };\n\ntype UseQueryOptions<Query extends FunctionReference<\"query\">> = {\n query: Query;\n args: FunctionArgs<Query> | \"skip\";\n throwOnError?: boolean;\n};\n\n/**\n * Load a reactive query within a React component.\n *\n * This React hook subscribes to a Convex query and causes a rerender whenever\n * the query result changes. The subscription is managed automatically --\n * it starts when the component mounts and stops when it unmounts.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @example\n * ```tsx\n * import { useQuery } from \"convex/react\";\n * import { api } from \"../convex/_generated/api\";\n *\n * function TaskList() {\n * // Reactively loads tasks, re-renders when data changes:\n * const tasks = useQuery(api.tasks.list, { completed: false });\n *\n * // Returns `undefined` while loading:\n * if (tasks === undefined) return <div>Loading...</div>;\n *\n * return tasks.map((task) => <div key={task._id}>{task.text}</div>);\n * }\n *\n * // Pass \"skip\" to conditionally disable the query:\n * function MaybeProfile({ userId }: { userId?: Id<\"users\"> }) {\n * const profile = useQuery(\n * api.users.get,\n * userId ? { userId } : \"skip\",\n * );\n * // ...\n * }\n * ```\n *\n * @param query - a {@link server.FunctionReference} for the public query to run\n * like `api.dir1.dir2.filename.func`.\n * @param args - The arguments to the query function or the string `\"skip\"` if the\n * query should not be loaded.\n * @returns the result of the query. Returns `undefined` while loading.\n *\n * @see https://docs.convex.dev/client/react#fetching-data\n * @public\n */\nexport function useQuery<Query extends FunctionReference<\"query\">>(\n query: Query,\n ...args: OptionalRestArgsOrSkip<Query>\n): Query[\"_returnType\"] | undefined;\n\n/**\n * Load a reactive query within a React component using an options object.\n *\n * This is an alternative form of {@link useQuery} that accepts a single\n * {@link UseQueryOptions} object instead of positional arguments.\n * Errors are returned in the result object unless `throwOnError` is set.\n *\n * @example\n * ```tsx\n * import { useQuery } from \"convex/react\";\n * import { api } from \"../convex/_generated/api\";\n *\n * function TaskList() {\n * const state = useQuery({ query: api.tasks.list, args: { completed: false } });\n *\n * if (state.status === \"pending\") return <div>Loading...</div>;\n * if (state.status === \"error\") return <div>Error: {state.error.message}</div>;\n * return state.data.map((task) => <div key={task._id}>{task.text}</div>);\n * }\n * ```\n *\n * @param options - Query options. Pass `args: \"skip\"` to disable the query.\n * @returns the current query state as a {@link UseQueryResult} object.\n *\n * @see https://docs.convex.dev/client/react#fetching-data\n * @internal\n */\nexport function useQuery<Query extends FunctionReference<\"query\">>(\n options: UseQueryOptions<Query>,\n): UseQueryResult<Query[\"_returnType\"]>;\n\nexport function useQuery<Query extends FunctionReference<\"query\">>(\n queryOrOptions: Query | UseQueryOptions<Query>,\n ...args: OptionalRestArgsOrSkip<Query>\n): Query[\"_returnType\"] | undefined | UseQueryResult<Query[\"_returnType\"]> {\n const isObjectOptions =\n typeof queryOrOptions === \"object\" &&\n queryOrOptions !== null &&\n \"query\" in queryOrOptions;\n const throwOnError = isObjectOptions\n ? (queryOrOptions.throwOnError ?? false)\n : true;\n\n let queryReference: Query | undefined;\n let argsObject: Record<string, Value> = {};\n\n if (isObjectOptions) {\n const query = queryOrOptions.query;\n queryReference =\n typeof query === \"string\"\n ? (makeFunctionReference<\"query\", any, any>(query) as Query)\n : query;\n if (queryOrOptions.args !== \"skip\") {\n argsObject = parseArgs(queryOrOptions.args as Record<string, Value>);\n }\n } else {\n const query = queryOrOptions;\n queryReference =\n typeof query === \"string\"\n ? (makeFunctionReference<\"query\", any, any>(query) as Query)\n : query;\n argsObject = args[0] === \"skip\" ? {} : parseArgs(args[0] as Query[\"_args\"]);\n }\n\n const queryName = queryReference\n ? getFunctionName(queryReference)\n : undefined;\n const skip =\n (isObjectOptions && queryOrOptions.args === \"skip\") ||\n (!isObjectOptions && args[0] === \"skip\");\n\n const queries = useMemo(\n () =>\n skip || !queryReference\n ? ({} as RequestForQueries)\n : { query: { query: queryReference, args: argsObject } },\n // Stringify args so args that are semantically the same don't trigger a\n // rerender. Saves developers from adding `useMemo` on every args usage.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(convexToJson(argsObject)), queryName, skip],\n );\n\n const results = useQueries(queries);\n const result = results[\"query\"];\n\n if (isObjectOptions) {\n if (result instanceof Error) {\n if (throwOnError) {\n throw result;\n }\n return {\n data: undefined,\n error: result,\n status: \"error\",\n };\n }\n\n if (result === undefined) {\n return {\n data: undefined,\n error: undefined,\n status: \"pending\",\n };\n }\n\n return {\n data: result,\n error: undefined,\n status: \"success\",\n };\n }\n\n if (result instanceof Error) {\n throw result;\n }\n return result;\n}\n\n/**\n * Construct a new {@link ReactMutation}.\n *\n * Returns a function that you can call to execute a Convex mutation. The\n * returned function is stable across renders (same reference identity), so\n * it can be safely used in dependency arrays and memoization.\n *\n * Mutations can optionally be configured with\n * [optimistic updates](https://docs.convex.dev/client/react/optimistic-updates)\n * for instant UI feedback.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @example\n * ```tsx\n * import { useMutation } from \"convex/react\";\n * import { api } from \"../convex/_generated/api\";\n *\n * function CreateTask() {\n * const createTask = useMutation(api.tasks.create);\n *\n * const handleClick = async () => {\n * await createTask({ text: \"New task\" });\n * };\n *\n * return <button onClick={handleClick}>Add Task</button>;\n * }\n * ```\n *\n * @param mutation - A {@link server.FunctionReference} for the public mutation\n * to run like `api.dir1.dir2.filename.func`.\n * @returns The {@link ReactMutation} object with that name.\n *\n * @see https://docs.convex.dev/client/react#editing-data\n * @public\n */\nexport function useMutation<Mutation extends FunctionReference<\"mutation\">>(\n mutation: Mutation,\n): ReactMutation<Mutation> {\n const mutationReference =\n typeof mutation === \"string\"\n ? makeFunctionReference<\"mutation\", any, any>(mutation)\n : mutation;\n\n const convex = useContext(ConvexContext);\n if (convex === undefined) {\n throw new Error(\n \"Could not find Convex client! `useMutation` must be used in the React component \" +\n \"tree under `ConvexProvider`. Did you forget it? \" +\n \"See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app\",\n );\n }\n return useMemo(\n () => createMutation(mutationReference, convex),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [convex, getFunctionName(mutationReference)],\n );\n}\n\n/**\n * Construct a new {@link ReactAction}.\n *\n * Returns a function that you can call to execute a Convex action. Actions\n * can call third-party APIs and perform side effects. The returned function\n * is stable across renders (same reference identity).\n *\n * **Error handling:** Actions can fail (e.g., if an external API is down).\n * Always wrap action calls in try/catch or handle the rejected promise.\n *\n * **Note:** In most cases, calling an action directly from a client is an\n * anti-pattern. Prefer having the client call a mutation that captures the\n * user's intent (by writing to the database) and then schedules the action\n * via `ctx.scheduler.runAfter`. This ensures the intent is durably recorded\n * even if the client disconnects.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @example\n * ```tsx\n * import { useAction } from \"convex/react\";\n * import { api } from \"../convex/_generated/api\";\n *\n * function GenerateSummary() {\n * const generate = useAction(api.ai.generateSummary);\n *\n * const handleClick = async () => {\n * try {\n * const summary = await generate({ text: \"Some long text...\" });\n * console.log(summary);\n * } catch (error) {\n * console.error(\"Action failed:\", error);\n * }\n * };\n *\n * return <button onClick={handleClick}>Generate</button>;\n * }\n * ```\n *\n * @param action - A {@link server.FunctionReference} for the public action\n * to run like `api.dir1.dir2.filename.func`.\n * @returns The {@link ReactAction} object with that name.\n *\n * @see https://docs.convex.dev/functions/actions#calling-actions-from-clients\n * @public\n */\nexport function useAction<Action extends FunctionReference<\"action\">>(\n action: Action,\n): ReactAction<Action> {\n const convex = useContext(ConvexContext);\n const actionReference =\n typeof action === \"string\"\n ? makeFunctionReference<\"action\", any, any>(action)\n : action;\n\n if (convex === undefined) {\n throw new Error(\n \"Could not find Convex client! `useAction` must be used in the React component \" +\n \"tree under `ConvexProvider`. Did you forget it? \" +\n \"See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app\",\n );\n }\n return useMemo(\n () => createAction(actionReference, convex),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [convex, getFunctionName(actionReference)],\n );\n}\n\n/**\n * React hook to get the current {@link ConnectionState} and subscribe to changes.\n *\n * This hook returns the current connection state and automatically rerenders\n * when any part of the connection state changes (e.g., when going online/offline,\n * when requests start/complete, etc.).\n *\n * The shape of ConnectionState may change in the future which may cause this\n * hook to rerender more frequently.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @returns The current {@link ConnectionState} with the Convex backend.\n *\n * @public\n */\nexport function useConvexConnectionState(): ConnectionState {\n const convex = useContext(ConvexContext);\n if (convex === undefined) {\n throw new Error(\n \"Could not find Convex client! `useConvexConnectionState` must be used in the React component \" +\n \"tree under `ConvexProvider`. Did you forget it? \" +\n \"See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app\",\n );\n }\n\n const getCurrentValue = useCallback(() => {\n return convex.connectionState();\n }, [convex]);\n\n const subscribe = useCallback(\n (callback: () => void) => {\n return convex.subscribeToConnectionState(() => {\n callback();\n });\n },\n [convex],\n );\n\n return useSubscription({ getCurrentValue, subscribe });\n}\n\n// When a function is called with a single argument that looks like a\n// React SyntheticEvent it was likely called as an event handler.\nfunction assertNotAccidentalArgument(value: any) {\n // these are properties of a React.SyntheticEvent\n // https://reactjs.org/docs/events.html\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"bubbles\" in value &&\n \"persist\" in value &&\n \"isDefaultPrevented\" in value\n ) {\n throw new Error(\n `Convex function called with SyntheticEvent object. Did you use a Convex function as an event handler directly? Event handlers like onClick receive an event object as their first argument. These SyntheticEvent objects are not valid Convex values. Try wrapping the function like \\`const handler = () => myMutation();\\` and using \\`handler\\` in the event handler.`,\n );\n }\n}\n", "import { useEffect, useState } from \"react\";\n\n/*\nThis code is taken from https://gist.github.com/bvaughn/e25397f70e8c65b0ae0d7c90b731b189\nbecause correct subscriptions in async React is complex!\n\nIt could probably be replaced with `useSyncExternalStore()`.\n\nThe MIT License (MIT)\nCopyright \u00A9 2023 Brian Vaughn\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \u201CSoftware\u201D), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \u201CAS IS\u201D, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n/**\n * Hook used for safely managing subscriptions in concurrent mode.\n *\n * In order to avoid removing and re-adding subscriptions each time this hook is called,\n * the parameters passed to this hook should be memoized in some way\u2013\n * either by wrapping the entire params object with useMemo()\n * or by wrapping the individual callbacks with useCallback().\n *\n * @internal\n */\nexport function useSubscription<Value>({\n // (Synchronously) returns the current value of our subscription.\n getCurrentValue,\n\n // This function is passed an event handler to attach to the subscription.\n // It should return an unsubscribe function that removes the handler.\n subscribe,\n}: {\n getCurrentValue: () => Value;\n subscribe: (callback: () => void) => () => void;\n}): Value {\n // Read the current value from our subscription.\n // When this value changes, we'll schedule an update with React.\n // It's important to also store the hook params so that we can check for staleness.\n // (See the comment in checkForUpdates() below for more info.)\n const [state, setState] = useState(() => ({\n getCurrentValue,\n subscribe,\n value: getCurrentValue(),\n }));\n\n let valueToReturn = state.value;\n\n // If parameters have changed since our last render, schedule an update with its current value.\n if (\n state.getCurrentValue !== getCurrentValue ||\n state.subscribe !== subscribe\n ) {\n // If the subscription has been updated, we'll schedule another update with React.\n // React will process this update immediately, so the old subscription value won't be committed.\n // It is still nice to avoid returning a mismatched value though, so let's override the return value.\n valueToReturn = getCurrentValue();\n\n setState({\n getCurrentValue,\n subscribe,\n value: valueToReturn,\n });\n }\n\n // It is important not to subscribe while rendering because this can lead to memory leaks.\n // (Learn more at reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects)\n // Instead, we wait until the commit phase to attach our handler.\n //\n // We intentionally use a passive effect (useEffect) rather than a synchronous one (useLayoutEffect)\n // so that we don't stretch the commit phase.\n // This also has an added benefit when multiple components are subscribed to the same source:\n // It allows each of the event handlers to safely schedule work without potentially removing an another handler.\n // (Learn more at https://codesandbox.io/s/k0yvr5970o)\n useEffect(() => {\n let didUnsubscribe = false;\n\n const checkForUpdates = () => {\n // It's possible that this callback will be invoked even after being unsubscribed,\n // if it's removed as a result of a subscription event/update.\n // In this case, React will log a DEV warning about an update from an unmounted component.\n // We can avoid triggering that warning with this check.\n if (didUnsubscribe) {\n return;\n }\n\n setState((prevState) => {\n // Ignore values from stale sources!\n // Since we subscribe an unsubscribe in a passive effect,\n // it's possible that this callback will be invoked for a stale (previous) subscription.\n // This check avoids scheduling an update for that stale subscription.\n if (\n prevState.getCurrentValue !== getCurrentValue ||\n prevState.subscribe !== subscribe\n ) {\n return prevState;\n }\n\n // Some subscriptions will auto-invoke the handler, even if the value hasn't changed.\n // If the value hasn't changed, no update is needed.\n // Return state as-is so React can bail out and avoid an unnecessary render.\n const value = getCurrentValue();\n if (prevState.value === value) {\n return prevState;\n }\n\n return { ...prevState, value };\n });\n };\n const unsubscribe = subscribe(checkForUpdates);\n\n // Because we're subscribing in a passive effect,\n // it's possible that an update has occurred between render and our effect handler.\n // Check for this and schedule an update if work has occurred.\n checkForUpdates();\n\n return () => {\n didUnsubscribe = true;\n unsubscribe();\n };\n }, [getCurrentValue, subscribe]);\n\n // Return the current value for our caller to use while rendering.\n return valueToReturn;\n}\n", "import { convexToJson, Value } from \"../values/index.js\";\nimport { PaginatedWatch, Watch } from \"./client.js\";\nimport { QueryJournal } from \"../browser/sync/protocol.js\";\nimport { FunctionReference, getFunctionName } from \"../server/api.js\";\nimport { RequestForQueries } from \"./use_queries.js\";\nimport { PaginatedQueryResult } from \"../browser/sync/pagination.js\";\nimport { SubscribeToPaginatedQueryOptions } from \"../browser/sync/paginated_query_client.js\";\n\ntype Identifier = string;\n\ntype QueryInfo = {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n watch: Watch<Value> | PaginatedWatch<Value>;\n unsubscribe: () => void;\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n};\n\nexport interface CreateWatch {\n (\n query: FunctionReference<\"query\">,\n args: Record<string, Value>,\n options: {\n journal?: QueryJournal;\n // Just the existence of this option makes this a paginated query\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n },\n ): Watch<Value> | PaginatedWatch<Value>;\n}\n\n/**\n * A class for observing the results of multiple queries at the same time.\n *\n * Any time the result of a query changes, the listeners are notified.\n */\nexport class QueriesObserver {\n public createWatch: CreateWatch;\n private queries: Record<Identifier, QueryInfo>;\n private listeners: Set<() => void>;\n\n constructor(createWatch: CreateWatch) {\n this.createWatch = createWatch;\n this.queries = {};\n this.listeners = new Set();\n }\n\n setQueries(\n newQueries: Record<\n Identifier,\n {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n }\n >,\n ) {\n // Add the new queries before unsubscribing from the old ones so that\n // the deduping in the `ConvexReactClient` can help if there are duplicates.\n for (const identifier of Object.keys(newQueries)) {\n const { query, args, paginationOptions } = newQueries[identifier];\n // Might throw\n getFunctionName(query);\n\n if (this.queries[identifier] === undefined) {\n // No existing query => add it.\n this.addQuery(\n identifier,\n query,\n args,\n paginationOptions ? { paginationOptions } : {},\n );\n } else {\n const existingInfo = this.queries[identifier];\n\n if (\n getFunctionName(query) !== getFunctionName(existingInfo.query) ||\n JSON.stringify(convexToJson(args)) !==\n JSON.stringify(convexToJson(existingInfo.args)) ||\n JSON.stringify(paginationOptions) !==\n JSON.stringify(existingInfo.paginationOptions)\n ) {\n // Existing query that doesn't match => remove the old and add the new.\n this.removeQuery(identifier);\n this.addQuery(\n identifier,\n query,\n args,\n paginationOptions ? { paginationOptions } : {},\n );\n }\n }\n }\n\n // Prune all the existing queries that we no longer need.\n for (const identifier of Object.keys(this.queries)) {\n if (newQueries[identifier] === undefined) {\n this.removeQuery(identifier);\n }\n }\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n getLocalResults(\n queries: RequestForQueries,\n ): Record<\n Identifier,\n Value | undefined | Error | PaginatedQueryResult<Value>\n > {\n const result: Record<\n Identifier,\n Value | Error | undefined | PaginatedQueryResult<Value>\n > = {};\n for (const identifier of Object.keys(queries)) {\n const { query, args } = queries[identifier];\n const paginationOptions = queries[identifier].paginationOptions;\n\n // Might throw\n getFunctionName(query);\n\n // Note: We're not gonna watch, we could save some allocations\n // by getting a reference to the client directly instead.\n const watch = this.createWatch(\n query,\n args,\n paginationOptions ? { paginationOptions } : {},\n );\n\n let value: Value | undefined | Error | PaginatedQueryResult<Value>;\n try {\n value = watch.localQueryResult();\n } catch (e) {\n // Only collect instances of `Error` because thats how callers\n // will distinguish errors from normal results.\n if (e instanceof Error) {\n value = e;\n } else {\n throw e;\n }\n }\n result[identifier] = value;\n }\n return result;\n }\n\n setCreateWatch(createWatch: CreateWatch) {\n this.createWatch = createWatch;\n // If we have a new watch, we might be using a new Convex client.\n // Recreate all the watches being careful to preserve the journals.\n for (const identifier of Object.keys(this.queries)) {\n const { query, args, watch, paginationOptions } =\n this.queries[identifier];\n const journal = \"journal\" in watch ? watch.journal() : undefined;\n this.removeQuery(identifier);\n this.addQuery(identifier, query, args, {\n ...(journal ? { journal } : []),\n ...(paginationOptions ? { paginationOptions } : {}),\n });\n }\n }\n\n destroy() {\n for (const identifier of Object.keys(this.queries)) {\n this.removeQuery(identifier);\n }\n this.listeners = new Set();\n }\n\n private addQuery(\n identifier: Identifier,\n query: FunctionReference<\"query\">,\n args: Record<string, Value>,\n {\n paginationOptions,\n journal,\n }: {\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n journal?: QueryJournal;\n },\n ) {\n if (this.queries[identifier] !== undefined) {\n throw new Error(\n `Tried to add a new query with identifier ${identifier} when it already exists.`,\n );\n }\n const watch = this.createWatch(query, args, {\n ...(journal ? { journal } : []),\n ...(paginationOptions ? { paginationOptions } : {}),\n });\n const unsubscribe = watch.onUpdate(() => this.notifyListeners());\n this.queries[identifier] = {\n query,\n args,\n watch,\n unsubscribe,\n ...(paginationOptions ? { paginationOptions } : {}),\n };\n }\n\n private removeQuery(identifier: Identifier) {\n const info = this.queries[identifier];\n if (info === undefined) {\n throw new Error(`No query found with identifier ${identifier}.`);\n }\n info.unsubscribe();\n delete this.queries[identifier];\n }\n\n private notifyListeners(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n", "import { useState } from \"react\";\n\nimport { FunctionReference, getFunctionName } from \"../server/api.js\";\nimport {\n PaginatedQueryReference,\n PaginatedQueryArgs,\n UsePaginatedQueryOptions,\n UsePaginatedQueryReturnType,\n UsePaginatedQueryObjectReturnType,\n} from \"./use_paginated_query.js\";\nimport { convexToJson, Value } from \"../values/value.js\";\nimport { useQueries } from \"./use_queries.js\";\nimport { PaginatedQueryResult } from \"../browser/sync/pagination.js\";\nimport { SubscribeToPaginatedQueryOptions } from \"../browser/sync/paginated_query_client.js\";\nimport { ConvexError } from \"../values/errors.js\";\nimport { useConvex } from \"./client.js\";\n\ntype UsePaginatedQueryState = {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n id: number;\n queries: {\n paginatedQuery?: {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n paginationOptions: SubscribeToPaginatedQueryOptions;\n };\n };\n skip: boolean;\n};\n\n/**\n * Experimental new usePaginatedQuery implementation that will replace the current one\n * in the future.\n *\n * Load data reactively from a paginated query to a create a growing list.\n *\n * This is an alternate implementation that relies on new client pagination logic.\n *\n * This can be used to power \"infinite scroll\" UIs.\n *\n * This hook must be used with public query references that match\n * {@link PaginatedQueryReference}.\n *\n * `usePaginatedQuery` concatenates all the pages of results into a single list\n * and manages the continuation cursors when requesting more items.\n *\n * Example usage:\n * ```typescript\n * const { results, status, isLoading, loadMore } = usePaginatedQuery(\n * api.messages.list,\n * { channel: \"#general\" },\n * { initialNumItems: 5 }\n * );\n * ```\n *\n * If the query reference or arguments change, the pagination state will be reset\n * to the first page. Similarly, if any of the pages result in an InvalidCursor\n * error or an error associated with too much data, the pagination state will also\n * reset to the first page.\n *\n * To learn more about pagination, see [Paginated Queries](https://docs.convex.dev/database/pagination).\n *\n * @param query - A FunctionReference to the public query function to run.\n * @param args - The arguments object for the query function, excluding\n * the `paginationOpts` property. That property is injected by this hook.\n * @param options - An object specifying the `initialNumItems` to be loaded in\n * the first page.\n * @returns A {@link UsePaginatedQueryResult} that includes the currently loaded\n * items, the status of the pagination, and a `loadMore` function.\n *\n * @public\n */\nexport function usePaginatedQuery_experimental<\n Query extends PaginatedQueryReference,\n>(\n query: Query,\n args: PaginatedQueryArgs<Query> | \"skip\",\n // Future options this hook might accept:\n // - maximumRowsRead\n // - maximumBytesRead\n // - a cursor for where to start? although probably no endCursor\n options: { initialNumItems: number },\n): UsePaginatedQueryReturnType<Query>;\n\n/** @internal */\nexport function usePaginatedQuery_experimental<\n Query extends PaginatedQueryReference,\n>(\n options: UsePaginatedQueryOptions<Query>,\n): UsePaginatedQueryObjectReturnType<Query>;\n\nexport function usePaginatedQuery_experimental<\n Query extends PaginatedQueryReference,\n>(\n queryOrOptions: Query | UsePaginatedQueryOptions<Query>,\n args?: PaginatedQueryArgs<Query> | \"skip\",\n // Future options this hook might accept:\n // - maximumRowsRead\n // - maximumBytesRead\n // - a cursor for where to start? although probably no endCursor\n options?: { initialNumItems: number },\n):\n | UsePaginatedQueryReturnType<Query>\n | UsePaginatedQueryObjectReturnType<Query> {\n const isObjectOptions =\n typeof queryOrOptions === \"object\" &&\n queryOrOptions !== null &&\n \"query\" in queryOrOptions;\n\n const query = isObjectOptions ? queryOrOptions.query : queryOrOptions;\n const queryArgs = isObjectOptions ? queryOrOptions.args : args;\n const throwOnError = isObjectOptions\n ? (queryOrOptions.throwOnError ?? false)\n : true;\n const initialOptions = isObjectOptions\n ? { initialNumItems: queryOrOptions.initialNumItems }\n : options;\n\n if (\n typeof initialOptions?.initialNumItems !== \"number\" ||\n initialOptions.initialNumItems < 0\n ) {\n throw new Error(\n `\\`options.initialNumItems\\` must be a positive number. Received \\`${initialOptions?.initialNumItems}\\`.`,\n );\n }\n const skip = queryArgs === \"skip\";\n const argsObject = skip ? {} : queryArgs;\n\n const convexClient = useConvex();\n const logger = convexClient.logger;\n\n // The identity of createInitialState changes each time!\n const createInitialState: () => UsePaginatedQueryState = () => {\n const id = nextPaginationId();\n return {\n query,\n args: argsObject as Record<string, Value>,\n id,\n // Queries will contain zero or one queries forever.\n queries: skip\n ? ({} as UsePaginatedQueryState[\"queries\"])\n : {\n paginatedQuery: {\n query,\n args: {\n ...argsObject,\n },\n paginationOptions: {\n initialNumItems: initialOptions.initialNumItems,\n id,\n },\n },\n },\n skip,\n };\n };\n\n const [state, setState] =\n useState<UsePaginatedQueryState>(createInitialState);\n\n // `currState` is the state that we'll render based on.\n let currState = state;\n // New function, args, or skip? New paginated query!\n if (\n getFunctionName(query) !== getFunctionName(state.query) ||\n JSON.stringify(convexToJson(argsObject as Value)) !==\n JSON.stringify(convexToJson(state.args)) ||\n skip !== state.skip\n ) {\n currState = createInitialState();\n setState(currState);\n }\n // currState.queries is just a single query; we use useQueries\n // because it's the lower-level ook sthat supports pagination options.\n const resultsObject = useQueries(currState.queries);\n\n // skip\n if (!(\"paginatedQuery\" in resultsObject)) {\n if (!skip) {\n throw new Error(\"Why is it missing?\");\n }\n const internalResult = {\n results: [] as Query[\"_returnType\"][\"page\"],\n status: \"LoadingFirstPage\" as const,\n isLoading: true as const,\n loadMore: function skipNOP(_numItems: number) {\n return false;\n },\n };\n if (isObjectOptions) {\n return reshapeToObjectForm2(\n internalResult,\n ) as unknown as UsePaginatedQueryObjectReturnType<Query>;\n }\n return internalResult as unknown as UsePaginatedQueryReturnType<Query>;\n }\n const result = resultsObject.paginatedQuery as\n | PaginatedQueryResult<Query[\"_returnType\"][\"page\"][number]>\n | Error;\n\n // TODO this is a weird mix of responsibilities:\n // - is it the hook's job to render the initial loading state?\n // - or is it the paginated query's job to render the approproate loading state?\n // It comes back to why we'd ever get undefined when asking about a query; have we not yet called subscribe for it?\n if (result === undefined) {\n const internalResult = {\n results: [] as Query[\"_returnType\"][\"page\"],\n loadMore: () => false,\n isLoading: true as const,\n status: \"LoadingFirstPage\" as const,\n };\n if (isObjectOptions) {\n return reshapeToObjectForm2(\n internalResult,\n ) as unknown as UsePaginatedQueryObjectReturnType<Query>;\n }\n return internalResult as unknown as UsePaginatedQueryReturnType<Query>;\n }\n\n if (result instanceof Error) {\n if (\n result.message.includes(\"InvalidCursor\") ||\n (result instanceof ConvexError &&\n typeof result.data === \"object\" &&\n result.data?.isConvexSystemError === true &&\n result.data?.paginationError === \"InvalidCursor\")\n ) {\n // - InvalidCursor: If the cursor is invalid, probably the paginated\n // database query was data-dependent and changed underneath us. The\n // cursor in the params or journal no longer matches the current\n // database query.\n\n // In all cases, we want to restart pagination to throw away all our\n // existing cursors.\n logger.warn(\n \"usePaginatedQuery hit error, resetting pagination state: \" +\n result.message,\n );\n setState(createInitialState);\n const internalResult = {\n results: [] as Query[\"_returnType\"][\"page\"],\n loadMore: () => false,\n isLoading: true as const,\n status: \"LoadingFirstPage\" as const,\n };\n if (isObjectOptions) {\n return reshapeToObjectForm2(\n internalResult,\n ) as unknown as UsePaginatedQueryObjectReturnType<Query>;\n }\n return internalResult as unknown as UsePaginatedQueryReturnType<Query>;\n } else {\n if (throwOnError) {\n throw result;\n }\n const internalResult = {\n results: [] as Query[\"_returnType\"][\"page\"],\n loadMore: () => false,\n isLoading: false as const,\n status: \"Error\" as const,\n error: result,\n };\n if (isObjectOptions) {\n return reshapeToObjectForm2(\n internalResult,\n ) as unknown as UsePaginatedQueryObjectReturnType<Query>;\n }\n return internalResult as unknown as UsePaginatedQueryReturnType<Query>;\n }\n }\n\n const internalResult = {\n ...result,\n loadMore: (num: number) => {\n return result.loadMore(num);\n },\n isLoading:\n result.status === \"LoadingFirstPage\"\n ? (true as const)\n : result.status === \"LoadingMore\"\n ? (true as const)\n : (false as const),\n };\n if (isObjectOptions) {\n return reshapeToObjectForm2(\n internalResult,\n ) as unknown as UsePaginatedQueryObjectReturnType<Query>;\n }\n return internalResult as unknown as UsePaginatedQueryReturnType<Query>;\n}\n\n/**\n * Reshape the internal TitleCase pagination result into the object-form\n * return type with lowercase `status`, `canLoadMore`, and `data`.\n */\nfunction reshapeToObjectForm2<Item>(internal: {\n results: Item[];\n status: string;\n isLoading: boolean;\n loadMore: (...args: any[]) => any;\n error?: Error;\n}) {\n const { results, loadMore } = internal;\n if (internal.status === \"Error\" && \"error\" in internal) {\n return {\n data: results,\n status: \"error\" as const,\n canLoadMore: false as const,\n isLoading: false as const,\n error: internal.error,\n loadMore,\n };\n }\n if (\n internal.status === \"LoadingFirstPage\" ||\n internal.status === \"LoadingMore\"\n ) {\n return {\n data: internal.status === \"LoadingFirstPage\" ? undefined : results,\n status: \"pending\" as const,\n canLoadMore: false as const,\n isLoading: true as const,\n error: undefined,\n loadMore,\n };\n }\n // CanLoadMore or Exhausted\n return {\n data: results,\n status: \"success\" as const,\n canLoadMore: internal.status === \"CanLoadMore\",\n isLoading: false as const,\n error: undefined,\n loadMore,\n };\n}\n\nlet paginationId = 0;\n/**\n * See ./use_paginated_query for the purpose, but we may be able to get rid of this soon.\n *\n * @returns The pagination ID.\n */\nfunction nextPaginationId(): number {\n paginationId++;\n return paginationId;\n}\n\n/**\n * Reset pagination id for tests only, so tests know what it is.\n */\nexport function resetPaginationId() {\n paginationId = 0;\n}\n", "import React from \"react\";\nimport { ReactNode } from \"react\";\nimport { useConvexAuth } from \"./ConvexAuthState.js\";\n\n/**\n * Renders children if the client is authenticated.\n *\n * @public\n */\nexport function Authenticated({ children }: { children: ReactNode }) {\n const { isLoading, isAuthenticated } = useConvexAuth();\n if (isLoading || !isAuthenticated) {\n return null;\n }\n return <>{children}</>;\n}\n\n/**\n * Renders children if the client is using authentication but is not authenticated.\n *\n * @public\n */\nexport function Unauthenticated({ children }: { children: ReactNode }) {\n const { isLoading, isAuthenticated } = useConvexAuth();\n if (isLoading || isAuthenticated) {\n return null;\n }\n return <>{children}</>;\n}\n\n/**\n * Renders children if the client isn't using authentication or is in the process\n * of authenticating.\n *\n * @public\n */\nexport function AuthLoading({ children }: { children: ReactNode }) {\n const { isLoading } = useConvexAuth();\n if (!isLoading) {\n return null;\n }\n return <>{children}</>;\n}\n", "import React, {\n createContext,\n ReactNode,\n useContext,\n useEffect,\n useState,\n} from \"react\";\nimport { AuthTokenFetcher } from \"../browser/sync/client.js\";\nimport { ConvexProvider } from \"./client.js\";\n\n// Until we can import from our own entry points (requires TypeScript 4.7),\n// just describe the interface enough to help users pass the right type.\ntype IConvexReactClient = {\n setAuth(\n fetchToken: AuthTokenFetcher,\n onChange: (isAuthenticated: boolean) => void,\n ): void;\n clearAuth(): void;\n};\n\n/**\n * Type representing the state of an auth integration with Convex.\n *\n * @public\n */\nexport type ConvexAuthState = {\n isLoading: boolean;\n isAuthenticated: boolean;\n};\n\nconst ConvexAuthContext = createContext<ConvexAuthState>(undefined as any);\n\n/**\n * Get the {@link ConvexAuthState} within a React component.\n *\n * This relies on a Convex auth integration provider being above in the React\n * component tree.\n *\n * @returns The current {@link ConvexAuthState}.\n *\n * @public\n */\nexport function useConvexAuth(): {\n isLoading: boolean;\n isAuthenticated: boolean;\n} {\n const authContext = useContext(ConvexAuthContext);\n if (authContext === undefined) {\n throw new Error(\n \"Could not find `ConvexProviderWithAuth` (or `ConvexProviderWithClerk` \" +\n \"or `ConvexProviderWithAuth0`) \" +\n \"as an ancestor component. This component may be missing, or you \" +\n \"might have two instances of the `convex/react` module loaded in your \" +\n \"project.\",\n );\n }\n return authContext;\n}\n\n/**\n * A replacement for {@link ConvexProvider} which additionally provides\n * {@link ConvexAuthState} to descendants of this component.\n *\n * Use this to integrate any auth provider with Convex. The `useAuth` prop\n * should be a React hook that returns the provider's authentication state\n * and a function to fetch a JWT access token.\n *\n * If the `useAuth` prop function updates causing a rerender then auth state\n * will transition to loading and the `fetchAccessToken()` function called again.\n *\n * See [Custom Auth Integration](https://docs.convex.dev/auth/advanced/custom-auth) for more information.\n *\n * @public\n */\nexport function ConvexProviderWithAuth({\n children,\n client,\n useAuth,\n}: {\n children?: ReactNode;\n client: IConvexReactClient;\n useAuth: () => {\n isLoading: boolean;\n isAuthenticated: boolean;\n fetchAccessToken: (args: {\n forceRefreshToken: boolean;\n }) => Promise<string | null>;\n };\n}) {\n const {\n isLoading: authProviderLoading,\n isAuthenticated: authProviderAuthenticated,\n fetchAccessToken,\n } = useAuth();\n const [isConvexAuthenticated, setIsConvexAuthenticated] = useState<\n boolean | null\n >(null);\n\n // If the useAuth went back to the authProviderLoading state (which is unusual but possible)\n // reset the Convex auth state to null so that we can correctly\n // transition the state from \"loading\" to \"authenticated\"\n // without going through \"unauthenticated\".\n if (authProviderLoading && isConvexAuthenticated !== null) {\n setIsConvexAuthenticated(null);\n }\n\n // If the useAuth goes to not authenticated then isConvexAuthenticated should reflect that.\n if (\n !authProviderLoading &&\n !authProviderAuthenticated &&\n isConvexAuthenticated !== false\n ) {\n setIsConvexAuthenticated(false);\n }\n\n return (\n <ConvexAuthContext.Provider\n value={{\n isLoading: isConvexAuthenticated === null,\n isAuthenticated:\n authProviderAuthenticated && (isConvexAuthenticated ?? false),\n }}\n >\n <ConvexAuthStateFirstEffect\n authProviderAuthenticated={authProviderAuthenticated}\n fetchAccessToken={fetchAccessToken}\n authProviderLoading={authProviderLoading}\n client={client}\n setIsConvexAuthenticated={setIsConvexAuthenticated}\n />\n <ConvexProvider client={client as any}>{children}</ConvexProvider>\n <ConvexAuthStateLastEffect\n authProviderAuthenticated={authProviderAuthenticated}\n fetchAccessToken={fetchAccessToken}\n authProviderLoading={authProviderLoading}\n client={client}\n setIsConvexAuthenticated={setIsConvexAuthenticated}\n />\n </ConvexAuthContext.Provider>\n );\n}\n\n// First child ensures we `setAuth` before\n// other child components subscribe to queries via `useEffect`.\nfunction ConvexAuthStateFirstEffect({\n authProviderAuthenticated,\n fetchAccessToken,\n authProviderLoading,\n client,\n setIsConvexAuthenticated,\n}: {\n authProviderAuthenticated: boolean;\n fetchAccessToken: (args: {\n forceRefreshToken: boolean;\n }) => Promise<string | null>;\n authProviderLoading: boolean;\n client: IConvexReactClient;\n setIsConvexAuthenticated: React.Dispatch<\n React.SetStateAction<boolean | null>\n >;\n}) {\n useEffect(() => {\n let isThisEffectRelevant = true;\n if (authProviderAuthenticated) {\n client.setAuth(fetchAccessToken, (backendReportsIsAuthenticated) => {\n if (isThisEffectRelevant) {\n setIsConvexAuthenticated(() => backendReportsIsAuthenticated);\n }\n });\n return () => {\n isThisEffectRelevant = false;\n\n // If unmounting or something changed before we finished fetching the token\n // we shouldn't transition to a loaded state.\n setIsConvexAuthenticated((isConvexAuthenticated) =>\n isConvexAuthenticated ? false : null,\n );\n };\n }\n }, [\n authProviderAuthenticated,\n fetchAccessToken,\n authProviderLoading,\n client,\n setIsConvexAuthenticated,\n ]);\n return null;\n}\n\n// Last child ensures we `clearAuth` last,\n// so that queries from unmounted sibling components\n// unsubscribe first and don't rerun without auth on the server\nfunction ConvexAuthStateLastEffect({\n authProviderAuthenticated,\n fetchAccessToken,\n authProviderLoading,\n client,\n setIsConvexAuthenticated,\n}: {\n authProviderAuthenticated: boolean;\n fetchAccessToken: (args: {\n forceRefreshToken: boolean;\n }) => Promise<string | null>;\n authProviderLoading: boolean;\n client: IConvexReactClient;\n setIsConvexAuthenticated: React.Dispatch<\n React.SetStateAction<boolean | null>\n >;\n}) {\n useEffect(() => {\n // If rendered with authProviderAuthenticated=true then clear that auth on in cleanup.\n if (authProviderAuthenticated) {\n return () => {\n client.clearAuth();\n // Set state back to loading in case this is a transition from one\n // fetchToken function to another which signals a new auth context,\n // e.g. a new orgId from Clerk. Auth context changes like this\n // return isAuthenticated: true from useAuth() but if\n // useAuth reports isAuthenticated: false on the next render\n // then this null value will be overridden to false.\n setIsConvexAuthenticated(() => null);\n };\n }\n }, [\n authProviderAuthenticated,\n fetchAccessToken,\n authProviderLoading,\n client,\n setIsConvexAuthenticated,\n ]);\n return null;\n}\n", "import { useMemo } from \"react\";\nimport { useQuery } from \"../react/client.js\";\nimport { FunctionReference, makeFunctionReference } from \"../server/api.js\";\nimport { jsonToConvex } from \"../values/index.js\";\n\n/**\n * The preloaded query payload, which should be passed to a client component\n * and passed to {@link usePreloadedQuery}.\n *\n * @public\n */\nexport type Preloaded<Query extends FunctionReference<\"query\">> = {\n __type: Query;\n _name: string;\n _argsJSON: string;\n _valueJSON: string;\n};\n\n/**\n * Load a reactive query within a React component using a `Preloaded` payload\n * from a Server Component returned by {@link nextjs.preloadQuery}.\n *\n * This React hook contains internal state that will cause a rerender\n * whenever the query result changes.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @param preloadedQuery - The `Preloaded` query payload from a Server Component.\n * @returns the result of the query. Initially returns the result fetched\n * by the Server Component. Subsequently returns the result fetched by the client.\n *\n * @public\n */\nexport function usePreloadedQuery<Query extends FunctionReference<\"query\">>(\n preloadedQuery: Preloaded<Query>,\n): Query[\"_returnType\"] {\n const args = useMemo(\n () => jsonToConvex(preloadedQuery._argsJSON),\n [preloadedQuery._argsJSON],\n ) as Query[\"_args\"];\n const preloadedResult = useMemo(\n () => jsonToConvex(preloadedQuery._valueJSON),\n [preloadedQuery._valueJSON],\n );\n const result = useQuery(\n makeFunctionReference(preloadedQuery._name) as Query,\n args,\n );\n return result === undefined ? preloadedResult : result;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["module.exports = window.React", "/**\n * Tools to integrate Convex into React applications.\n *\n * This module contains:\n * 1. {@link ConvexReactClient}, a client for using Convex in React.\n * 2. {@link ConvexProvider}, a component that stores this client in React context.\n * 3. {@link Authenticated}, {@link Unauthenticated} and {@link AuthLoading} helper auth components.\n * 4. Hooks {@link useQuery}, {@link useMutation}, {@link useAction} and more for accessing this\n * client from your React components.\n *\n * ## Usage\n *\n * ### Creating the client\n *\n * ```typescript\n * import { ConvexReactClient } from \"convex/react\";\n *\n * // typically loaded from an environment variable\n * const address = \"https://small-mouse-123.convex.cloud\"\n * const convex = new ConvexReactClient(address);\n * ```\n *\n * ### Storing the client in React Context\n *\n * ```typescript\n * import { ConvexProvider } from \"convex/react\";\n *\n * <ConvexProvider client={convex}>\n * <App />\n * </ConvexProvider>\n * ```\n *\n * ### Using the auth helpers\n *\n * ```typescript\n * import { Authenticated, Unauthenticated, AuthLoading } from \"convex/react\";\n *\n * <Authenticated>\n * Logged in\n * </Authenticated>\n * <Unauthenticated>\n * Logged out\n * </Unauthenticated>\n * <AuthLoading>\n * Still loading\n * </AuthLoading>\n * ```\n *\n * ### Using React hooks\n *\n * ```typescript\n * import { useQuery, useMutation } from \"convex/react\";\n * import { api } from \"../convex/_generated/api\";\n *\n * function App() {\n * const counter = useQuery(api.getCounter.default);\n * const increment = useMutation(api.incrementCounter.default);\n * // Your component here!\n * }\n * ```\n * @module\n */\nexport * from \"./use_paginated_query.js\";\nexport {\n usePaginatedQuery_experimental,\n type UsePaginatedQueryOptions,\n type UsePaginatedQueryObjectReturnType,\n} from \"./use_paginated_query2.js\";\nexport { usePaginatedQuery } from \"./use_paginated_query.js\";\nexport { useQueries, type RequestForQueries } from \"./use_queries.js\";\nexport type { AuthTokenFetcher } from \"../browser/sync/client.js\";\nexport * from \"./auth_helpers.js\";\nexport * from \"./ConvexAuthState.js\";\nexport * from \"./hydration.js\";\n/* @internal */\nexport { useSubscription } from \"./use_subscription.js\";\nexport {\n type ReactMutation,\n type ReactAction,\n type Watch,\n type WatchQueryOptions,\n type MutationOptions,\n type ConvexReactClientOptions,\n type OptionalRestArgsOrSkip,\n ConvexReactClient,\n useConvex,\n ConvexProvider,\n useQuery,\n useQuery_experimental,\n useMutation,\n useAction,\n useConvexConnectionState,\n} from \"./client.js\";\n/** @internal */\nexport type { UseQueryResult } from \"./client.js\";\n/** @internal */\nexport { convexQueryOptions } from \"../browser/query_options.js\";\nexport type { QueryOptions } from \"../browser/query_options.js\";\n", "import { useMemo, useState } from \"react\";\n\nimport { OptimisticLocalStore } from \"../browser/index.js\";\nimport {\n FunctionReturnType,\n PaginationOptions,\n paginationOptsValidator,\n PaginationResult,\n} from \"../server/index.js\";\nimport { ConvexError, convexToJson, Infer, Value } from \"../values/index.js\";\nimport { useQueries } from \"./use_queries.js\";\nimport {\n FunctionArgs,\n FunctionReference,\n getFunctionName,\n} from \"../server/api.js\";\nimport { BetterOmit, Expand } from \"../type_utils.js\";\nimport { useConvex } from \"./client.js\";\nimport { compareValues } from \"../values/compare.js\";\n\n/**\n * A {@link server.FunctionReference} that is usable with {@link usePaginatedQuery}.\n *\n * This function reference must:\n * - Refer to a public query\n * - Have an argument named \"paginationOpts\" of type {@link server.PaginationOptions}\n * - Have a return type of {@link server.PaginationResult}.\n *\n * @public\n */\nexport type PaginatedQueryReference = FunctionReference<\n \"query\",\n \"public\",\n { paginationOpts: PaginationOptions },\n PaginationResult<any>\n>;\n\n// Incrementing integer for each page queried in the usePaginatedQuery hook.\ntype QueryPageKey = number;\n\ntype UsePaginatedQueryState = {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n id: number;\n nextPageKey: QueryPageKey;\n pageKeys: QueryPageKey[];\n queries: Record<\n QueryPageKey,\n {\n query: FunctionReference<\"query\">;\n // Use the validator type as a test that it matches the args\n // we generate.\n args: { paginationOpts: Infer<typeof paginationOptsValidator> };\n }\n >;\n ongoingSplits: Record<QueryPageKey, [QueryPageKey, QueryPageKey]>;\n skip: boolean;\n};\n\nconst splitQuery =\n (key: QueryPageKey, splitCursor: string, continueCursor: string) =>\n (prevState: UsePaginatedQueryState) => {\n const queries = { ...prevState.queries };\n const splitKey1 = prevState.nextPageKey;\n const splitKey2 = prevState.nextPageKey + 1;\n const nextPageKey = prevState.nextPageKey + 2;\n queries[splitKey1] = {\n query: prevState.query,\n args: {\n ...prevState.args,\n paginationOpts: {\n ...prevState.queries[key].args.paginationOpts,\n endCursor: splitCursor,\n },\n },\n };\n queries[splitKey2] = {\n query: prevState.query,\n args: {\n ...prevState.args,\n paginationOpts: {\n ...prevState.queries[key].args.paginationOpts,\n cursor: splitCursor,\n endCursor: continueCursor,\n },\n },\n };\n const ongoingSplits = { ...prevState.ongoingSplits };\n ongoingSplits[key] = [splitKey1, splitKey2];\n return {\n ...prevState,\n nextPageKey,\n queries,\n ongoingSplits,\n };\n };\n\nconst completeSplitQuery =\n (key: QueryPageKey) => (prevState: UsePaginatedQueryState) => {\n const completedSplit = prevState.ongoingSplits[key];\n if (completedSplit === undefined) {\n return prevState;\n }\n const queries = { ...prevState.queries };\n delete queries[key];\n const ongoingSplits = { ...prevState.ongoingSplits };\n delete ongoingSplits[key];\n let pageKeys = prevState.pageKeys.slice();\n const pageIndex = prevState.pageKeys.findIndex((v) => v === key);\n if (pageIndex >= 0) {\n pageKeys = [\n ...prevState.pageKeys.slice(0, pageIndex),\n ...completedSplit,\n ...prevState.pageKeys.slice(pageIndex + 1),\n ];\n }\n return {\n ...prevState,\n queries,\n pageKeys,\n ongoingSplits,\n };\n };\n\n/**\n * Load data reactively from a paginated query to a create a growing list.\n *\n * This can be used to power \"infinite scroll\" UIs.\n *\n * This hook must be used with public query references that match\n * {@link PaginatedQueryReference}.\n *\n * `usePaginatedQuery` concatenates all the pages of results into a single list\n * and manages the continuation cursors when requesting more items.\n *\n * Example usage:\n * ```typescript\n * const { results, status, isLoading, loadMore } = usePaginatedQuery(\n * api.messages.list,\n * { channel: \"#general\" },\n * { initialNumItems: 5 }\n * );\n * ```\n *\n * If the query reference or arguments change, the pagination state will be reset\n * to the first page. Similarly, if any of the pages result in an InvalidCursor\n * error or an error associated with too much data, the pagination state will also\n * reset to the first page.\n *\n * To learn more about pagination, see [Paginated Queries](https://docs.convex.dev/database/pagination).\n *\n * @param query - A FunctionReference to the public query function to run.\n * @param args - The arguments object for the query function, excluding\n * the `paginationOpts` property. That property is injected by this hook.\n * @param options - An object specifying the `initialNumItems` to be loaded in\n * the first page.\n * @returns A {@link UsePaginatedQueryResult} that includes the currently loaded\n * items, the status of the pagination, and a `loadMore` function.\n *\n * @public\n */\nexport function usePaginatedQuery<Query extends PaginatedQueryReference>(\n query: Query,\n args: PaginatedQueryArgs<Query> | \"skip\",\n options: { initialNumItems: number },\n): UsePaginatedQueryReturnType<Query>;\n\nexport function usePaginatedQuery<Query extends PaginatedQueryReference>(\n query: Query,\n args: PaginatedQueryArgs<Query> | \"skip\",\n options: { initialNumItems: number },\n): UsePaginatedQueryReturnType<Query> {\n const { user: positionalResult } = usePaginatedQueryInternal(\n query,\n args,\n options,\n true,\n );\n return positionalResult as unknown as UsePaginatedQueryReturnType<Query>;\n}\n\n/** @internal */\nexport const includePage = Symbol(\"includePageKeys\");\n\n/** @internal */\nexport const page = Symbol(\"page\");\n\n/**\n * @internal\n */\nexport function usePaginatedQueryInternal<\n Query extends PaginatedQueryReference,\n>(\n query: Query,\n args: PaginatedQueryArgs<Query> | \"skip\",\n options: {\n initialNumItems: number;\n [includePage]?: boolean;\n },\n throwOnError: boolean = true,\n): {\n user: UsePaginatedQueryInternalResult<PaginatedQueryItem<Query>>;\n internal: { state: UsePaginatedQueryState };\n} {\n if (\n typeof options?.initialNumItems !== \"number\" ||\n options.initialNumItems < 0\n ) {\n throw new Error(\n `\\`options.initialNumItems\\` must be a positive number. Received \\`${options?.initialNumItems}\\`.`,\n );\n }\n const skip = args === \"skip\";\n const argsObject = skip ? {} : args;\n const queryName = getFunctionName(query);\n const createInitialState = useMemo(() => {\n return () => {\n const id = nextPaginationId();\n return {\n query,\n args: argsObject as Record<string, Value>,\n id,\n nextPageKey: 1,\n pageKeys: skip ? [] : [0],\n queries: skip\n ? ({} as UsePaginatedQueryState[\"queries\"])\n : {\n 0: {\n query,\n args: {\n ...argsObject,\n paginationOpts: {\n numItems: options.initialNumItems,\n cursor: null,\n id,\n },\n },\n },\n },\n ongoingSplits: {},\n skip,\n };\n };\n // ESLint doesn't like that we're stringifying the args. We do this because\n // we want to avoid rerendering if the args are a different\n // object that serializes to the same result.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(convexToJson(argsObject as Value)),\n queryName,\n options.initialNumItems,\n skip,\n ]);\n\n const [state, setState] =\n useState<UsePaginatedQueryState>(createInitialState);\n\n // `currState` is the state that we'll render based on.\n let currState = state;\n if (\n getFunctionName(query) !== getFunctionName(state.query) ||\n JSON.stringify(convexToJson(argsObject as Value)) !==\n JSON.stringify(convexToJson(state.args)) ||\n skip !== state.skip\n ) {\n currState = createInitialState();\n setState(currState);\n }\n const convexClient = useConvex();\n const logger = convexClient.logger;\n\n const resultsObject = useQueries(currState.queries);\n\n const isIncludingPageKeys = options[includePage] ?? false;\n const [results, maybeLastResult, maybeError]: [\n Value[],\n undefined | PaginationResult<Value>,\n undefined | Error,\n ] = useMemo(() => {\n let currResult = undefined;\n\n const allItems = [];\n for (const pageKey of currState.pageKeys) {\n currResult = resultsObject[pageKey];\n if (currResult === undefined) {\n break;\n }\n\n if (currResult instanceof Error) {\n if (\n currResult.message.includes(\"InvalidCursor\") ||\n (currResult instanceof ConvexError &&\n typeof currResult.data === \"object\" &&\n currResult.data?.isConvexSystemError === true &&\n currResult.data?.paginationError === \"InvalidCursor\")\n ) {\n // - InvalidCursor: If the cursor is invalid, probably the paginated\n // database query was data-dependent and changed underneath us. The\n // cursor in the params or journal no longer matches the current\n // database query.\n\n // In all cases, we want to restart pagination to throw away all our\n // existing cursors.\n logger.warn(\n \"usePaginatedQuery hit error, resetting pagination state: \" +\n currResult.message,\n );\n setState(createInitialState);\n return [[], undefined, undefined];\n } else {\n if (throwOnError) {\n throw currResult;\n }\n return [allItems, undefined, currResult];\n }\n }\n const ongoingSplit = currState.ongoingSplits[pageKey];\n if (ongoingSplit !== undefined) {\n if (\n resultsObject[ongoingSplit[0]] !== undefined &&\n resultsObject[ongoingSplit[1]] !== undefined\n ) {\n // Both pages of the split have results now. Swap them in.\n setState(completeSplitQuery(pageKey));\n }\n } else if (\n currResult.splitCursor &&\n (currResult.pageStatus === \"SplitRecommended\" ||\n currResult.pageStatus === \"SplitRequired\" ||\n currResult.page.length > options.initialNumItems * 2)\n ) {\n // If a single page has more than double the expected number of items,\n // or if the server requests a split, split the page into two.\n setState(\n splitQuery(\n pageKey,\n currResult.splitCursor,\n currResult.continueCursor,\n ),\n );\n }\n if (currResult.pageStatus === \"SplitRequired\") {\n // If pageStatus is 'SplitRequired', it means the server was not able to\n // fetch the full page. So we stop results before the incomplete\n // page and return 'LoadingMore' while the page is splitting.\n return [allItems, undefined, undefined];\n }\n allItems.push(\n ...(isIncludingPageKeys\n ? currResult.page.map((i: any) => ({\n ...i,\n [page]: pageKey.toString(),\n }))\n : currResult.page),\n );\n }\n return [allItems, currResult, undefined];\n }, [\n resultsObject,\n currState.pageKeys,\n currState.ongoingSplits,\n options.initialNumItems,\n createInitialState,\n logger,\n isIncludingPageKeys,\n throwOnError,\n ]);\n\n const statusObject = useMemo(() => {\n if (maybeError !== undefined) {\n return {\n status: \"Error\",\n isLoading: false,\n error: maybeError,\n loadMore: () => {\n // Intentional noop.\n },\n } as const;\n }\n if (maybeLastResult === undefined) {\n if (currState.nextPageKey === 1) {\n return {\n status: \"LoadingFirstPage\",\n isLoading: true,\n loadMore: () => {\n // Intentional noop.\n },\n } as const;\n } else {\n return {\n status: \"LoadingMore\",\n isLoading: true,\n loadMore: (_numItems: number) => {\n // Intentional noop.\n },\n } as const;\n }\n }\n if (maybeLastResult.isDone) {\n return {\n status: \"Exhausted\",\n isLoading: false,\n loadMore: (_numItems: number) => {\n // Intentional noop.\n },\n } as const;\n }\n const continueCursor = maybeLastResult.continueCursor;\n let alreadyLoadingMore = false;\n return {\n status: \"CanLoadMore\",\n isLoading: false,\n loadMore: (numItems: number) => {\n if (!alreadyLoadingMore) {\n alreadyLoadingMore = true;\n setState((prevState) => {\n const pageKeys = [...prevState.pageKeys, prevState.nextPageKey];\n const queries = { ...prevState.queries };\n queries[prevState.nextPageKey] = {\n query: prevState.query,\n args: {\n ...prevState.args,\n paginationOpts: {\n numItems,\n cursor: continueCursor,\n id: prevState.id,\n },\n },\n };\n return {\n ...prevState,\n nextPageKey: prevState.nextPageKey + 1,\n pageKeys,\n queries,\n };\n });\n }\n },\n } as const;\n }, [maybeError, maybeLastResult, currState.nextPageKey]);\n\n return {\n user: {\n results,\n ...statusObject,\n },\n internal: { state: currState },\n };\n}\n\nlet paginationId = 0;\n/**\n * Generate a new, unique ID for a pagination session.\n *\n * Every usage of {@link usePaginatedQuery} puts a unique ID into the\n * query function arguments as a \"cache-buster\". This serves two purposes:\n *\n * 1. All calls to {@link usePaginatedQuery} have independent query\n * journals.\n *\n * Every time we start a new pagination session, we'll load the first page of\n * results and receive a fresh journal. Without the ID, we might instead reuse\n * a query subscription already present in our client. This isn't desirable\n * because the existing query function result may have grown or shrunk from the\n * requested `initialNumItems`.\n *\n * 2. We can restart the pagination session on some types of errors.\n *\n * Sometimes we want to restart pagination from the beginning if we hit an error.\n * Similar to (1), we'd like to ensure that this new session actually requests\n * its first page from the server and doesn't reuse a query result already\n * present in the client that may have hit the error.\n *\n * @returns The pagination ID.\n */\nfunction nextPaginationId(): number {\n paginationId++;\n return paginationId;\n}\n\n/**\n * Reset pagination id for tests only, so tests know what it is.\n */\nexport function resetPaginationId() {\n paginationId = 0;\n}\n\n/**\n * The result of calling the {@link usePaginatedQuery} hook.\n *\n * This includes:\n * - `results` - An array of the currently loaded results.\n * - `isLoading` - Whether the hook is currently loading results.\n * - `status` - The status of the pagination. The possible statuses are:\n * - \"LoadingFirstPage\": The hook is loading the first page of results.\n * - \"CanLoadMore\": This query may have more items to fetch. Call `loadMore` to\n * fetch another page.\n * - \"LoadingMore\": We're currently loading another page of results.\n * - \"Exhausted\": We've paginated to the end of the list.\n * - `loadMore(n)` A callback to fetch more results. This will only fetch more\n * results if the status is \"CanLoadMore\".\n *\n * @public\n */\nexport type UsePaginatedQueryResult<Item> = {\n results: Item[];\n loadMore: (numItems: number) => void;\n} & (\n | {\n status: \"LoadingFirstPage\";\n isLoading: true;\n }\n | {\n status: \"CanLoadMore\";\n isLoading: false;\n }\n | {\n status: \"LoadingMore\";\n isLoading: true;\n }\n | {\n status: \"Exhausted\";\n isLoading: false;\n }\n);\n\n/**\n * @internal\n */\nexport type UsePaginatedQueryInternalResult<Item> =\n | UsePaginatedQueryResult<Item>\n | {\n results: Item[];\n status: \"Error\";\n isLoading: false;\n error: Error;\n loadMore: (numItems: number) => void;\n };\n\n/**\n * The possible pagination statuses in {@link UsePaginatedQueryResult}.\n *\n * This is a union of string literal types.\n * @public\n */\nexport type PaginationStatus = UsePaginatedQueryResult<any>[\"status\"];\n\n/**\n * Given a {@link PaginatedQueryReference}, get the type of the arguments\n * object for the query, excluding the `paginationOpts` argument.\n *\n * @public\n */\nexport type PaginatedQueryArgs<Query extends PaginatedQueryReference> = Expand<\n BetterOmit<FunctionArgs<Query>, \"paginationOpts\">\n>;\n\n/**\n * Given a {@link PaginatedQueryReference}, get the type of the item being\n * paginated over.\n * @public\n */\nexport type PaginatedQueryItem<Query extends PaginatedQueryReference> =\n FunctionReturnType<Query>[\"page\"][number];\n\n/**\n * The return type of {@link usePaginatedQuery}.\n *\n * @public\n */\nexport type UsePaginatedQueryReturnType<Query extends PaginatedQueryReference> =\n UsePaginatedQueryResult<PaginatedQueryItem<Query>>;\n\n/**\n * Optimistically update the values in a paginated list.\n *\n * This optimistic update is designed to be used to update data loaded with\n * {@link usePaginatedQuery}. It updates the list by applying\n * `updateValue` to each element of the list across all of the loaded pages.\n *\n * This will only apply to queries with a matching names and arguments.\n *\n * Example usage:\n * ```ts\n * const myMutation = useMutation(api.myModule.myMutation)\n * .withOptimisticUpdate((localStore, mutationArg) => {\n *\n * // Optimistically update the document with ID `mutationArg`\n * // to have an additional property.\n *\n * optimisticallyUpdateValueInPaginatedQuery(\n * localStore,\n * api.myModule.paginatedQuery\n * {},\n * currentValue => {\n * if (mutationArg === currentValue._id) {\n * return {\n * ...currentValue,\n * \"newProperty\": \"newValue\",\n * };\n * }\n * return currentValue;\n * }\n * );\n *\n * });\n * ```\n *\n * @param localStore - An {@link OptimisticLocalStore} to update.\n * @param query - A {@link FunctionReference} for the paginated query to update.\n * @param args - The arguments object to the query function, excluding the\n * `paginationOpts` property.\n * @param updateValue - A function to produce the new values.\n *\n * @public\n */\nexport function optimisticallyUpdateValueInPaginatedQuery<\n Query extends PaginatedQueryReference,\n>(\n localStore: OptimisticLocalStore,\n query: Query,\n args: PaginatedQueryArgs<Query>,\n updateValue: (\n currentValue: PaginatedQueryItem<Query>,\n ) => PaginatedQueryItem<Query>,\n): void {\n const expectedArgs = JSON.stringify(convexToJson(args as Value));\n\n for (const queryResult of localStore.getAllQueries(query)) {\n if (queryResult.value !== undefined) {\n const { paginationOpts: _, ...innerArgs } = queryResult.args as {\n paginationOpts: PaginationOptions;\n };\n if (JSON.stringify(convexToJson(innerArgs as Value)) === expectedArgs) {\n const value = queryResult.value;\n if (\n typeof value === \"object\" &&\n value !== null &&\n Array.isArray(value.page)\n ) {\n localStore.setQuery(query, queryResult.args, {\n ...value,\n page: value.page.map(updateValue),\n });\n }\n }\n }\n }\n}\n\n/**\n * Updates a paginated query to insert an element at the top of the list.\n *\n * This is regardless of the sort order, so if the list is in descending order,\n * the inserted element will be treated as the \"biggest\" element, but if it's\n * ascending, it'll be treated as the \"smallest\".\n *\n * Example:\n * ```ts\n * const createTask = useMutation(api.tasks.create)\n * .withOptimisticUpdate((localStore, mutationArgs) => {\n * insertAtTop({\n * paginatedQuery: api.tasks.list,\n * argsToMatch: { listId: mutationArgs.listId },\n * localQueryStore: localStore,\n * item: { _id: crypto.randomUUID() as Id<\"tasks\">, title: mutationArgs.title, completed: false },\n * });\n * });\n * ```\n *\n * @param options.paginatedQuery - A function reference to the paginated query.\n * @param options.argsToMatch - Optional arguments that must be in each relevant paginated query.\n * This is useful if you use the same query function with different arguments to load\n * different lists.\n * @param options.localQueryStore\n * @param options.item The item to insert.\n * @returns\n */\nexport function insertAtTop<Query extends PaginatedQueryReference>(options: {\n paginatedQuery: Query;\n argsToMatch?: Partial<PaginatedQueryArgs<Query>>;\n localQueryStore: OptimisticLocalStore;\n item: PaginatedQueryItem<Query>;\n}) {\n const { paginatedQuery, argsToMatch, localQueryStore, item } = options;\n const queries = localQueryStore.getAllQueries(paginatedQuery);\n const queriesThatMatch = queries.filter((q) => {\n if (argsToMatch === undefined) {\n return true;\n }\n return Object.keys(argsToMatch).every(\n // @ts-expect-error -- This should be safe since both should be plain objects\n (k) => compareValues(argsToMatch[k], q.args[k]) === 0,\n );\n });\n const firstPage = queriesThatMatch.find(\n (q) => q.args.paginationOpts.cursor === null,\n );\n if (firstPage === undefined || firstPage.value === undefined) {\n // first page is not loaded, so don't update it until it loads\n return;\n }\n localQueryStore.setQuery(paginatedQuery, firstPage.args, {\n ...firstPage.value,\n page: [item, ...firstPage.value.page],\n });\n}\n\n/**\n * Updates a paginated query to insert an element at the bottom of the list.\n *\n * This is regardless of the sort order, so if the list is in descending order,\n * the inserted element will be treated as the \"smallest\" element, but if it's\n * ascending, it'll be treated as the \"biggest\".\n *\n * This only has an effect if the last page is loaded, since otherwise it would result\n * in the element being inserted at the end of whatever is loaded (which is the middle of the list)\n * and then popping out once the optimistic update is over.\n *\n * @param options.paginatedQuery - A function reference to the paginated query.\n * @param options.argsToMatch - Optional arguments that must be in each relevant paginated query.\n * This is useful if you use the same query function with different arguments to load\n * different lists.\n * @param options.localQueryStore\n * @param options.element The element to insert.\n * @returns\n */\nexport function insertAtBottomIfLoaded<\n Query extends PaginatedQueryReference,\n>(options: {\n paginatedQuery: Query;\n argsToMatch?: Partial<PaginatedQueryArgs<Query>>;\n localQueryStore: OptimisticLocalStore;\n item: PaginatedQueryItem<Query>;\n}) {\n const { paginatedQuery, localQueryStore, item, argsToMatch } = options;\n const queries = localQueryStore.getAllQueries(paginatedQuery);\n const queriesThatMatch = queries.filter((q) => {\n if (argsToMatch === undefined) {\n return true;\n }\n return Object.keys(argsToMatch).every(\n // @ts-expect-error -- This should be safe since both should be plain objects\n (k) => compareValues(argsToMatch[k], q.args[k]) === 0,\n );\n });\n const lastPage = queriesThatMatch.find(\n (q) => q.value !== undefined && q.value.isDone,\n );\n if (lastPage === undefined) {\n // last page is not loaded, so don't update it since the item would immediately pop out\n // when the server updates\n return;\n }\n localQueryStore.setQuery(paginatedQuery, lastPage.args, {\n ...lastPage.value!,\n page: [...lastPage.value!.page, item],\n });\n}\n\ntype LocalQueryResult<Query extends FunctionReference<\"query\">> = {\n args: FunctionArgs<Query>;\n value: undefined | FunctionReturnType<Query>;\n};\n\ntype LoadedResult<Query extends FunctionReference<\"query\">> = {\n args: FunctionArgs<Query>;\n value: FunctionReturnType<Query>;\n};\n\n/**\n * This is a helper function for inserting an item at a specific position in a paginated query.\n *\n * You must provide the sortOrder and a function for deriving the sort key (an array of values) from an item in the list.\n *\n * This will only work if the server query uses the same sort order and sort key as the optimistic update.\n *\n * Example:\n * ```ts\n * const createTask = useMutation(api.tasks.create)\n * .withOptimisticUpdate((localStore, mutationArgs) => {\n * insertAtPosition({\n * paginatedQuery: api.tasks.listByPriority,\n * argsToMatch: { listId: mutationArgs.listId },\n * sortOrder: \"asc\",\n * sortKeyFromItem: (item) => [item.priority, item._creationTime],\n * localQueryStore: localStore,\n * item: {\n * _id: crypto.randomUUID() as Id<\"tasks\">,\n * _creationTime: Date.now(),\n * title: mutationArgs.title,\n * completed: false,\n * priority: mutationArgs.priority,\n * },\n * });\n * });\n * ```\n * @param options.paginatedQuery - A function reference to the paginated query.\n * @param options.argsToMatch - Optional arguments that must be in each relevant paginated query.\n * This is useful if you use the same query function with different arguments to load\n * different lists.\n * @param options.sortOrder - The sort order of the paginated query (\"asc\" or \"desc\").\n * @param options.sortKeyFromItem - A function for deriving the sort key (an array of values) from an element in the list.\n * Including a tie-breaker field like `_creationTime` is recommended.\n * @param options.localQueryStore\n * @param options.item - The item to insert.\n * @returns\n */\nexport function insertAtPosition<\n Query extends PaginatedQueryReference,\n>(options: {\n paginatedQuery: Query;\n argsToMatch?: Partial<PaginatedQueryArgs<Query>>;\n sortOrder: \"asc\" | \"desc\";\n sortKeyFromItem: (element: PaginatedQueryItem<Query>) => Value | Value[];\n localQueryStore: OptimisticLocalStore;\n item: PaginatedQueryItem<Query>;\n}) {\n const {\n paginatedQuery,\n sortOrder,\n sortKeyFromItem,\n localQueryStore,\n item,\n argsToMatch,\n } = options;\n\n const queries: LocalQueryResult<Query>[] =\n localQueryStore.getAllQueries(paginatedQuery);\n // Group into sets of pages for the same usePaginatedQuery. Grouping is by all\n // args except paginationOpts, but including paginationOpts.id.\n const queryGroups: Record<string, LocalQueryResult<Query>[]> = {};\n for (const query of queries) {\n if (\n argsToMatch !== undefined &&\n !Object.keys(argsToMatch).every(\n (k) =>\n // @ts-ignore why is this not working?\n argsToMatch[k] === query.args[k],\n )\n ) {\n continue;\n }\n const key = JSON.stringify(\n Object.fromEntries(\n Object.entries(query.args).map(([k, v]) => [\n k,\n k === \"paginationOpts\" ? (v as any).id : v,\n ]),\n ),\n );\n queryGroups[key] ??= [];\n queryGroups[key].push(query);\n }\n for (const pageQueries of Object.values(queryGroups)) {\n insertAtPositionInPages({\n pageQueries,\n paginatedQuery,\n sortOrder,\n sortKeyFromItem,\n localQueryStore,\n item,\n });\n }\n}\n\nfunction insertAtPositionInPages<\n Query extends PaginatedQueryReference,\n>(options: {\n pageQueries: LocalQueryResult<Query>[];\n paginatedQuery: Query;\n sortOrder: \"asc\" | \"desc\";\n sortKeyFromItem: (element: PaginatedQueryItem<Query>) => Value | Value[];\n localQueryStore: OptimisticLocalStore;\n item: PaginatedQueryItem<Query>;\n}) {\n const {\n pageQueries,\n sortOrder,\n sortKeyFromItem,\n localQueryStore,\n item,\n paginatedQuery,\n } = options;\n const insertedKey = sortKeyFromItem(item);\n const loadedPages: LoadedResult<Query>[] = pageQueries.filter(\n (q): q is LoadedResult<Query> =>\n q.value !== undefined && q.value.page.length > 0,\n );\n const sortedPages = loadedPages.sort((a, b) => {\n const aKey = sortKeyFromItem(a.value.page[0]);\n const bKey = sortKeyFromItem(b.value.page[0]);\n if (sortOrder === \"asc\") {\n return compareValues(aKey, bKey);\n } else {\n return compareValues(bKey, aKey);\n }\n });\n\n // check if the inserted element is before the first page\n const firstLoadedPage = sortedPages[0];\n if (firstLoadedPage === undefined) {\n // no pages, so don't update until they load\n return;\n }\n const firstPageKey = sortKeyFromItem(firstLoadedPage.value.page[0]);\n const isBeforeFirstPage =\n sortOrder === \"asc\"\n ? compareValues(insertedKey, firstPageKey) <= 0\n : compareValues(insertedKey, firstPageKey) >= 0;\n if (isBeforeFirstPage) {\n if (firstLoadedPage.args.paginationOpts.cursor === null) {\n localQueryStore.setQuery(paginatedQuery, firstLoadedPage.args, {\n ...firstLoadedPage.value,\n page: [item, ...firstLoadedPage.value.page],\n });\n } else {\n // if the very first page is not loaded\n return;\n }\n return;\n }\n\n const lastLoadedPage = sortedPages[sortedPages.length - 1];\n if (lastLoadedPage === undefined) {\n // no pages, so don't update until they load\n return;\n }\n const lastPageKey = sortKeyFromItem(\n lastLoadedPage.value.page[lastLoadedPage.value.page.length - 1],\n );\n const isAfterLastPage =\n sortOrder === \"asc\"\n ? compareValues(insertedKey, lastPageKey) >= 0\n : compareValues(insertedKey, lastPageKey) <= 0;\n if (isAfterLastPage) {\n // Only update if the last page is done loading, otherwise it will pop out\n // when the server updates the query\n if (lastLoadedPage.value.isDone) {\n localQueryStore.setQuery(paginatedQuery, lastLoadedPage.args, {\n ...lastLoadedPage.value,\n page: [...lastLoadedPage.value.page, item],\n });\n }\n return;\n }\n\n // if sorted in ascending order, find the first page that starts with a key greater than the inserted element,\n // and update the page before it\n // if sorted in descending order, find the first page that starts with a key less than the inserted element,\n // and update the page before it\n\n const successorPageIndex = sortedPages.findIndex((p) =>\n sortOrder === \"asc\"\n ? compareValues(sortKeyFromItem(p.value.page[0]), insertedKey) > 0\n : compareValues(sortKeyFromItem(p.value.page[0]), insertedKey) < 0,\n );\n const pageToUpdate =\n successorPageIndex === -1\n ? sortedPages[sortedPages.length - 1]\n : sortedPages[successorPageIndex - 1];\n if (pageToUpdate === undefined) {\n // no pages, so don't update until they load\n return;\n }\n // If ascending, find the first element that is greater than or equal to the inserted element\n // If descending, find the first element that is less than or equal to the inserted element\n const indexWithinPage = pageToUpdate.value.page.findIndex((e) =>\n sortOrder === \"asc\"\n ? compareValues(sortKeyFromItem(e), insertedKey) >= 0\n : compareValues(sortKeyFromItem(e), insertedKey) <= 0,\n );\n const newPage =\n indexWithinPage === -1\n ? [...pageToUpdate.value.page, item]\n : [\n ...pageToUpdate.value.page.slice(0, indexWithinPage),\n item,\n ...pageToUpdate.value.page.slice(indexWithinPage),\n ];\n localQueryStore.setQuery(paginatedQuery, pageToUpdate.args, {\n ...pageToUpdate.value,\n page: newPage,\n });\n}\n", "/*\nhttps://github.com/beatgammit/base64-js/blob/88957c9943c7e2a0f03cdf73e71d579e433627d3/index.js\nCopyright (c) 2014 Jameson Little\nThe MIT License (MIT)\n*/\n\n// Vendored because this library has no ESM build, and some environments\n// (SvelteKit) are happiest when all dependencies are ESM.\n\nvar lookup: string[] = [];\nvar revLookup: number[] = [];\nvar Arr = Uint8Array;\n\nvar code = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\nfor (var i = 0, len = code.length; i < len; ++i) {\n lookup[i] = code[i];\n revLookup[code.charCodeAt(i)] = i;\n}\n\n// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup[\"-\".charCodeAt(0)] = 62;\nrevLookup[\"_\".charCodeAt(0)] = 63;\n\nfunction getLens(b64: string) {\n var len = b64.length;\n\n if (len % 4 > 0) {\n throw new Error(\"Invalid string. Length must be a multiple of 4\");\n }\n\n // Trim off extra bytes after placeholder bytes are found\n // See: https://github.com/beatgammit/base64-js/issues/42\n var validLen = b64.indexOf(\"=\");\n if (validLen === -1) validLen = len;\n\n var placeHoldersLen = validLen === len ? 0 : 4 - (validLen % 4);\n\n return [validLen, placeHoldersLen];\n}\n\n// base64 is 4/3 + up to two characters of the original data\n/** @public */\nexport function byteLength(b64: string): number {\n var lens = getLens(b64);\n var validLen = lens[0];\n var placeHoldersLen = lens[1];\n return ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen;\n}\n\nfunction _byteLength(_b64: string, validLen: number, placeHoldersLen: number) {\n return ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen;\n}\n\n/** @public */\nexport function toByteArray(b64: string): Uint8Array {\n var tmp;\n var lens = getLens(b64);\n var validLen = lens[0];\n var placeHoldersLen = lens[1];\n\n var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen));\n\n var curByte = 0;\n\n // if there are placeholders, only get up to the last complete 4 chars\n var len = placeHoldersLen > 0 ? validLen - 4 : validLen;\n\n var i;\n for (i = 0; i < len; i += 4) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 18) |\n (revLookup[b64.charCodeAt(i + 1)] << 12) |\n (revLookup[b64.charCodeAt(i + 2)] << 6) |\n revLookup[b64.charCodeAt(i + 3)];\n arr[curByte++] = (tmp >> 16) & 0xff;\n arr[curByte++] = (tmp >> 8) & 0xff;\n arr[curByte++] = tmp & 0xff;\n }\n\n if (placeHoldersLen === 2) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 2) |\n (revLookup[b64.charCodeAt(i + 1)] >> 4);\n arr[curByte++] = tmp & 0xff;\n }\n\n if (placeHoldersLen === 1) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 10) |\n (revLookup[b64.charCodeAt(i + 1)] << 4) |\n (revLookup[b64.charCodeAt(i + 2)] >> 2);\n arr[curByte++] = (tmp >> 8) & 0xff;\n arr[curByte++] = tmp & 0xff;\n }\n\n return arr;\n}\n\nfunction tripletToBase64(num: number) {\n return (\n lookup[(num >> 18) & 0x3f] +\n lookup[(num >> 12) & 0x3f] +\n lookup[(num >> 6) & 0x3f] +\n lookup[num & 0x3f]\n );\n}\n\nfunction encodeChunk(uint8: Uint8Array, start: number, end: number) {\n var tmp;\n var output = [];\n for (var i = start; i < end; i += 3) {\n tmp =\n ((uint8[i] << 16) & 0xff0000) +\n ((uint8[i + 1] << 8) & 0xff00) +\n (uint8[i + 2] & 0xff);\n output.push(tripletToBase64(tmp));\n }\n return output.join(\"\");\n}\n\n/** @public */\nexport function fromByteArray(uint8: Uint8Array): string {\n var tmp;\n var len = uint8.length;\n var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes\n var parts = [];\n var maxChunkLength = 16383; // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(\n encodeChunk(\n uint8,\n i,\n i + maxChunkLength > len2 ? len2 : i + maxChunkLength,\n ),\n );\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1];\n parts.push(lookup[tmp >> 2] + lookup[(tmp << 4) & 0x3f] + \"==\");\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + uint8[len - 1];\n parts.push(\n lookup[tmp >> 10] +\n lookup[(tmp >> 4) & 0x3f] +\n lookup[(tmp << 2) & 0x3f] +\n \"=\",\n );\n }\n\n return parts.join(\"\");\n}\n\nexport function fromByteArrayUrlSafeNoPadding(uint8: Uint8Array): string {\n return fromByteArray(uint8)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=/g, \"\");\n}\n", "import type { Value } from \"../values/value.js\";\n\n/**\n * Validate that the arguments to a Convex function are an object, defaulting\n * `undefined` to `{}`.\n */\nexport function parseArgs(\n args: Record<string, Value> | undefined,\n): Record<string, Value> {\n if (args === undefined) {\n return {};\n }\n if (!isSimpleObject(args)) {\n throw new Error(\n `The arguments to a Convex function must be an object. Received: ${\n args as any\n }`,\n );\n }\n return args;\n}\n\nexport function validateDeploymentUrl(deploymentUrl: string) {\n // Don't use things like `new URL(deploymentUrl).hostname` since these aren't\n // supported by React Native's JS environment\n if (typeof deploymentUrl === \"undefined\") {\n throw new Error(\n `Client created with undefined deployment address. If you used an environment variable, check that it's set.`,\n );\n }\n if (typeof deploymentUrl !== \"string\") {\n throw new Error(\n `Invalid deployment address: found ${deploymentUrl as any}\".`,\n );\n }\n if (\n !(deploymentUrl.startsWith(\"http:\") || deploymentUrl.startsWith(\"https:\"))\n ) {\n throw new Error(\n `Invalid deployment address: Must start with \"https://\" or \"http://\". Found \"${deploymentUrl}\".`,\n );\n }\n\n // Most clients should connect to \".convex.cloud\". But we also support localhost and\n // custom custom. We validate the deployment url is a valid url, which is the most\n // common failure pattern.\n try {\n new URL(deploymentUrl);\n } catch {\n throw new Error(\n `Invalid deployment address: \"${deploymentUrl}\" is not a valid URL. If you believe this URL is correct, use the \\`skipConvexDeploymentUrlCheck\\` option to bypass this.`,\n );\n }\n\n // If a user uses .convex.site, this is very likely incorrect.\n if (deploymentUrl.endsWith(\".convex.site\")) {\n throw new Error(\n `Invalid deployment address: \"${deploymentUrl}\" ends with .convex.site, which is used for HTTP Actions. Convex deployment URLs typically end with .convex.cloud? If you believe this URL is correct, use the \\`skipConvexDeploymentUrlCheck\\` option to bypass this.`,\n );\n }\n}\n\n/**\n * Check whether a value is a plain old JavaScript object.\n */\nexport function isSimpleObject(value: unknown) {\n const isObject = typeof value === \"object\";\n const prototype = Object.getPrototypeOf(value);\n const isSimple =\n prototype === null ||\n prototype === Object.prototype ||\n // Objects generated from other contexts (e.g. across Node.js `vm` modules) will not satisfy the previous\n // conditions but are still simple objects.\n prototype?.constructor?.name === \"Object\";\n return isObject && isSimple;\n}\n", "/**\n * Utilities for working with values stored in Convex.\n *\n * You can see the full set of supported types at\n * [Types](https://docs.convex.dev/using/types).\n * @module\n */\nimport * as Base64 from \"./base64.js\";\nimport { isSimpleObject } from \"../common/index.js\";\n\nconst LITTLE_ENDIAN = true;\n// This code is used by code that may not have bigint literals.\nconst MIN_INT64 = BigInt(\"-9223372036854775808\");\nconst MAX_INT64 = BigInt(\"9223372036854775807\");\nconst ZERO = BigInt(\"0\");\nconst EIGHT = BigInt(\"8\");\nconst TWOFIFTYSIX = BigInt(\"256\");\n\n/**\n * The type of JavaScript values serializable to JSON.\n *\n * @public\n */\nexport type JSONValue =\n | null\n | boolean\n | number\n | string\n | JSONValue[]\n | { [key: string]: JSONValue };\n\n/**\n * An identifier for a document in Convex.\n *\n * Convex documents are uniquely identified by their `Id`, which is accessible\n * on the `_id` field. To learn more, see [Document IDs](https://docs.convex.dev/database/document-ids).\n *\n * Documents can be loaded using `db.get(tableName, id)` in query and mutation functions.\n *\n * IDs are base 32 encoded strings which are URL safe.\n *\n * IDs are just strings at runtime, but this type can be used to distinguish them from other\n * strings at compile time.\n *\n * If you're using code generation, use the `Id` type generated for your data model in\n * `convex/_generated/dataModel.d.ts`.\n *\n * @typeParam TableName - A string literal type of the table name (like \"users\").\n *\n * @public\n */\nexport type Id<TableName extends string> = string & { __tableName: TableName };\n\n/**\n * A value supported by Convex.\n *\n * Values can be:\n * - stored inside of documents.\n * - used as arguments and return types to queries and mutation functions.\n *\n * You can see the full set of supported types at\n * [Types](https://docs.convex.dev/using/types).\n *\n * @public\n */\nexport type Value =\n | null\n | bigint\n | number\n | boolean\n | string\n | ArrayBuffer\n | Value[]\n | { [key: string]: undefined | Value };\n\n/**\n * The types of {@link Value} that can be used to represent numbers.\n *\n * @public\n */\nexport type NumericValue = bigint | number;\n\nfunction isSpecial(n: number) {\n return Number.isNaN(n) || !Number.isFinite(n) || Object.is(n, -0);\n}\n\nexport function slowBigIntToBase64(value: bigint): string {\n // the conversion is easy if we pretend it's unsigned\n if (value < ZERO) {\n value -= MIN_INT64 + MIN_INT64;\n }\n let hex = value.toString(16);\n if (hex.length % 2 === 1) hex = \"0\" + hex;\n\n const bytes = new Uint8Array(new ArrayBuffer(8));\n let i = 0;\n for (const hexByte of hex.match(/.{2}/g)!.reverse()) {\n bytes.set([parseInt(hexByte, 16)], i++);\n value >>= EIGHT;\n }\n return Base64.fromByteArray(bytes);\n}\n\nexport function slowBase64ToBigInt(encoded: string): bigint {\n const integerBytes = Base64.toByteArray(encoded);\n if (integerBytes.byteLength !== 8) {\n throw new Error(\n `Received ${integerBytes.byteLength} bytes, expected 8 for $integer`,\n );\n }\n let value = ZERO;\n let power = ZERO;\n for (const byte of integerBytes) {\n value += BigInt(byte) * TWOFIFTYSIX ** power;\n power++;\n }\n if (value > MAX_INT64) {\n value += MIN_INT64 + MIN_INT64;\n }\n return value;\n}\n\nexport function modernBigIntToBase64(value: bigint): string {\n if (value < MIN_INT64 || MAX_INT64 < value) {\n throw new Error(\n `BigInt ${value} does not fit into a 64-bit signed integer.`,\n );\n }\n const buffer = new ArrayBuffer(8);\n new DataView(buffer).setBigInt64(0, value, true);\n return Base64.fromByteArray(new Uint8Array(buffer));\n}\n\nexport function modernBase64ToBigInt(encoded: string): bigint {\n const integerBytes = Base64.toByteArray(encoded);\n if (integerBytes.byteLength !== 8) {\n throw new Error(\n `Received ${integerBytes.byteLength} bytes, expected 8 for $integer`,\n );\n }\n const intBytesView = new DataView(integerBytes.buffer);\n return intBytesView.getBigInt64(0, true);\n}\n\n// Fall back to a slower version on Safari 14 which lacks these APIs.\nexport const bigIntToBase64 = (DataView.prototype as any).setBigInt64\n ? modernBigIntToBase64\n : slowBigIntToBase64;\nexport const base64ToBigInt = (DataView.prototype as any).getBigInt64\n ? modernBase64ToBigInt\n : slowBase64ToBigInt;\n\nconst MAX_IDENTIFIER_LEN = 1024;\n\nfunction validateObjectField(k: string) {\n if (k.length > MAX_IDENTIFIER_LEN) {\n throw new Error(\n `Field name ${k} exceeds maximum field name length ${MAX_IDENTIFIER_LEN}.`,\n );\n }\n if (k.startsWith(\"$\")) {\n throw new Error(`Field name ${k} starts with a '$', which is reserved.`);\n }\n for (let i = 0; i < k.length; i += 1) {\n const charCode = k.charCodeAt(i);\n // Non-control ASCII characters\n if (charCode < 32 || charCode >= 127) {\n throw new Error(\n `Field name ${k} has invalid character '${k[i]}': Field names can only contain non-control ASCII characters`,\n );\n }\n }\n}\n\n/**\n * Parse a Convex value from its JSON representation.\n *\n * This function will deserialize serialized Int64s to `BigInt`s, Bytes to `ArrayBuffer`s etc.\n *\n * To learn more about Convex values, see [Types](https://docs.convex.dev/using/types).\n *\n * @param value - The JSON representation of a Convex value previously created with {@link convexToJson}.\n * @returns The JavaScript representation of the Convex value.\n *\n * @public\n */\nexport function jsonToConvex(value: JSONValue): Value {\n if (value === null) {\n return value;\n }\n if (typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"number\") {\n return value;\n }\n if (typeof value === \"string\") {\n return value;\n }\n if (Array.isArray(value)) {\n return value.map((value) => jsonToConvex(value));\n }\n if (typeof value !== \"object\") {\n throw new Error(`Unexpected type of ${value as any}`);\n }\n const entries = Object.entries(value);\n if (entries.length === 1) {\n const key = entries[0][0];\n if (key === \"$bytes\") {\n if (typeof value.$bytes !== \"string\") {\n throw new Error(`Malformed $bytes field on ${value as any}`);\n }\n return Base64.toByteArray(value.$bytes).buffer;\n }\n if (key === \"$integer\") {\n if (typeof value.$integer !== \"string\") {\n throw new Error(`Malformed $integer field on ${value as any}`);\n }\n return base64ToBigInt(value.$integer);\n }\n if (key === \"$float\") {\n if (typeof value.$float !== \"string\") {\n throw new Error(`Malformed $float field on ${value as any}`);\n }\n const floatBytes = Base64.toByteArray(value.$float);\n if (floatBytes.byteLength !== 8) {\n throw new Error(\n `Received ${floatBytes.byteLength} bytes, expected 8 for $float`,\n );\n }\n const floatBytesView = new DataView(floatBytes.buffer);\n const float = floatBytesView.getFloat64(0, LITTLE_ENDIAN);\n if (!isSpecial(float)) {\n throw new Error(`Float ${float} should be encoded as a number`);\n }\n return float;\n }\n if (key === \"$set\") {\n throw new Error(\n `Received a Set which is no longer supported as a Convex type.`,\n );\n }\n if (key === \"$map\") {\n throw new Error(\n `Received a Map which is no longer supported as a Convex type.`,\n );\n }\n }\n const out: { [key: string]: Value } = {};\n for (const [k, v] of Object.entries(value)) {\n validateObjectField(k);\n out[k] = jsonToConvex(v);\n }\n return out;\n}\n\nconst MAX_VALUE_FOR_ERROR_LEN = 16384;\n\nexport function stringifyValueForError(value: any) {\n const str = JSON.stringify(value, (_key, value) => {\n if (value === undefined) {\n // By default `JSON.stringify` converts undefined, functions, symbols,\n // Infinity, and NaN to null which produces a confusing error message.\n // We deal with `undefined` specifically because it's the most common.\n // Ideally we'd use a pretty-printing library that prints `undefined`\n // (no quotes), but it might not be worth the bundle size cost.\n return \"undefined\";\n }\n if (typeof value === \"bigint\") {\n // `JSON.stringify` throws on bigints by default.\n return `${value.toString()}n`;\n }\n return value;\n });\n if (str.length > MAX_VALUE_FOR_ERROR_LEN) {\n const rest = \"[...truncated]\";\n let truncateAt = MAX_VALUE_FOR_ERROR_LEN - rest.length;\n const codePoint = str.codePointAt(truncateAt - 1);\n if (codePoint !== undefined && codePoint > 0xffff) {\n // don't split a surrogate pair in half\n truncateAt -= 1;\n }\n return str.substring(0, truncateAt) + rest;\n }\n return str;\n}\n\nfunction convexToJsonInternal(\n value: Value,\n originalValue: Value,\n context: string,\n includeTopLevelUndefined: boolean,\n): JSONValue {\n if (value === undefined) {\n const contextText =\n context &&\n ` (present at path ${context} in original object ${stringifyValueForError(\n originalValue,\n )})`;\n throw new Error(\n `undefined is not a valid Convex value${contextText}. To learn about Convex's supported types, see https://docs.convex.dev/using/types.`,\n );\n }\n if (value === null) {\n return value;\n }\n if (typeof value === \"bigint\") {\n if (value < MIN_INT64 || MAX_INT64 < value) {\n throw new Error(\n `BigInt ${value} does not fit into a 64-bit signed integer.`,\n );\n }\n return { $integer: bigIntToBase64(value) };\n }\n if (typeof value === \"number\") {\n if (isSpecial(value)) {\n const buffer = new ArrayBuffer(8);\n new DataView(buffer).setFloat64(0, value, LITTLE_ENDIAN);\n return { $float: Base64.fromByteArray(new Uint8Array(buffer)) };\n } else {\n return value;\n }\n }\n if (typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"string\") {\n return value;\n }\n if (value instanceof ArrayBuffer) {\n return { $bytes: Base64.fromByteArray(new Uint8Array(value)) };\n }\n if (Array.isArray(value)) {\n return value.map((value, i) =>\n convexToJsonInternal(value, originalValue, context + `[${i}]`, false),\n );\n }\n if (value instanceof Set) {\n throw new Error(\n errorMessageForUnsupportedType(context, \"Set\", [...value], originalValue),\n );\n }\n if (value instanceof Map) {\n throw new Error(\n errorMessageForUnsupportedType(context, \"Map\", [...value], originalValue),\n );\n }\n\n if (!isSimpleObject(value)) {\n const theType = value?.constructor?.name;\n const typeName = theType ? `${theType} ` : \"\";\n throw new Error(\n errorMessageForUnsupportedType(context, typeName, value, originalValue),\n );\n }\n\n const out: { [key: string]: JSONValue } = {};\n const entries = Object.entries(value);\n entries.sort(([k1, _v1], [k2, _v2]) => (k1 === k2 ? 0 : k1 < k2 ? -1 : 1));\n for (const [k, v] of entries) {\n if (v !== undefined) {\n validateObjectField(k);\n out[k] = convexToJsonInternal(v, originalValue, context + `.${k}`, false);\n } else if (includeTopLevelUndefined) {\n validateObjectField(k);\n out[k] = convexOrUndefinedToJsonInternal(\n v,\n originalValue,\n context + `.${k}`,\n );\n }\n }\n return out;\n}\n\nfunction errorMessageForUnsupportedType(\n context: string,\n typeName: string,\n value: any,\n originalValue: any,\n) {\n if (context) {\n return `${typeName}${stringifyValueForError(\n value,\n )} is not a supported Convex type (present at path ${context} in original object ${stringifyValueForError(\n originalValue,\n )}). To learn about Convex's supported types, see https://docs.convex.dev/using/types.`;\n } else {\n return `${typeName}${stringifyValueForError(\n value,\n )} is not a supported Convex type.`;\n }\n}\n\n// convexOrUndefinedToJsonInternal wrapper exists so we can pipe through the\n// `originalValue` and `context` through for better error messaging.\nfunction convexOrUndefinedToJsonInternal(\n value: Value | undefined,\n originalValue: Value | undefined,\n context: string,\n): JSONValue {\n if (value === undefined) {\n return { $undefined: null };\n } else {\n if (originalValue === undefined) {\n // This should not happen.\n throw new Error(\n `Programming error. Current value is ${stringifyValueForError(\n value,\n )} but original value is undefined`,\n );\n }\n return convexToJsonInternal(value, originalValue, context, false);\n }\n}\n\n/**\n * Convert a Convex value to its JSON representation.\n *\n * Use {@link jsonToConvex} to recreate the original value.\n *\n * To learn more about Convex values, see [Types](https://docs.convex.dev/using/types).\n *\n * @param value - A Convex value to convert into JSON.\n * @returns The JSON representation of `value`.\n *\n * @public\n */\nexport function convexToJson(value: Value): JSONValue {\n return convexToJsonInternal(value, value, \"\", false);\n}\n\n// Convert a Convex value or `undefined` into its JSON representation.\n// `undefined` is used in filters to represent a missing object field.\nexport function convexOrUndefinedToJson(value: Value | undefined): JSONValue {\n return convexOrUndefinedToJsonInternal(value, value, \"\");\n}\n\n/**\n * Similar to convexToJson but also serializes top level undefined fields\n * using convexOrUndefinedToJson().\n *\n * @param value - A Convex value to convert into JSON.\n * @returns The JSON representation of `value`.\n */\nexport function patchValueToJson(value: Value): JSONValue {\n return convexToJsonInternal(value, value, \"\", true);\n}\n", "import { Value, stringifyValueForError } from \"./value.js\";\n\nconst IDENTIFYING_FIELD = Symbol.for(\"ConvexError\");\n\nexport class ConvexError<TData extends Value> extends Error {\n name = \"ConvexError\";\n data: TData;\n [IDENTIFYING_FIELD] = true;\n\n constructor(data: TData) {\n super(typeof data === \"string\" ? data : stringifyValueForError(data));\n this.data = data;\n }\n}\n", "/**\n * Taken from https://github.com/rocicorp/compare-utf8/blob/main/LICENSE\n * (Apache Version 2.0, January 2004)\n */\n\n/**\n * This is copied here instead of added as a dependency to avoid bundling issues.\n */\n\n/**\n * Compares two JavaScript strings as if they were UTF-8 encoded byte arrays.\n * @param {string} a\n * @param {string} b\n * @returns {number}\n */\nexport function compareUTF8(a: string, b: string): number {\n const aLength = a.length;\n const bLength = b.length;\n const length = Math.min(aLength, bLength);\n for (let i = 0; i < length; ) {\n const aCodePoint = a.codePointAt(i)!;\n const bCodePoint = b.codePointAt(i)!;\n if (aCodePoint !== bCodePoint) {\n // Code points below 0x80 are represented the same way in UTF-8 as in\n // UTF-16.\n if (aCodePoint < 0x80 && bCodePoint < 0x80) {\n return aCodePoint - bCodePoint;\n }\n\n // get the UTF-8 bytes for the code points\n const aLength = utf8Bytes(aCodePoint, aBytes);\n const bLength = utf8Bytes(bCodePoint, bBytes);\n return compareArrays(aBytes, aLength, bBytes, bLength);\n }\n\n i += utf16LengthForCodePoint(aCodePoint);\n }\n\n return aLength - bLength;\n}\n\n/**\n * @param {number[]} a\n * @param {number} aLength\n * @param {number[]} b\n * @param {number} bLength\n * @returns {number}\n */\nfunction compareArrays(\n a: number[],\n aLength: number,\n b: number[],\n bLength: number,\n) {\n const length = Math.min(aLength, bLength);\n for (let i = 0; i < length; i++) {\n const aValue = a[i];\n const bValue = b[i];\n if (aValue !== bValue) {\n return aValue - bValue;\n }\n }\n return aLength - bLength;\n}\n\n/**\n * @param {number} aCodePoint\n * @returns {number}\n */\nexport function utf16LengthForCodePoint(aCodePoint: number) {\n return aCodePoint > 0xffff ? 2 : 1;\n}\n\n// 2 preallocated arrays for utf8Bytes.\nconst arr = () => Array.from({ length: 4 }, () => 0);\nconst aBytes = arr();\nconst bBytes = arr();\n\n/**\n * @param {number} codePoint\n * @param {number[]} bytes\n * @returns {number}\n */\nfunction utf8Bytes(codePoint: number, bytes: number[]) {\n if (codePoint < 0x80) {\n bytes[0] = codePoint;\n return 1;\n }\n\n let count;\n let offset;\n\n if (codePoint <= 0x07ff) {\n count = 1;\n offset = 0xc0;\n } else if (codePoint <= 0xffff) {\n count = 2;\n offset = 0xe0;\n } else if (codePoint <= 0x10ffff) {\n count = 3;\n offset = 0xf0;\n } else {\n throw new Error(\"Invalid code point\");\n }\n\n bytes[0] = (codePoint >> (6 * count)) + offset;\n let i = 1;\n for (; count > 0; count--) {\n const temp = codePoint >> (6 * (count - 1));\n bytes[i++] = 0x80 | (temp & 0x3f);\n }\n return i;\n}\n\n/**\n * @param {string} a\n * @param {string} b\n * @returns {boolean}\n */\nexport function greaterThan(a: string, b: string) {\n return compareUTF8(a, b) > 0;\n}\n\n/**\n * @param {string} a\n * @param {string} b\n * @returns {boolean}\n */\nexport function greaterThanEq(a: string, b: string) {\n return compareUTF8(a, b) >= 0;\n}\n\n/**\n * @param {string} a\n * @param {string} b\n * @returns {boolean}\n */\nexport function lessThan(a: string, b: string) {\n return compareUTF8(a, b) < 0;\n}\n\n/**\n * @param {string} a\n * @param {string} b\n * @returns {boolean}\n */\nexport function lessThanEq(a: string, b: string) {\n return compareUTF8(a, b) <= 0;\n}\n", "import { Value } from \"./value.js\";\nimport { compareUTF8 } from \"./compare_utf8.js\";\n\nexport function compareValues(k1: Value | undefined, k2: Value | undefined) {\n return compareAsTuples(makeComparable(k1), makeComparable(k2));\n}\n\nfunction compareAsTuples<T>(a: [number, T], b: [number, T]): number {\n if (a[0] === b[0]) {\n return compareSameTypeValues(a[1], b[1]);\n } else if (a[0] < b[0]) {\n return -1;\n }\n return 1;\n}\n\nfunction compareSameTypeValues<T>(v1: T, v2: T): number {\n if (v1 === undefined || v1 === null) {\n return 0;\n }\n if (typeof v1 === \"number\") {\n if (typeof v2 !== \"number\") {\n throw new Error(`Unexpected type ${v2 as any}`);\n }\n return compareNumbers(v1, v2);\n }\n if (typeof v1 === \"string\") {\n if (typeof v2 !== \"string\") {\n throw new Error(`Unexpected type ${v2 as any}`);\n }\n return compareUTF8(v1, v2);\n }\n if (\n typeof v1 === \"bigint\" ||\n typeof v1 === \"boolean\" ||\n typeof v1 === \"string\"\n ) {\n return v1 < v2 ? -1 : v1 === v2 ? 0 : 1;\n }\n if (!Array.isArray(v1) || !Array.isArray(v2)) {\n throw new Error(`Unexpected type ${v1 as any}`);\n }\n for (let i = 0; i < v1.length && i < v2.length; i++) {\n const cmp = compareAsTuples(v1[i], v2[i]);\n if (cmp !== 0) {\n return cmp;\n }\n }\n if (v1.length < v2.length) {\n return -1;\n }\n if (v1.length > v2.length) {\n return 1;\n }\n return 0;\n}\n\nfunction compareNumbers(v1: number, v2: number): number {\n // Handle NaN values\n if (isNaN(v1) || isNaN(v2)) {\n // Create DataViews for bit-level comparison\n const buffer1 = new ArrayBuffer(8);\n const buffer2 = new ArrayBuffer(8);\n new DataView(buffer1).setFloat64(0, v1, /* little-endian */ true);\n new DataView(buffer2).setFloat64(0, v2, /* little-endian */ true);\n\n // Read as BigInt to compare bits\n const v1Bits = BigInt(\n new DataView(buffer1).getBigInt64(0, /* little-endian */ true),\n );\n const v2Bits = BigInt(\n new DataView(buffer2).getBigInt64(0, /* little-endian */ true),\n );\n\n // The sign bit is the most significant bit (bit 63)\n const v1Sign = (v1Bits & 0x8000000000000000n) !== 0n;\n const v2Sign = (v2Bits & 0x8000000000000000n) !== 0n;\n\n // If one value is NaN and the other isn't, use sign bits first\n if (isNaN(v1) !== isNaN(v2)) {\n // If v1 is NaN, compare based on sign bits\n if (isNaN(v1)) {\n return v1Sign ? -1 : 1;\n }\n // If v2 is NaN, compare based on sign bits\n return v2Sign ? 1 : -1;\n }\n\n // If both are NaN, compare their binary representations\n if (v1Sign !== v2Sign) {\n return v1Sign ? -1 : 1; // true means negative\n }\n return v1Bits < v2Bits ? -1 : v1Bits === v2Bits ? 0 : 1;\n }\n\n if (Object.is(v1, v2)) {\n return 0;\n }\n\n if (Object.is(v1, -0)) {\n return Object.is(v2, 0) ? -1 : -Math.sign(v2);\n }\n if (Object.is(v2, -0)) {\n return Object.is(v1, 0) ? 1 : Math.sign(v1);\n }\n\n // Handle regular number comparison\n return v1 < v2 ? -1 : 1;\n}\n\n// Returns an array which can be compared to other arrays as if they were tuples.\n// For example, [1, null] < [2, 1n] means null sorts before all bigints\n// And [3, 5] < [3, 6] means floats sort as expected\n// And [7, [[5, \"a\"]]] < [7, [[5, \"a\"], [5, \"b\"]]] means arrays sort as expected\nfunction makeComparable(v: Value | undefined): [number, any] {\n if (v === undefined) {\n return [0, undefined];\n }\n if (v === null) {\n return [1, null];\n }\n if (typeof v === \"bigint\") {\n return [2, v];\n }\n if (typeof v === \"number\") {\n return [3, v];\n }\n if (typeof v === \"boolean\") {\n return [4, v];\n }\n if (typeof v === \"string\") {\n return [5, v];\n }\n if (v instanceof ArrayBuffer) {\n return [6, Array.from(new Uint8Array(v)).map(makeComparable)];\n }\n if (Array.isArray(v)) {\n return [7, v.map(makeComparable)];\n }\n // Otherwise, it's an POJO.\n const keys = Object.keys(v).sort();\n const pojo: Value[] = keys.map((k) => [k, v[k]!]);\n return [8, pojo.map(makeComparable)];\n}\n", "import { Value } from \"../values/index.js\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useConvex } from \"./client.js\";\nimport { CreateWatch, QueriesObserver } from \"./queries_observer.js\";\nimport { useSubscription } from \"./use_subscription.js\";\nimport { QueryJournal } from \"../browser/index.js\";\nimport { FunctionReference } from \"../server/api.js\";\nimport { SubscribeToPaginatedQueryOptions } from \"../browser/sync/paginated_query_client.js\";\n\n/**\n * Load a variable number of reactive Convex queries.\n *\n * `useQueries` is similar to {@link useQuery} but it allows\n * loading multiple queries which can be useful for loading a dynamic number\n * of queries without violating the rules of React hooks.\n *\n * This hook accepts an object whose keys are identifiers for each query and the\n * values are objects of `{ query: FunctionReference, args: Record<string, Value> }`. The\n * `query` is a FunctionReference for the Convex query function to load, and the `args` are\n * the arguments to that function.\n *\n * The hook returns an object that maps each identifier to the result of the query,\n * `undefined` if the query is still loading, or an instance of `Error` if the query\n * threw an exception.\n *\n * For example if you loaded a query like:\n * ```typescript\n * const results = useQueries({\n * messagesInGeneral: {\n * query: \"listMessages\",\n * args: { channel: \"#general\" }\n * }\n * });\n * ```\n * then the result would look like:\n * ```typescript\n * {\n * messagesInGeneral: [{\n * channel: \"#general\",\n * body: \"hello\"\n * _id: ...,\n * _creationTime: ...\n * }]\n * }\n * ```\n *\n * This React hook contains internal state that will cause a rerender\n * whenever any of the query results change.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @param queries - An object mapping identifiers to objects of\n * `{query: string, args: Record<string, Value> }` describing which query\n * functions to fetch.\n * @returns An object with the same keys as the input. The values are the result\n * of the query function, `undefined` if it's still loading, or an `Error` if\n * it threw an exception.\n *\n * @public\n */\nexport function useQueries(\n queries: RequestForQueries,\n): Record<string, any | undefined | Error> {\n const convex = useConvex();\n if (convex === undefined) {\n // Error message includes `useQuery` because this hook is called by `useQuery`\n // more often than it's called directly.\n throw new Error(\n \"Could not find Convex client! `useQuery` must be used in the React component \" +\n \"tree under `ConvexProvider`. Did you forget it? \" +\n \"See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app\",\n );\n }\n const createWatch = useMemo(() => {\n return (\n query: FunctionReference<\"query\">,\n args: Record<string, Value>,\n {\n journal,\n paginationOptions,\n }: {\n journal?: QueryJournal;\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n },\n ) => {\n if (paginationOptions) {\n return convex.watchPaginatedQuery(query, args, paginationOptions);\n } else {\n return convex.watchQuery(query, args, journal ? { journal } : {});\n }\n };\n }, [convex]);\n return useQueriesHelper(queries, createWatch);\n}\n\n/**\n * Internal version of `useQueries` that is exported for testing.\n */\nexport function useQueriesHelper(\n queries: RequestForQueries,\n createWatch: CreateWatch,\n): Record<string, any | undefined | Error> {\n const [observer] = useState(() => new QueriesObserver(createWatch));\n\n if (observer.createWatch !== createWatch) {\n observer.setCreateWatch(createWatch);\n }\n\n // Unsubscribe from all queries on unmount.\n useEffect(() => () => observer.destroy(), [observer]);\n\n const subscription = useMemo(\n () => ({\n getCurrentValue: () => {\n return observer.getLocalResults(queries);\n },\n subscribe: (callback: () => void) => {\n observer.setQueries(queries);\n return observer.subscribe(callback);\n },\n }),\n [observer, queries],\n );\n\n return useSubscription(subscription);\n}\n\n/**\n * An object representing a request to load multiple queries.\n *\n * The keys of this object are identifiers and the values are objects containing\n * the query function and the arguments to pass to it.\n *\n * This is used as an argument to {@link useQueries}.\n * @public\n */\nexport type RequestForQueries = Record<\n string,\n {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n /** @internal */\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n }\n>;\n", "export const version = \"1.37.0\";\n", "/* eslint-disable no-console */ // This is the one file where we can `console.log` for the default logger implementation.\nimport { ConvexError, Value } from \"../values/index.js\";\nimport { FunctionFailure } from \"./sync/function_result.js\";\n\n// This is blue #9 from https://www.radix-ui.com/docs/colors/palette-composition/the-scales\n// It must look good in both light and dark mode.\nconst INFO_COLOR = \"color:rgb(0, 145, 255)\";\n\nexport type UdfType = \"query\" | \"mutation\" | \"action\" | \"any\";\n\nfunction prefix_for_source(source: UdfType) {\n switch (source) {\n case \"query\":\n return \"Q\";\n case \"mutation\":\n return \"M\";\n case \"action\":\n return \"A\";\n case \"any\":\n return \"?\";\n }\n}\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\n/**\n * A logger that can be used to log messages. By default, this is a wrapper\n * around `console`, but can be configured to not log at all or to log somewhere\n * else.\n */\nexport type Logger = {\n logVerbose(...args: any[]): void;\n log(...args: any[]): void;\n warn(...args: any[]): void;\n error(...args: any[]): void;\n};\n\nexport class DefaultLogger implements Logger {\n private _onLogLineFuncs: Record<\n string,\n (level: LogLevel, ...args: any[]) => void\n >;\n private _verbose: boolean;\n\n constructor(options: { verbose: boolean }) {\n this._onLogLineFuncs = {};\n this._verbose = options.verbose;\n }\n\n addLogLineListener(\n func: (level: LogLevel, ...args: any[]) => void,\n ): () => void {\n let id = Math.random().toString(36).substring(2, 15);\n for (let i = 0; i < 10; i++) {\n if (this._onLogLineFuncs[id] === undefined) {\n break;\n }\n id = Math.random().toString(36).substring(2, 15);\n }\n this._onLogLineFuncs[id] = func;\n return () => {\n delete this._onLogLineFuncs[id];\n };\n }\n\n logVerbose(...args: any[]) {\n if (this._verbose) {\n for (const func of Object.values(this._onLogLineFuncs)) {\n func(\"debug\", `${new Date().toISOString()}`, ...args);\n }\n }\n }\n\n log(...args: any[]) {\n for (const func of Object.values(this._onLogLineFuncs)) {\n func(\"info\", ...args);\n }\n }\n\n warn(...args: any[]) {\n for (const func of Object.values(this._onLogLineFuncs)) {\n func(\"warn\", ...args);\n }\n }\n\n error(...args: any[]) {\n for (const func of Object.values(this._onLogLineFuncs)) {\n func(\"error\", ...args);\n }\n }\n}\n\nexport function instantiateDefaultLogger(options: {\n verbose: boolean;\n}): Logger {\n const logger = new DefaultLogger(options);\n logger.addLogLineListener((level, ...args) => {\n switch (level) {\n case \"debug\":\n console.debug(...args);\n break;\n case \"info\":\n console.log(...args);\n break;\n case \"warn\":\n console.warn(...args);\n break;\n case \"error\":\n console.error(...args);\n break;\n default: {\n level satisfies never;\n console.log(...args);\n }\n }\n });\n return logger;\n}\n\nexport function instantiateNoopLogger(options: { verbose: boolean }): Logger {\n return new DefaultLogger(options);\n}\n\nexport function logForFunction(\n logger: Logger,\n type: \"info\" | \"error\",\n source: UdfType,\n udfPath: string,\n message: string | { errorData: Value },\n) {\n const prefix = prefix_for_source(source);\n\n if (typeof message === \"object\") {\n message = `ConvexError ${JSON.stringify(message.errorData, null, 2)}`;\n }\n if (type === \"info\") {\n const match = message.match(/^\\[.*?\\] /);\n if (match === null) {\n logger.error(\n `[CONVEX ${prefix}(${udfPath})] Could not parse console.log`,\n );\n return;\n }\n const level = message.slice(1, match[0].length - 2);\n const args = message.slice(match[0].length);\n\n logger.log(`%c[CONVEX ${prefix}(${udfPath})] [${level}]`, INFO_COLOR, args);\n } else {\n logger.error(`[CONVEX ${prefix}(${udfPath})] ${message}`);\n }\n}\n\nexport function logFatalError(logger: Logger, message: string): Error {\n const errorMessage = `[CONVEX FATAL ERROR] ${message}`;\n logger.error(errorMessage);\n return new Error(errorMessage);\n}\n\nexport function createHybridErrorStacktrace(\n source: UdfType,\n udfPath: string,\n result: FunctionFailure,\n): string {\n const prefix = prefix_for_source(source);\n return `[CONVEX ${prefix}(${udfPath})] ${result.errorMessage}\\n Called by client`;\n}\n\nexport function forwardData(\n result: FunctionFailure,\n error: ConvexError<string>,\n) {\n (error as ConvexError<any>).data = result.errorData;\n return error;\n}\n", "import { convexToJson, Value } from \"../../values/index.js\";\n\nexport function canonicalizeUdfPath(udfPath: string): string {\n const pieces = udfPath.split(\":\");\n let moduleName: string;\n let functionName: string;\n if (pieces.length === 1) {\n moduleName = pieces[0];\n functionName = \"default\";\n } else {\n moduleName = pieces.slice(0, pieces.length - 1).join(\":\");\n functionName = pieces[pieces.length - 1];\n }\n if (moduleName.endsWith(\".js\")) {\n moduleName = moduleName.slice(0, -3);\n }\n return `${moduleName}:${functionName}`;\n}\n\n/**\n * The serialization here is not stable, these strings never make it outside the client.\n */\n\n/**\n * A string representing the name and arguments of a query.\n *\n * This is used by the {@link BaseConvexClient}.\n *\n * @public\n */\nexport type QueryToken = string & { __queryToken: true };\n\n/**\n * A string representing the name and arguments of a paginated query.\n *\n * This is a specialized form of QueryToken used for paginated queries.\n */\nexport type PaginatedQueryToken = QueryToken & { __paginatedQueryToken: true };\n\nexport function serializePathAndArgs(\n udfPath: string,\n args: Record<string, Value>,\n): QueryToken {\n return JSON.stringify({\n udfPath: canonicalizeUdfPath(udfPath),\n args: convexToJson(args),\n }) as QueryToken;\n}\n\nexport function serializePaginatedPathAndArgs(\n udfPath: string,\n args: Record<string, Value>, // args WITHOUT paginationOpts\n options: { initialNumItems: number; id: number },\n): PaginatedQueryToken {\n const { initialNumItems, id } = options;\n const result = JSON.stringify({\n type: \"paginated\",\n udfPath: canonicalizeUdfPath(udfPath),\n args: convexToJson(args),\n options: convexToJson({ initialNumItems, id }),\n }) as PaginatedQueryToken;\n return result;\n}\n\nexport function serializedQueryTokenIsPaginated(\n token: QueryToken | PaginatedQueryToken,\n): token is PaginatedQueryToken {\n return JSON.parse(token).type === \"paginated\";\n}\n", "/**\n * The local state of the client:\n * - which queries are subscribed to\n * - the \"Query Set Version,\" used to produce QuerySetModification messages\n * - the current auth token and \"Identity Version\"\n *\n * Local state does not include:\n * - query results (see RemoteQuerySet)\n * - locally made \"optimistic update\" modifications to query results (see OptimisticQueryResults)\n * - any query results at all\n **/\n\nimport { convexToJson, Value } from \"../../values/index.js\";\nimport {\n AddQuery,\n RemoveQuery,\n QueryId,\n QuerySetModification,\n QuerySetVersion,\n IdentityVersion,\n Authenticate,\n QueryJournal,\n Transition,\n AdminAuthentication,\n UserIdentityAttributes,\n} from \"./protocol.js\";\nimport {\n canonicalizeUdfPath,\n QueryToken,\n serializePathAndArgs,\n} from \"./udf_path_utils.js\";\n\ntype LocalQuery = {\n id: QueryId;\n canonicalizedUdfPath: string;\n args: Record<string, Value>;\n numSubscribers: number;\n journal?: QueryJournal | undefined;\n componentPath?: string | undefined;\n};\n\nexport type AuthState =\n | {\n tokenType: \"User\";\n value: string;\n }\n | {\n tokenType: \"Admin\";\n value: string;\n impersonating?: UserIdentityAttributes | undefined;\n };\n\nexport class LocalSyncState {\n private nextQueryId: QueryId;\n private querySetVersion: QuerySetVersion;\n private readonly querySet: Map<QueryToken, LocalQuery>;\n private readonly queryIdToToken: Map<QueryId, QueryToken>;\n private identityVersion: IdentityVersion;\n private auth: AuthState | undefined;\n private readonly outstandingQueriesOlderThanRestart: Set<QueryId>;\n private outstandingAuthOlderThanRestart: boolean;\n private paused: boolean;\n private pendingQuerySetModifications: Map<QueryId, AddQuery | RemoveQuery>;\n\n constructor() {\n this.nextQueryId = 0;\n this.querySetVersion = 0;\n this.identityVersion = 0;\n this.querySet = new Map();\n this.queryIdToToken = new Map();\n this.outstandingQueriesOlderThanRestart = new Set();\n this.outstandingAuthOlderThanRestart = false;\n this.paused = false;\n this.pendingQuerySetModifications = new Map();\n }\n\n hasSyncedPastLastReconnect(): boolean {\n return (\n this.outstandingQueriesOlderThanRestart.size === 0 &&\n !this.outstandingAuthOlderThanRestart\n );\n }\n\n markAuthCompletion() {\n this.outstandingAuthOlderThanRestart = false;\n }\n\n subscribe(\n udfPath: string,\n args: Record<string, Value>,\n journal?: QueryJournal | undefined,\n componentPath?: string | undefined,\n ): {\n queryToken: QueryToken;\n modification: QuerySetModification | null;\n unsubscribe: () => QuerySetModification | null;\n } {\n const canonicalizedUdfPath = canonicalizeUdfPath(udfPath);\n const queryToken = serializePathAndArgs(canonicalizedUdfPath, args);\n\n const existingEntry = this.querySet.get(queryToken);\n\n if (existingEntry !== undefined) {\n existingEntry.numSubscribers += 1;\n return {\n queryToken,\n modification: null,\n unsubscribe: () => this.removeSubscriber(queryToken),\n };\n } else {\n const queryId = this.nextQueryId++;\n const query: LocalQuery = {\n id: queryId,\n canonicalizedUdfPath,\n args,\n numSubscribers: 1,\n journal,\n componentPath,\n };\n this.querySet.set(queryToken, query);\n this.queryIdToToken.set(queryId, queryToken);\n\n const baseVersion = this.querySetVersion;\n const newVersion = this.querySetVersion + 1;\n\n const add: AddQuery = {\n type: \"Add\",\n queryId,\n udfPath: canonicalizedUdfPath,\n args: [convexToJson(args)],\n journal,\n componentPath,\n };\n\n if (this.paused) {\n this.pendingQuerySetModifications.set(queryId, add);\n } else {\n this.querySetVersion = newVersion;\n }\n\n const modification: QuerySetModification = {\n type: \"ModifyQuerySet\",\n baseVersion,\n newVersion,\n modifications: [add],\n };\n return {\n queryToken,\n modification,\n unsubscribe: () => this.removeSubscriber(queryToken),\n };\n }\n }\n\n transition(transition: Transition) {\n for (const modification of transition.modifications) {\n switch (modification.type) {\n case \"QueryUpdated\":\n case \"QueryFailed\": {\n this.outstandingQueriesOlderThanRestart.delete(modification.queryId);\n const journal = modification.journal;\n if (journal !== undefined) {\n const queryToken = this.queryIdToToken.get(modification.queryId);\n // We may have already unsubscribed to this query by the time the server\n // sends us the journal. If so, just ignore it.\n if (queryToken !== undefined) {\n this.querySet.get(queryToken)!.journal = journal;\n }\n }\n\n break;\n }\n case \"QueryRemoved\": {\n this.outstandingQueriesOlderThanRestart.delete(modification.queryId);\n break;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n modification satisfies never;\n throw new Error(`Invalid modification ${(modification as any).type}`);\n }\n }\n }\n }\n\n queryId(udfPath: string, args: Record<string, Value>): QueryId | null {\n const canonicalizedUdfPath = canonicalizeUdfPath(udfPath);\n const queryToken = serializePathAndArgs(canonicalizedUdfPath, args);\n const existingEntry = this.querySet.get(queryToken);\n if (existingEntry !== undefined) {\n return existingEntry.id;\n }\n return null;\n }\n\n isCurrentOrNewerAuthVersion(version: IdentityVersion): boolean {\n return version >= this.identityVersion;\n }\n\n getAuth(): AuthState | undefined {\n return this.auth;\n }\n\n setAuth(value: string): Authenticate {\n this.auth = {\n tokenType: \"User\" as const,\n value: value,\n };\n const baseVersion = this.identityVersion;\n if (!this.paused) {\n this.identityVersion = baseVersion + 1;\n }\n return {\n type: \"Authenticate\",\n baseVersion: baseVersion,\n ...this.auth,\n };\n }\n\n setAdminAuth(\n value: string,\n actingAs?: UserIdentityAttributes,\n ): AdminAuthentication {\n const auth: typeof this.auth & {\n tokenType: \"Admin\";\n } = {\n tokenType: \"Admin\",\n value,\n impersonating: actingAs,\n };\n this.auth = auth;\n const baseVersion = this.identityVersion;\n if (!this.paused) {\n this.identityVersion = baseVersion + 1;\n }\n return {\n type: \"Authenticate\",\n baseVersion: baseVersion,\n ...auth,\n };\n }\n\n clearAuth(): Authenticate {\n this.auth = undefined;\n this.markAuthCompletion();\n const baseVersion = this.identityVersion;\n if (!this.paused) {\n this.identityVersion = baseVersion + 1;\n }\n return {\n type: \"Authenticate\",\n tokenType: \"None\",\n baseVersion: baseVersion,\n };\n }\n\n hasAuth(): boolean {\n return !!this.auth;\n }\n\n isNewAuth(value: string): boolean {\n return this.auth?.value !== value;\n }\n\n queryPath(queryId: QueryId): string | null {\n const pathAndArgs = this.queryIdToToken.get(queryId);\n if (pathAndArgs) {\n return this.querySet.get(pathAndArgs)!.canonicalizedUdfPath;\n }\n return null;\n }\n\n queryArgs(queryId: QueryId): Record<string, Value> | null {\n const pathAndArgs = this.queryIdToToken.get(queryId);\n if (pathAndArgs) {\n return this.querySet.get(pathAndArgs)!.args;\n }\n return null;\n }\n\n queryToken(queryId: QueryId): QueryToken | null {\n return this.queryIdToToken.get(queryId) ?? null;\n }\n\n queryJournal(queryToken: QueryToken): QueryJournal | undefined {\n return this.querySet.get(queryToken)?.journal;\n }\n\n restart(): [QuerySetModification, (Authenticate | undefined)?] {\n // Restart works whether we are paused or unpaused.\n // The `this.pendingQuerySetModifications` is not used\n // when restarting as the AddQuery and RemoveQuery are computed\n // from scratch, based on the old remote query results, here.\n this.unpause();\n\n this.outstandingQueriesOlderThanRestart.clear();\n const modifications = [];\n for (const localQuery of this.querySet.values()) {\n const add: AddQuery = {\n type: \"Add\",\n queryId: localQuery.id,\n udfPath: localQuery.canonicalizedUdfPath,\n args: [convexToJson(localQuery.args)],\n journal: localQuery.journal,\n componentPath: localQuery.componentPath,\n };\n modifications.push(add);\n\n // Track all re-sent queries as outstanding so the backoff retry\n // counter doesn't reset until the server has re-confirmed results\n // for every active query.\n this.outstandingQueriesOlderThanRestart.add(localQuery.id);\n }\n this.querySetVersion = 1;\n const querySet: QuerySetModification = {\n type: \"ModifyQuerySet\",\n baseVersion: 0,\n newVersion: 1,\n modifications,\n };\n // If there's no auth, no need to send an update as the server will also start with an unknown identity.\n if (!this.auth) {\n this.identityVersion = 0;\n return [querySet, undefined];\n }\n this.outstandingAuthOlderThanRestart = true;\n const authenticate: Authenticate = {\n type: \"Authenticate\",\n baseVersion: 0,\n ...this.auth,\n };\n this.identityVersion = 1;\n return [querySet, authenticate];\n }\n\n pause() {\n this.paused = true;\n }\n\n resume(): [QuerySetModification | undefined, Authenticate | undefined] {\n const querySet: QuerySetModification | undefined =\n this.pendingQuerySetModifications.size > 0\n ? {\n type: \"ModifyQuerySet\",\n baseVersion: this.querySetVersion,\n newVersion: ++this.querySetVersion,\n modifications: Array.from(\n this.pendingQuerySetModifications.values(),\n ),\n }\n : undefined;\n const authenticate: Authenticate | undefined =\n this.auth !== undefined\n ? {\n type: \"Authenticate\",\n baseVersion: this.identityVersion++,\n ...this.auth,\n }\n : undefined;\n\n this.unpause();\n\n return [querySet, authenticate];\n }\n\n private unpause() {\n this.paused = false;\n this.pendingQuerySetModifications.clear();\n }\n\n private removeSubscriber(\n queryToken: QueryToken,\n ): QuerySetModification | null {\n const localQuery = this.querySet.get(queryToken)!;\n\n if (localQuery.numSubscribers > 1) {\n localQuery.numSubscribers -= 1;\n return null;\n } else {\n this.querySet.delete(queryToken);\n this.queryIdToToken.delete(localQuery.id);\n this.outstandingQueriesOlderThanRestart.delete(localQuery.id);\n const baseVersion = this.querySetVersion;\n const newVersion = this.querySetVersion + 1;\n const remove: RemoveQuery = {\n type: \"Remove\",\n queryId: localQuery.id,\n };\n if (this.paused) {\n if (this.pendingQuerySetModifications.has(localQuery.id)) {\n this.pendingQuerySetModifications.delete(localQuery.id);\n } else {\n this.pendingQuerySetModifications.set(localQuery.id, remove);\n }\n } else {\n this.querySetVersion = newVersion;\n }\n return {\n type: \"ModifyQuerySet\",\n baseVersion,\n newVersion,\n modifications: [remove],\n };\n }\n }\n}\n", "import { jsonToConvex } from \"../../values/index.js\";\nimport { logForFunction, Logger } from \"../logging.js\";\nimport { Long } from \"../../vendor/long.js\";\nimport { FunctionResult } from \"./function_result.js\";\nimport {\n ActionRequest,\n ActionResponse,\n ClientMessage,\n MutationRequest,\n MutationResponse,\n RequestId,\n} from \"./protocol.js\";\n\ntype RequestStatus =\n | {\n status: \"Requested\" | \"NotSent\";\n onResult: (result: FunctionResult) => void;\n requestedAt: Date;\n }\n | {\n status: \"Completed\";\n result: FunctionResult;\n onResolve: () => void;\n ts: Long;\n };\n\nexport class RequestManager {\n private inflightRequests: Map<\n RequestId,\n {\n message: MutationRequest | ActionRequest;\n status: RequestStatus;\n }\n >;\n private requestsOlderThanRestart: Set<RequestId>;\n private inflightMutationsCount: number = 0;\n private inflightActionsCount: number = 0;\n constructor(\n private readonly logger: Logger,\n private readonly markConnectionStateDirty: () => void,\n ) {\n this.inflightRequests = new Map();\n this.requestsOlderThanRestart = new Set();\n }\n\n request(\n message: MutationRequest | ActionRequest,\n sent: boolean,\n ): Promise<FunctionResult> {\n const result = new Promise<FunctionResult>((resolve) => {\n const status = sent ? \"Requested\" : \"NotSent\";\n this.inflightRequests.set(message.requestId, {\n message,\n status: { status, requestedAt: new Date(), onResult: resolve },\n });\n\n if (message.type === \"Mutation\") {\n this.inflightMutationsCount++;\n } else if (message.type === \"Action\") {\n this.inflightActionsCount++;\n }\n });\n\n this.markConnectionStateDirty();\n return result;\n }\n\n /**\n * Update the state after receiving a response.\n *\n * @returns A RequestId if the request is complete and its optimistic update\n * can be dropped, null otherwise.\n */\n onResponse(\n response: MutationResponse | ActionResponse,\n ): { requestId: RequestId; result: FunctionResult } | null {\n const requestInfo = this.inflightRequests.get(response.requestId);\n if (requestInfo === undefined) {\n // Annoyingly we can occasionally get responses to mutations that we're no\n // longer tracking. One flow where this happens is:\n // 1. Client sends mutation 1\n // 2. Client gets response for mutation 1. The sever says that it was committed at ts=10.\n // 3. Client is disconnected\n // 4. Client reconnects and re-issues queries and this mutation.\n // 5. Server sends transition message to ts=20\n // 6. Client drops mutation because it's already been observed.\n // 7. Client receives a second response for mutation 1 but doesn't know about it anymore.\n\n // The right fix for this is probably to add a reconciliation phase on\n // reconnection where we receive responses to all the mutations before\n // the transition message so this flow could never happen (CX-1513).\n\n // For now though, we can just ignore this message.\n return null;\n }\n\n // Because `.restart()` re-requests completed requests, we may get some\n // responses for requests that are already in the \"Completed\" state.\n // We can safely ignore those because we've already notified the UI about\n // their results.\n if (requestInfo.status.status === \"Completed\") {\n return null;\n }\n\n const udfType =\n requestInfo.message.type === \"Mutation\" ? \"mutation\" : \"action\";\n const udfPath = requestInfo.message.udfPath;\n\n for (const line of response.logLines) {\n logForFunction(this.logger, \"info\", udfType, udfPath, line);\n }\n\n const status = requestInfo.status;\n let result: FunctionResult;\n let onResolve;\n if (response.success) {\n result = {\n success: true,\n logLines: response.logLines,\n value: jsonToConvex(response.result),\n };\n onResolve = () => status.onResult(result);\n } else {\n const errorMessage = response.result as string;\n const { errorData } = response;\n logForFunction(this.logger, \"error\", udfType, udfPath, errorMessage);\n result = {\n success: false,\n errorMessage,\n errorData:\n errorData !== undefined ? jsonToConvex(errorData) : undefined,\n logLines: response.logLines,\n };\n onResolve = () => status.onResult(result);\n }\n\n // We can resolve Mutation failures immediately since they don't have any\n // side effects. Actions are intentionally decoupled from\n // queries/mutations here on the sync protocol since they have different\n // guarantees.\n if (response.type === \"ActionResponse\" || !response.success) {\n onResolve();\n this.inflightRequests.delete(response.requestId);\n this.requestsOlderThanRestart.delete(response.requestId);\n\n if (requestInfo.message.type === \"Action\") {\n this.inflightActionsCount--;\n } else if (requestInfo.message.type === \"Mutation\") {\n this.inflightMutationsCount--;\n }\n\n this.markConnectionStateDirty();\n return { requestId: response.requestId, result };\n }\n\n // We have to wait to resolve the request promise until after we transition\n // past this timestamp so clients can read their own writes.\n requestInfo.status = {\n status: \"Completed\",\n result,\n ts: response.ts,\n onResolve,\n };\n\n return null;\n }\n\n // Remove and returns completed requests.\n removeCompleted(ts: Long): Map<RequestId, FunctionResult> {\n const completeRequests: Map<RequestId, FunctionResult> = new Map();\n for (const [requestId, requestInfo] of this.inflightRequests.entries()) {\n const status = requestInfo.status;\n if (status.status === \"Completed\" && status.ts.lessThanOrEqual(ts)) {\n status.onResolve();\n completeRequests.set(requestId, status.result);\n\n if (requestInfo.message.type === \"Mutation\") {\n this.inflightMutationsCount--;\n } else if (requestInfo.message.type === \"Action\") {\n this.inflightActionsCount--;\n }\n\n this.inflightRequests.delete(requestId);\n this.requestsOlderThanRestart.delete(requestId);\n }\n }\n if (completeRequests.size > 0) {\n this.markConnectionStateDirty();\n }\n return completeRequests;\n }\n\n restart(): ClientMessage[] {\n // When we reconnect to the backend, re-request all requests that are safe\n // to be resend.\n\n this.requestsOlderThanRestart = new Set(this.inflightRequests.keys());\n const allMessages = [];\n for (const [requestId, value] of this.inflightRequests) {\n if (value.status.status === \"NotSent\") {\n value.status.status = \"Requested\";\n allMessages.push(value.message);\n continue;\n }\n\n if (value.message.type === \"Mutation\") {\n // This includes ones that have already been completed because we still\n // want to tell the backend to transition the client past the completed\n // timestamp. This is safe since mutations are idempotent.\n allMessages.push(value.message);\n } else if (value.message.type === \"Action\") {\n // Unlike mutations, actions are not idempotent. When we reconnect to the\n // backend, we don't know if it is safe to resend in-flight actions, so we\n // cancel them and consider them failed.\n this.inflightRequests.delete(requestId);\n this.requestsOlderThanRestart.delete(requestId);\n this.inflightActionsCount--;\n if (value.status.status === \"Completed\") {\n throw new Error(\"Action should never be in 'Completed' state\");\n }\n value.status.onResult({\n success: false,\n errorMessage: \"Connection lost while action was in flight\",\n logLines: [],\n });\n }\n }\n this.markConnectionStateDirty();\n return allMessages;\n }\n\n resume(): ClientMessage[] {\n const allMessages = [];\n for (const [, value] of this.inflightRequests) {\n if (value.status.status === \"NotSent\") {\n value.status.status = \"Requested\";\n allMessages.push(value.message);\n continue;\n }\n }\n return allMessages;\n }\n\n /**\n * @returns true if there are any requests that have been requested but have\n * not be completed yet.\n */\n hasIncompleteRequests(): boolean {\n for (const requestInfo of this.inflightRequests.values()) {\n if (requestInfo.status.status === \"Requested\") {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @returns true if there are any inflight requests, including ones that have\n * completed on the server, but have not been applied.\n */\n hasInflightRequests(): boolean {\n return this.inflightRequests.size > 0;\n }\n\n /**\n * @returns true if there are any inflight requests, that have been hanging around\n * since prior to the most recent restart.\n */\n hasSyncedPastLastReconnect(): boolean {\n return this.requestsOlderThanRestart.size === 0;\n }\n\n timeOfOldestInflightRequest(): Date | null {\n if (this.inflightRequests.size === 0) {\n return null;\n }\n let oldestInflightRequest = Date.now();\n for (const request of this.inflightRequests.values()) {\n if (request.status.status !== \"Completed\") {\n if (request.status.requestedAt.getTime() < oldestInflightRequest) {\n oldestInflightRequest = request.status.requestedAt.getTime();\n }\n }\n }\n return new Date(oldestInflightRequest);\n }\n\n /**\n * @returns The number of mutations currently in flight.\n */\n inflightMutations(): number {\n return this.inflightMutationsCount;\n }\n\n /**\n * @returns The number of actions currently in flight.\n */\n inflightActions(): number {\n return this.inflightActionsCount;\n }\n}\n", "/**\n * A symbol for accessing the name of a {@link FunctionReference} at runtime.\n */\nexport const functionName = Symbol.for(\"functionName\");\n", "import { functionName } from \"../functionName.js\";\n\nexport const toReferencePath = Symbol.for(\"toReferencePath\");\n\n// Multiple instances of the same Symbol.for() are equal at runtime but not\n// at type-time, so `[toReferencePath]` properties aren't used in types.\n// Use this function to set the property invisibly.\nexport function setReferencePath<T>(obj: T, value: string) {\n (obj as any)[toReferencePath] = value;\n}\n\nexport function extractReferencePath(reference: any): string | null {\n return reference[toReferencePath] ?? null;\n}\n\nexport function isFunctionHandle(s: string): boolean {\n return s.startsWith(\"function://\");\n}\n\nexport function getFunctionAddress(functionReference: any) {\n // The `run*` syscalls expect either a UDF path at \"name\" or a serialized\n // reference at \"reference\". Dispatch on `functionReference` to coerce\n // it to one or the other.\n let functionAddress;\n\n // Legacy path for passing in UDF paths directly as function references.\n if (typeof functionReference === \"string\") {\n if (isFunctionHandle(functionReference)) {\n functionAddress = { functionHandle: functionReference };\n } else {\n functionAddress = { name: functionReference };\n }\n }\n // Path for passing in a `FunctionReference`, either from `api` or directly\n // created from a UDF path with `makeFunctionReference`.\n else if (functionReference[functionName]) {\n functionAddress = { name: functionReference[functionName] };\n }\n // Reference to a component's function derived from `app` or `component`.\n else {\n const referencePath = extractReferencePath(functionReference);\n if (!referencePath) {\n throw new Error(`${functionReference} is not a functionReference`);\n }\n functionAddress = { reference: referencePath };\n }\n return functionAddress;\n}\n", "import {\n EmptyObject,\n DefaultFunctionArgs,\n FunctionVisibility,\n RegisteredAction,\n RegisteredMutation,\n RegisteredQuery,\n} from \"./registration.js\";\nimport { Expand, UnionToIntersection } from \"../type_utils.js\";\nimport { PaginationOptions, PaginationResult } from \"./pagination.js\";\nimport { functionName } from \"./functionName.js\";\nimport { getFunctionAddress } from \"./components/paths.js\";\n\n/**\n * The type of a Convex function.\n *\n * @public\n */\nexport type FunctionType = \"query\" | \"mutation\" | \"action\";\n\n/**\n * A reference to a registered Convex function.\n *\n * You can create a {@link FunctionReference} using the generated `api` utility:\n * ```js\n * import { api } from \"../convex/_generated/api\";\n *\n * const reference = api.myModule.myFunction;\n * ```\n *\n * If you aren't using code generation, you can create references using\n * {@link anyApi}:\n * ```js\n * import { anyApi } from \"convex/server\";\n *\n * const reference = anyApi.myModule.myFunction;\n * ```\n *\n * Function references can be used to invoke functions from the client. For\n * example, in React you can pass references to the {@link react.useQuery} hook:\n * ```js\n * const result = useQuery(api.myModule.myFunction);\n * ```\n *\n * @typeParam Type - The type of the function (\"query\", \"mutation\", or \"action\").\n * @typeParam Visibility - The visibility of the function (\"public\" or \"internal\").\n * @typeParam Args - The arguments to this function. This is an object mapping\n * argument names to their types.\n * @typeParam ReturnType - The return type of this function.\n * @public\n */\nexport type FunctionReference<\n Type extends FunctionType,\n Visibility extends FunctionVisibility = \"public\",\n Args extends DefaultFunctionArgs = any,\n ReturnType = any,\n ComponentPath = string | undefined,\n> = {\n _type: Type;\n _visibility: Visibility;\n _args: Args;\n _returnType: ReturnType;\n _componentPath: ComponentPath;\n};\n\n/**\n * Get the name of a function from a {@link FunctionReference}.\n *\n * The name is a string like \"myDir/myModule:myFunction\". If the exported name\n * of the function is `\"default\"`, the function name is omitted\n * (e.g. \"myDir/myModule\").\n *\n * @param functionReference - A {@link FunctionReference} to get the name of.\n * @returns A string of the function's name.\n *\n * @public\n */\nexport function getFunctionName(\n functionReference: AnyFunctionReference,\n): string {\n const address = getFunctionAddress(functionReference);\n\n if (address.name === undefined) {\n if (address.functionHandle !== undefined) {\n throw new Error(\n `Expected function reference like \"api.file.func\" or \"internal.file.func\", but received function handle ${address.functionHandle}`,\n );\n } else if (address.reference !== undefined) {\n throw new Error(\n `Expected function reference in the current component like \"api.file.func\" or \"internal.file.func\", but received reference ${address.reference}`,\n );\n }\n throw new Error(\n `Expected function reference like \"api.file.func\" or \"internal.file.func\", but received ${JSON.stringify(address)}`,\n );\n }\n // Both a legacy thing and also a convenience for interactive use:\n // the types won't check but a string is always allowed at runtime.\n if (typeof functionReference === \"string\") return functionReference;\n\n // Two different runtime values for FunctionReference implement this\n // interface: api objects returned from `createApi()` and standalone\n // function reference objects returned from makeFunctionReference.\n const name = (functionReference as any)[functionName];\n if (!name) {\n throw new Error(`${functionReference as any} is not a functionReference`);\n }\n return name;\n}\n\n/**\n * FunctionReferences generally come from generated code, but in custom clients\n * it may be useful to be able to build one manually.\n *\n * Real function references are empty objects at runtime, but the same interface\n * can be implemented with an object for tests and clients which don't use\n * code generation.\n *\n * @param name - The identifier of the function. E.g. `path/to/file:functionName`\n * @public\n */\nexport function makeFunctionReference<\n type extends FunctionType,\n args extends DefaultFunctionArgs = any,\n ret = any,\n>(name: string): FunctionReference<type, \"public\", args, ret> {\n return { [functionName]: name } as unknown as FunctionReference<\n type,\n \"public\",\n args,\n ret\n >;\n}\n\n/**\n * Create a runtime API object that implements {@link AnyApi}.\n *\n * This allows accessing any path regardless of what directories, modules,\n * or functions are defined.\n *\n * @param pathParts - The path to the current node in the API.\n * @returns An {@link AnyApi}\n * @public\n */\nfunction createApi(pathParts: string[] = []): AnyApi {\n const handler: ProxyHandler<object> = {\n get(_, prop: string | symbol) {\n if (typeof prop === \"string\") {\n const newParts = [...pathParts, prop];\n return createApi(newParts);\n } else if (prop === functionName) {\n if (pathParts.length < 2) {\n const found = [\"api\", ...pathParts].join(\".\");\n throw new Error(\n `API path is expected to be of the form \\`api.moduleName.functionName\\`. Found: \\`${found}\\``,\n );\n }\n const path = pathParts.slice(0, -1).join(\"/\");\n const exportName = pathParts[pathParts.length - 1];\n if (exportName === \"default\") {\n return path;\n } else {\n return path + \":\" + exportName;\n }\n } else if (prop === Symbol.toStringTag) {\n return \"FunctionReference\";\n } else {\n return undefined;\n }\n },\n };\n\n return new Proxy({}, handler);\n}\n\n/**\n * Given an export from a module, convert it to a {@link FunctionReference}\n * if it is a Convex function.\n */\nexport type FunctionReferenceFromExport<Export> =\n Export extends RegisteredQuery<\n infer Visibility,\n infer Args,\n infer ReturnValue\n >\n ? FunctionReference<\n \"query\",\n Visibility,\n Args,\n ConvertReturnType<ReturnValue>\n >\n : Export extends RegisteredMutation<\n infer Visibility,\n infer Args,\n infer ReturnValue\n >\n ? FunctionReference<\n \"mutation\",\n Visibility,\n Args,\n ConvertReturnType<ReturnValue>\n >\n : Export extends RegisteredAction<\n infer Visibility,\n infer Args,\n infer ReturnValue\n >\n ? FunctionReference<\n \"action\",\n Visibility,\n Args,\n ConvertReturnType<ReturnValue>\n >\n : never;\n\n/**\n * Given a module, convert all the Convex functions into\n * {@link FunctionReference}s and remove the other exports.\n *\n * BE CAREFUL WHEN EDITING THIS!\n *\n * This is written carefully to preserve jumping to function definitions using\n * cmd+click. If you edit it, please test that cmd+click still works.\n */\ntype FunctionReferencesInModule<Module extends Record<string, any>> = {\n -readonly [ExportName in keyof Module as Module[ExportName][\"isConvexFunction\"] extends true\n ? ExportName\n : never]: FunctionReferenceFromExport<Module[ExportName]>;\n};\n\n/**\n * Given a path to a module and it's type, generate an API type for this module.\n *\n * This is a nested object according to the module's path.\n */\ntype ApiForModule<\n ModulePath extends string,\n Module extends object,\n> = ModulePath extends `${infer First}/${infer Second}`\n ? {\n [_ in First]: ApiForModule<Second, Module>;\n }\n : { [_ in ModulePath]: FunctionReferencesInModule<Module> };\n\n/**\n * Given the types of all modules in the `convex/` directory, construct the type\n * of `api`.\n *\n * `api` is a utility for constructing {@link FunctionReference}s.\n *\n * @typeParam AllModules - A type mapping module paths (like `\"dir/myModule\"`) to\n * the types of the modules.\n * @public\n */\nexport type ApiFromModules<AllModules extends Record<string, object>> =\n FilterApi<\n ApiFromModulesAllowEmptyNodes<AllModules>,\n FunctionReference<any, any, any, any>\n >;\n\ntype ApiFromModulesAllowEmptyNodes<AllModules extends Record<string, object>> =\n ExpandModulesAndDirs<\n UnionToIntersection<\n {\n [ModulePath in keyof AllModules]: ApiForModule<\n ModulePath & string,\n AllModules[ModulePath]\n >;\n }[keyof AllModules]\n >\n >;\n\ntype FilterKeysInApi<key, API, Predicate> = API extends Predicate\n ? key\n : API extends FunctionReference<any, any, any, any>\n ? never\n : FilterApi<API, Predicate> extends Record<string, never>\n ? never\n : key;\n\n/**\n * @public\n *\n * Filter a Convex deployment api object for functions which meet criteria,\n * for example all public queries.\n */\nexport type FilterApi<API, Predicate> = Expand<{\n [mod in keyof API as FilterKeysInApi<\n mod,\n API[mod],\n Predicate\n >]: API[mod] extends Predicate ? API[mod] : FilterApi<API[mod], Predicate>;\n}>;\n\n/**\n * Given an api of type API and a FunctionReference subtype, return an api object\n * containing only the function references that match.\n *\n * ```ts\n * const q = filterApi<typeof api, FunctionReference<\"query\">>(api)\n * ```\n *\n * @public\n */\nexport function filterApi<API, Predicate>(api: API): FilterApi<API, Predicate> {\n return api as any;\n}\n\n// These just* API filter helpers require no type parameters so are useable from JavaScript.\n/** @public */\nexport function justInternal<API>(\n api: API,\n): FilterApi<API, FunctionReference<any, \"internal\", any, any>> {\n return api as any;\n}\n\n/** @public */\nexport function justPublic<API>(\n api: API,\n): FilterApi<API, FunctionReference<any, \"public\", any, any>> {\n return api as any;\n}\n\n/** @public */\nexport function justQueries<API>(\n api: API,\n): FilterApi<API, FunctionReference<\"query\", any, any, any>> {\n return api as any;\n}\n\n/** @public */\nexport function justMutations<API>(\n api: API,\n): FilterApi<API, FunctionReference<\"mutation\", any, any, any>> {\n return api as any;\n}\n\n/** @public */\nexport function justActions<API>(\n api: API,\n): FilterApi<API, FunctionReference<\"action\", any, any, any>> {\n return api as any;\n}\n\n/** @public */\nexport function justPaginatedQueries<API>(\n api: API,\n): FilterApi<\n API,\n FunctionReference<\n \"query\",\n any,\n { paginationOpts: PaginationOptions },\n PaginationResult<any>\n >\n> {\n return api as any;\n}\n\n/** @public */\nexport function justSchedulable<API>(\n api: API,\n): FilterApi<API, FunctionReference<\"mutation\" | \"action\", any, any, any>> {\n return api as any;\n}\n\n/**\n * Like {@link Expand}, this simplifies how TypeScript displays object types.\n * The differences are:\n * 1. This version is recursive.\n * 2. This stops recursing when it hits a {@link FunctionReference}.\n */\ntype ExpandModulesAndDirs<ObjectType> = ObjectType extends AnyFunctionReference\n ? ObjectType\n : {\n [Key in keyof ObjectType]: ExpandModulesAndDirs<ObjectType[Key]>;\n };\n\n/**\n * A {@link FunctionReference} of any type and any visibility with any\n * arguments and any return type.\n *\n * @public\n */\nexport type AnyFunctionReference = FunctionReference<any, any>;\n\ntype AnyModuleDirOrFunc = {\n [key: string]: AnyModuleDirOrFunc;\n} & AnyFunctionReference;\n\n/**\n * The type that Convex api objects extend. If you were writing an api from\n * scratch it should extend this type.\n *\n * @public\n */\nexport type AnyApi = Record<string, Record<string, AnyModuleDirOrFunc>>;\n\n/**\n * Recursive partial API, useful for defining a subset of an API when mocking\n * or building custom api objects.\n *\n * @public\n */\nexport type PartialApi<API> = {\n [mod in keyof API]?: API[mod] extends FunctionReference<any, any, any, any>\n ? API[mod]\n : PartialApi<API[mod]>;\n};\n\n/**\n * A utility for constructing {@link FunctionReference}s in projects that\n * are not using code generation.\n *\n * You can create a reference to a function like:\n * ```js\n * const reference = anyApi.myModule.myFunction;\n * ```\n *\n * This supports accessing any path regardless of what directories and modules\n * are in your project. All function references are typed as\n * {@link AnyFunctionReference}.\n *\n *\n * If you're using code generation, use `api` from `convex/_generated/api`\n * instead. It will be more type-safe and produce better auto-complete\n * in your editor.\n *\n * @public\n */\nexport const anyApi: AnyApi = createApi() as any;\n\n/**\n * Given a {@link FunctionReference}, get the return type of the function.\n *\n * This is represented as an object mapping argument names to values.\n * @public\n */\nexport type FunctionArgs<FuncRef extends AnyFunctionReference> =\n FuncRef[\"_args\"];\n\n/**\n * A tuple type of the (maybe optional) arguments to `FuncRef`.\n *\n * This type is used to make methods involving arguments type safe while allowing\n * skipping the arguments for functions that don't require arguments.\n *\n * @public\n */\nexport type OptionalRestArgs<FuncRef extends AnyFunctionReference> =\n FuncRef[\"_args\"] extends EmptyObject\n ? [args?: EmptyObject]\n : [args: FuncRef[\"_args\"]];\n\n/**\n * A tuple type of the (maybe optional) arguments to `FuncRef`, followed by an options\n * object of type `Options`.\n *\n * This type is used to make methods like `useQuery` type-safe while allowing\n * 1. Skipping arguments for functions that don't require arguments.\n * 2. Skipping the options object.\n * @public\n */\nexport type ArgsAndOptions<\n FuncRef extends AnyFunctionReference,\n Options,\n> = FuncRef[\"_args\"] extends EmptyObject\n ? [args?: EmptyObject, options?: Options]\n : [args: FuncRef[\"_args\"], options?: Options];\n\n/**\n * Given a {@link FunctionReference}, get the return type of the function.\n *\n * @public\n */\nexport type FunctionReturnType<FuncRef extends AnyFunctionReference> =\n FuncRef[\"_returnType\"];\n\ntype UndefinedToNull<T> = T extends void ? null : T;\n\ntype NullToUndefinedOrNull<T> = T extends null ? T | undefined | void : T;\n\n/**\n * Convert the return type of a function to it's client-facing format.\n *\n * This means:\n * - Converting `undefined` and `void` to `null`\n * - Removing all `Promise` wrappers\n */\nexport type ConvertReturnType<T> = UndefinedToNull<Awaited<T>>;\n\nexport type ValidatorTypeToReturnType<T> =\n | Promise<NullToUndefinedOrNull<T>>\n | NullToUndefinedOrNull<T>;\n", "import {\n FunctionArgs,\n FunctionReference,\n FunctionReturnType,\n OptionalRestArgs,\n getFunctionName,\n} from \"../../server/api.js\";\nimport { parseArgs } from \"../../common/index.js\";\nimport { Value } from \"../../values/index.js\";\nimport { createHybridErrorStacktrace, forwardData } from \"../logging.js\";\nimport { FunctionResult } from \"./function_result.js\";\nimport { OptimisticLocalStore } from \"./optimistic_updates.js\";\nimport { RequestId } from \"./protocol.js\";\nimport {\n canonicalizeUdfPath,\n QueryToken,\n serializePathAndArgs,\n} from \"./udf_path_utils.js\";\nimport { ConvexError } from \"../../values/errors.js\";\n\n/**\n * An optimistic update function that has been curried over its arguments.\n */\ntype WrappedOptimisticUpdate = (locaQueryStore: OptimisticLocalStore) => void;\n\n/**\n * The implementation of `OptimisticLocalStore`.\n *\n * This class provides the interface for optimistic updates to modify query results.\n */\nclass OptimisticLocalStoreImpl implements OptimisticLocalStore {\n // A references of the query results in OptimisticQueryResults\n private readonly queryResults: QueryResultsMap;\n\n // All of the queries modified by this class\n readonly modifiedQueries: QueryToken[];\n\n constructor(queryResults: QueryResultsMap) {\n this.queryResults = queryResults;\n this.modifiedQueries = [];\n }\n\n getQuery<Query extends FunctionReference<\"query\">>(\n query: Query,\n ...args: OptionalRestArgs<Query>\n ): undefined | FunctionReturnType<Query> {\n const queryArgs = parseArgs(args[0]);\n const name = getFunctionName(query);\n const queryResult = this.queryResults.get(\n serializePathAndArgs(name, queryArgs),\n );\n if (queryResult === undefined) {\n return undefined;\n }\n return OptimisticLocalStoreImpl.queryValue(queryResult.result);\n }\n\n getAllQueries<Query extends FunctionReference<\"query\">>(\n query: Query,\n ): {\n args: FunctionArgs<Query>;\n value: undefined | FunctionReturnType<Query>;\n }[] {\n const queriesWithName: {\n args: FunctionArgs<Query>;\n value: undefined | FunctionReturnType<Query>;\n }[] = [];\n const name = getFunctionName(query);\n for (const queryResult of this.queryResults.values()) {\n if (queryResult.udfPath === canonicalizeUdfPath(name)) {\n queriesWithName.push({\n args: queryResult.args as FunctionArgs<Query>,\n value: OptimisticLocalStoreImpl.queryValue(queryResult.result),\n });\n }\n }\n return queriesWithName;\n }\n\n setQuery<QueryReference extends FunctionReference<\"query\">>(\n queryReference: QueryReference,\n args: FunctionArgs<QueryReference>,\n value: undefined | FunctionReturnType<QueryReference>,\n ): void {\n const queryArgs = parseArgs(args);\n const name = getFunctionName(queryReference);\n const queryToken = serializePathAndArgs(name, queryArgs);\n\n let result: FunctionResult | undefined;\n if (value === undefined) {\n result = undefined;\n } else {\n result = {\n success: true,\n value,\n // It's an optimistic update, so there are no function logs to show.\n logLines: [],\n };\n }\n const query: Query = {\n udfPath: name,\n args: queryArgs,\n result,\n };\n this.queryResults.set(queryToken, query);\n this.modifiedQueries.push(queryToken);\n }\n\n private static queryValue(\n result: FunctionResult | undefined,\n ): Value | undefined {\n if (result === undefined) {\n return undefined;\n } else if (result.success) {\n return result.value;\n } else {\n // If the query is an error state, just return `undefined` as though\n // it's loading. Optimistic updates should already handle `undefined` well\n // and there isn't a need to break the whole update because it tried\n // to load a single query that errored.\n return undefined;\n }\n }\n}\n\ntype OptimisticUpdateAndId = {\n update: WrappedOptimisticUpdate;\n mutationId: RequestId;\n};\n\ntype Query = {\n // undefined means the query was set to be loading (undefined) in an optimistic update.\n // Note that we can also have queries not present in the QueryResultMap\n // at all because they are still loading from the server and have no optimistic update\n // setting an optimistic value in advance.\n result: FunctionResult | undefined;\n udfPath: string;\n args: Record<string, Value>;\n};\nexport type QueryResultsMap = Map<QueryToken, Query>;\n\ntype ChangedQueries = QueryToken[];\n\n/**\n * A view of all of our query results with optimistic updates applied on top.\n */\nexport class OptimisticQueryResults {\n private queryResults: QueryResultsMap;\n private optimisticUpdates: OptimisticUpdateAndId[];\n\n constructor() {\n this.queryResults = new Map();\n this.optimisticUpdates = [];\n }\n\n /**\n * Apply all optimistic updates on top of server query results\n */\n ingestQueryResultsFromServer(\n serverQueryResults: QueryResultsMap,\n optimisticUpdatesToDrop: Set<RequestId>,\n ): ChangedQueries {\n this.optimisticUpdates = this.optimisticUpdates.filter((updateAndId) => {\n return !optimisticUpdatesToDrop.has(updateAndId.mutationId);\n });\n\n const oldQueryResults = this.queryResults;\n this.queryResults = new Map(serverQueryResults);\n const localStore = new OptimisticLocalStoreImpl(this.queryResults);\n for (const updateAndId of this.optimisticUpdates) {\n updateAndId.update(localStore);\n }\n\n // To find the changed queries, just do a shallow comparison\n // TODO(CX-733): Change this so we avoid unnecessary rerenders\n const changedQueries: ChangedQueries = [];\n for (const [queryToken, query] of this.queryResults) {\n const oldQuery = oldQueryResults.get(queryToken);\n if (oldQuery === undefined || oldQuery.result !== query.result) {\n changedQueries.push(queryToken);\n }\n }\n\n return changedQueries;\n }\n\n applyOptimisticUpdate(\n update: WrappedOptimisticUpdate,\n mutationId: RequestId,\n ): ChangedQueries {\n // Apply the update to our store\n this.optimisticUpdates.push({\n update,\n mutationId,\n });\n const localStore = new OptimisticLocalStoreImpl(this.queryResults);\n update(localStore);\n\n // Notify about any query results that changed\n // TODO(CX-733): Change this so we avoid unnecessary rerenders\n return localStore.modifiedQueries;\n }\n\n /**\n * \"Raw\" with respect to errors vs values, but query results still have\n * optimistic updates applied.\n *\n * @internal\n */\n rawQueryResult(queryToken: QueryToken): FunctionResult | undefined {\n const query = this.queryResults.get(queryToken);\n if (query === undefined) {\n return undefined;\n }\n return query.result;\n }\n\n queryResult(queryToken: QueryToken): Value | undefined {\n const query = this.queryResults.get(queryToken);\n if (query === undefined) {\n return undefined;\n }\n const result = query.result;\n if (result === undefined) {\n return undefined;\n } else if (result.success) {\n return result.value;\n } else {\n if (result.errorData !== undefined) {\n throw forwardData(\n result,\n new ConvexError(\n createHybridErrorStacktrace(\"query\", query.udfPath, result),\n ),\n );\n }\n throw new Error(\n createHybridErrorStacktrace(\"query\", query.udfPath, result),\n );\n }\n }\n\n hasQueryResult(queryToken: QueryToken): boolean {\n return this.queryResults.get(queryToken) !== undefined;\n }\n\n /**\n * @internal\n */\n queryLogs(queryToken: QueryToken): string[] | undefined {\n const query = this.queryResults.get(queryToken);\n return query?.result?.logLines;\n }\n}\n", "// Implements an unsigned long.\n// This is a subset of https://github.com/dcodeIO/Long.js,\n// vendored to decrease bundle size.\n// Copyright Daniel Wirtz <dcode@dcode.io>\n// License: Apache Version 2.0\n/*\n\n Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright 2023 Daniel Wirtz <dcode@dcode.io>\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n*/\n\n// This works... but don't try to compare one to a real Long.js Long!\n// For internal use only.\n// `| 0` assures the runtime that we are using integer arithmetic\nexport class Long {\n low: number;\n high: number;\n __isUnsignedLong__: boolean;\n\n static isLong(obj: Long) {\n return (obj && obj.__isUnsignedLong__) === true;\n }\n\n constructor(low: number, high: number) {\n this.low = low | 0;\n this.high = high | 0;\n this.__isUnsignedLong__ = true;\n }\n\n // prettier-ignore\n static fromBytesLE(bytes: number[]): Long {\n return new Long(\n bytes[0] |\n bytes[1] << 8 |\n bytes[2] << 16 |\n bytes[3] << 24,\n bytes[4] |\n bytes[5] << 8 |\n bytes[6] << 16 |\n bytes[7] << 24,\n );\n }\n\n // prettier-ignore\n toBytesLE() {\n const hi = this.high;\n const lo = this.low;\n return [\n lo & 0xff,\n lo >>> 8 & 0xff,\n lo >>> 16 & 0xff,\n lo >>> 24,\n hi & 0xff,\n hi >>> 8 & 0xff,\n hi >>> 16 & 0xff,\n hi >>> 24\n ];\n }\n\n static fromNumber(value: number) {\n if (isNaN(value)) return UZERO;\n if (value < 0) return UZERO;\n if (value >= TWO_PWR_64_DBL) return MAX_UNSIGNED_VALUE;\n return new Long(value % TWO_PWR_32_DBL | 0, (value / TWO_PWR_32_DBL) | 0);\n }\n\n toString() {\n return (\n BigInt(this.high) * BigInt(TWO_PWR_32_DBL) +\n BigInt(this.low)\n ).toString();\n }\n\n equals(other: Long) {\n if (!Long.isLong(other)) other = Long.fromValue(other);\n if (this.high >>> 31 === 1 && other.high >>> 31 === 1) return false;\n return this.high === other.high && this.low === other.low;\n }\n\n notEquals(other: Long) {\n return !this.equals(other);\n }\n\n comp(other: Long) {\n if (!Long.isLong(other)) other = Long.fromValue(other);\n if (this.equals(other)) return 0;\n return other.high >>> 0 > this.high >>> 0 ||\n (other.high === this.high && other.low >>> 0 > this.low >>> 0)\n ? -1\n : 1;\n }\n\n lessThanOrEqual(other: Long) {\n return this.comp(/* validates */ other) <= 0;\n }\n\n static fromValue(val: any) {\n if (typeof val === \"number\") return Long.fromNumber(val);\n // Throws for non-objects, converts non-instanceof Long:\n return new Long(val.low, val.high);\n }\n}\n\nconst UZERO = new Long(0, 0);\nconst TWO_PWR_16_DBL = 1 << 16;\nconst TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;\nconst TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;\nconst MAX_UNSIGNED_VALUE = new Long(0xffffffff | 0, 0xffffffff | 0);\n", "import { jsonToConvex } from \"../../values/index.js\";\nimport { Long } from \"../../vendor/long.js\";\nimport { logForFunction, Logger } from \"../logging.js\";\nimport { QueryId, StateVersion, Transition } from \"./protocol.js\";\nimport { FunctionResult } from \"./function_result.js\";\n\n/**\n * A represention of the query results we've received on the current WebSocket\n * connection.\n *\n * Queries you won't find here include:\n * - queries which have been requested, but no query transition has been received yet for\n * - queries which are populated only though active optimistic updates, but are not subscribed to\n * - queries which have already been removed by the server (which it shouldn't do unless that's\n * been requested by the client)\n */\nexport class RemoteQuerySet {\n private version: StateVersion;\n private readonly remoteQuerySet: Map<QueryId, FunctionResult>;\n private readonly queryPath: (queryId: QueryId) => string | null;\n private readonly logger: Logger;\n\n constructor(queryPath: (queryId: QueryId) => string | null, logger: Logger) {\n this.version = { querySet: 0, ts: Long.fromNumber(0), identity: 0 };\n this.remoteQuerySet = new Map();\n this.queryPath = queryPath;\n this.logger = logger;\n }\n\n transition(transition: Transition): void {\n const start = transition.startVersion;\n if (\n this.version.querySet !== start.querySet ||\n this.version.ts.notEquals(start.ts) ||\n this.version.identity !== start.identity\n ) {\n throw new Error(\n `Invalid start version: ${start.ts.toString()}:${start.querySet}:${start.identity}, transitioning from ${this.version.ts.toString()}:${this.version.querySet}:${this.version.identity}`,\n );\n }\n for (const modification of transition.modifications) {\n switch (modification.type) {\n case \"QueryUpdated\": {\n const queryPath = this.queryPath(modification.queryId);\n if (queryPath) {\n for (const line of modification.logLines) {\n logForFunction(this.logger, \"info\", \"query\", queryPath, line);\n }\n }\n const value = jsonToConvex(modification.value ?? null);\n this.remoteQuerySet.set(modification.queryId, {\n success: true,\n value,\n logLines: modification.logLines,\n });\n break;\n }\n case \"QueryFailed\": {\n const queryPath = this.queryPath(modification.queryId);\n if (queryPath) {\n for (const line of modification.logLines) {\n logForFunction(this.logger, \"info\", \"query\", queryPath, line);\n }\n }\n const { errorData } = modification;\n this.remoteQuerySet.set(modification.queryId, {\n success: false,\n errorMessage: modification.errorMessage,\n errorData:\n errorData !== undefined ? jsonToConvex(errorData) : undefined,\n logLines: modification.logLines,\n });\n break;\n }\n case \"QueryRemoved\": {\n this.remoteQuerySet.delete(modification.queryId);\n break;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n modification satisfies never;\n throw new Error(`Invalid modification ${(modification as any).type}`);\n }\n }\n }\n this.version = transition.endVersion;\n }\n\n remoteQueryResults(): Map<QueryId, FunctionResult> {\n return this.remoteQuerySet;\n }\n\n timestamp(): Long {\n return this.version.ts;\n }\n}\n", "import type { UserIdentityAttributes } from \"../../server/authentication.js\";\nexport type { UserIdentityAttributes } from \"../../server/authentication.js\";\nimport { JSONValue, Base64 } from \"../../values/index.js\";\nimport { Long } from \"../../vendor/long.js\";\n\n/**\n * Shared schema\n */\n\nexport function u64ToLong(encoded: EncodedU64): U64 {\n const integerBytes = Base64.toByteArray(encoded);\n return Long.fromBytesLE(Array.from(integerBytes));\n}\n\nexport function longToU64(raw: U64): EncodedU64 {\n const integerBytes = new Uint8Array(raw.toBytesLE());\n return Base64.fromByteArray(integerBytes);\n}\n\nexport function parseServerMessage(\n encoded: EncodedServerMessage,\n): WireServerMessage {\n switch (encoded.type) {\n case \"FatalError\":\n case \"AuthError\":\n case \"ActionResponse\":\n case \"TransitionChunk\":\n case \"Ping\": {\n return { ...encoded };\n }\n case \"MutationResponse\": {\n if (encoded.success) {\n return { ...encoded, ts: u64ToLong(encoded.ts) };\n } else {\n return { ...encoded };\n }\n }\n case \"Transition\": {\n return {\n ...encoded,\n startVersion: {\n ...encoded.startVersion,\n ts: u64ToLong(encoded.startVersion.ts),\n },\n endVersion: {\n ...encoded.endVersion,\n ts: u64ToLong(encoded.endVersion.ts),\n },\n };\n }\n default: {\n encoded satisfies never;\n }\n }\n return undefined as never;\n}\n\nexport function encodeClientMessage(\n message: ClientMessage,\n): EncodedClientMessage {\n switch (message.type) {\n case \"Authenticate\":\n case \"ModifyQuerySet\":\n case \"Mutation\":\n case \"Action\":\n case \"Event\": {\n return { ...message };\n }\n case \"Connect\": {\n if (message.maxObservedTimestamp !== undefined) {\n return {\n ...message,\n maxObservedTimestamp: longToU64(message.maxObservedTimestamp),\n };\n } else {\n return { ...message, maxObservedTimestamp: undefined };\n }\n }\n default: {\n message satisfies never;\n }\n }\n return undefined as never;\n}\n\ntype U64 = Long;\ntype EncodedU64 = string;\n\n/**\n * Unique nonnegative integer identifying a single query.\n */\nexport type QueryId = number; // nonnegative int\n\nexport type QuerySetVersion = number; // nonnegative int\n\nexport type RequestId = number; // nonnegative int\n\nexport type IdentityVersion = number; // nonnegative int\n\n/**\n * A serialized representation of decisions made during a query's execution.\n *\n * A journal is produced when a query function first executes and is re-used\n * when a query is re-executed.\n *\n * Currently this is used to store pagination end cursors to ensure\n * that pages of paginated queries will always end at the same cursor. This\n * enables gapless, reactive pagination.\n *\n * `null` is used to represent empty journals.\n * @public\n */\nexport type QueryJournal = string | null;\n\n/**\n * Client message schema\n */\n\ntype Connect = {\n type: \"Connect\";\n sessionId: string;\n connectionCount: number;\n lastCloseReason: string | null;\n maxObservedTimestamp?: TS | undefined;\n clientTs: number;\n};\n\nexport type AddQuery = {\n type: \"Add\";\n queryId: QueryId;\n udfPath: string;\n args: JSONValue[];\n journal?: QueryJournal | undefined;\n /**\n * @internal\n */\n componentPath?: string | undefined;\n};\n\nexport type RemoveQuery = {\n type: \"Remove\";\n queryId: QueryId;\n};\n\nexport type QuerySetModification = {\n type: \"ModifyQuerySet\";\n baseVersion: QuerySetVersion;\n newVersion: QuerySetVersion;\n modifications: (AddQuery | RemoveQuery)[];\n};\n\nexport type MutationRequest = {\n type: \"Mutation\";\n requestId: RequestId;\n udfPath: string;\n args: JSONValue[];\n // Execute the mutation on a specific component.\n // Only admin auth is allowed to run mutations on non-root components.\n componentPath?: string | undefined;\n};\n\nexport type ActionRequest = {\n type: \"Action\";\n requestId: RequestId;\n udfPath: string;\n args: JSONValue[];\n // Execute the action on a specific component.\n // Only admin auth is allowed to run actions on non-root components.\n componentPath?: string | undefined;\n};\n\nexport type AdminAuthentication = {\n type: \"Authenticate\";\n tokenType: \"Admin\";\n value: string;\n baseVersion: IdentityVersion;\n impersonating?: UserIdentityAttributes | undefined;\n};\n\nexport type Authenticate =\n | AdminAuthentication\n | {\n type: \"Authenticate\";\n tokenType: \"User\";\n value: string;\n baseVersion: IdentityVersion;\n }\n | {\n type: \"Authenticate\";\n tokenType: \"None\";\n baseVersion: IdentityVersion;\n };\n\nexport type Event = {\n type: \"Event\";\n eventType: string;\n event: any;\n};\nexport type ClientMessage =\n | Connect\n | Authenticate\n | QuerySetModification\n | MutationRequest\n | ActionRequest\n | Event;\n\ntype EncodedConnect = Omit<Connect, \"maxObservedTimestamp\"> & {\n maxObservedTimestamp?: EncodedTS | undefined;\n};\n\n// It's not a big deal to add `| undefined` to any optional properties here because\n// these messages are bound for JSON.stringify() serialization, which removes properties\n// that are undefined.\ntype EncodedClientMessage =\n | EncodedConnect\n | Authenticate\n | QuerySetModification\n | MutationRequest\n | ActionRequest\n | Event;\n\n/**\n * Server message schema\n */\nexport type TS = U64;\ntype EncodedTS = EncodedU64;\ntype LogLines = string[];\n\nexport type StateVersion = {\n querySet: QuerySetVersion;\n ts: TS;\n identity: IdentityVersion;\n};\ntype EncodedStateVersion = Omit<StateVersion, \"ts\"> & { ts: EncodedTS };\n\ntype StateModification =\n | {\n type: \"QueryUpdated\";\n queryId: QueryId;\n value: JSONValue;\n logLines: LogLines;\n journal: QueryJournal;\n }\n | {\n type: \"QueryFailed\";\n queryId: QueryId;\n errorMessage: string;\n logLines: LogLines;\n errorData: JSONValue;\n journal: QueryJournal;\n }\n | {\n type: \"QueryRemoved\";\n queryId: QueryId;\n };\n\nexport type Transition = {\n type: \"Transition\";\n startVersion: StateVersion;\n endVersion: StateVersion;\n modifications: StateModification[];\n clientClockSkew?: number;\n serverTs?: number;\n};\n\nexport type TransitionChunk = {\n type: \"TransitionChunk\";\n chunk: string;\n partNumber: number;\n totalParts: number;\n transitionId: string;\n};\n\ntype MutationSuccess = {\n type: \"MutationResponse\";\n requestId: RequestId;\n success: true;\n result: JSONValue;\n ts: TS;\n logLines: LogLines;\n};\ntype MutationFailed = {\n type: \"MutationResponse\";\n requestId: RequestId;\n success: false;\n result: string;\n logLines: LogLines;\n errorData?: JSONValue;\n};\nexport type MutationResponse = MutationSuccess | MutationFailed;\ntype ActionSuccess = {\n type: \"ActionResponse\";\n requestId: RequestId;\n success: true;\n result: JSONValue;\n logLines: LogLines;\n};\ntype ActionFailed = {\n type: \"ActionResponse\";\n requestId: RequestId;\n success: false;\n result: string;\n logLines: LogLines;\n errorData?: JSONValue;\n};\nexport type ActionResponse = ActionSuccess | ActionFailed;\nexport type AuthError = {\n type: \"AuthError\";\n error: string;\n baseVersion: IdentityVersion;\n // True if this error is in response to processing a new `Authenticate` message.\n // Other AuthErrors may occur due to executing a function with expired auth and\n // should be handled differently.\n authUpdateAttempted: boolean;\n};\ntype FatalError = {\n type: \"FatalError\";\n error: string;\n};\ntype Ping = {\n type: \"Ping\";\n};\n\n// Server Messages without the messages only visible to WebSocketManager\nexport type ServerMessage =\n | Transition\n | MutationResponse\n | ActionResponse\n | FatalError\n | AuthError;\n\nexport type WireServerMessage =\n | Transition\n | TransitionChunk\n | MutationResponse\n | ActionResponse\n | FatalError\n | AuthError\n | Ping;\n\ntype EncodedTransition = Omit<Transition, \"startVersion\" | \"endVersion\"> & {\n startVersion: EncodedStateVersion;\n endVersion: EncodedStateVersion;\n};\ntype EncodedMutationSuccess = Omit<MutationSuccess, \"ts\"> & { ts: EncodedTS };\ntype EncodedMutationResponse = MutationFailed | EncodedMutationSuccess;\n\ntype EncodedServerMessage =\n | EncodedTransition\n | TransitionChunk\n | EncodedMutationResponse\n | ActionResponse\n | FatalError\n | AuthError\n | Ping;\n", "import { Logger } from \"../logging.js\";\nimport {\n ClientMessage,\n encodeClientMessage,\n parseServerMessage,\n ServerMessage,\n Transition,\n TransitionChunk,\n} from \"./protocol.js\";\n\nconst CLOSE_NORMAL = 1000;\nconst CLOSE_GOING_AWAY = 1001;\nconst CLOSE_NO_STATUS = 1005;\n/** Convex-specific close code representing a \"404 Not Found\".\n * The edge Onramp accepts websocket upgrades before confirming that the\n * intended destination exists, so this code is sent once we've discovered that\n * the destination does not exist.\n */\nconst CLOSE_NOT_FOUND = 4040;\n\n/**\n * The various states our WebSocket can be in:\n *\n * - \"disconnected\": We don't have a WebSocket, but plan to create one.\n * - \"connecting\": We have created the WebSocket and are waiting for the\n * `onOpen` callback.\n * - \"ready\": We have an open WebSocket.\n * - \"stopped\": The WebSocket was closed and a new one can be created via `.restart()`.\n * - \"terminated\": We have closed the WebSocket and will never create a new one.\n *\n *\n * WebSocket State Machine\n * -----------------------\n * initialState: disconnected\n * validTransitions:\n * disconnected:\n * new WebSocket() -> connecting\n * terminate() -> terminated\n * connecting:\n * onopen -> ready\n * close() -> disconnected\n * terminate() -> terminated\n * ready:\n * close() -> disconnected\n * stop() -> stopped\n * terminate() -> terminated\n * stopped:\n * restart() -> connecting\n * terminate() -> terminated\n * terminalStates:\n * terminated\n *\n *\n *\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u250C\u2500\u2500\u2500\u2500terminate()\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2502 disconnected \u2502\u25C0\u2500\u2510\n * \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n * \u25BC \u2502 \u25B2 \u2502\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 new WebSocket() \u2502 \u2502\n * \u250C\u2500\u25B6\u2502 terminated \u2502\u25C0\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502 \u2502 \u2502\n * \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502 \u2502 \u2502 \u2502\n * \u2502 \u25B2 terminate() \u2502 close() close()\n * \u2502 terminate() \u2502 \u2502 \u2502 \u2502\n * \u2502 \u2502 \u2502 \u25BC \u2502 \u2502\n * \u2502 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\n * \u2502 \u2502 stopped \u2502\u2500\u2500restart()\u2500\u2500\u2500\u25B6\u2502 connecting \u2502 \u2502\n * \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n * \u2502 \u25B2 \u2502 \u2502\n * \u2502 \u2502 onopen \u2502\n * \u2502 \u2502 \u2502 \u2502\n * \u2502 \u2502 \u25BC \u2502\n * terminate() \u2502 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\n * \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500stop()\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2502 ready \u2502\u2500\u2500\u2518\n * \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n * \u2502 \u2502\n * \u2502 \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n *\n * The `connecting` and `ready` state have a sub-state-machine for pausing.\n */\n\ntype Socket =\n | { state: \"disconnected\" }\n | { state: \"connecting\"; ws: WebSocket; paused: \"yes\" | \"no\" }\n | { state: \"ready\"; ws: WebSocket; paused: \"yes\" | \"no\" | \"uninitialized\" }\n | { state: \"stopped\" }\n | { state: \"terminated\" };\n\nexport type ReconnectMetadata = {\n connectionCount: number;\n lastCloseReason: string | null;\n clientTs: number;\n};\n\nexport type OnMessageResponse = {\n hasSyncedPastLastReconnect: boolean;\n};\n\nlet firstTime: number | undefined;\nfunction monotonicMillis() {\n if (firstTime === undefined) {\n firstTime = Date.now();\n }\n if (typeof performance === \"undefined\" || !performance.now) {\n return Date.now();\n }\n return Math.round(firstTime + performance.now());\n}\n\nfunction prettyNow() {\n return `t=${Math.round((monotonicMillis() - firstTime!) / 100) / 10}s`;\n}\n\nconst serverDisconnectErrors = {\n // A known error, e.g. during a restart or push\n InternalServerError: { timeout: 1000 },\n // ErrorMetadata::overloaded() messages that we realy should back off\n SubscriptionsWorkerFullError: { timeout: 3000 },\n TooManyConcurrentRequests: { timeout: 3000 },\n CommitterFullError: { timeout: 3000 },\n AwsTooManyRequestsException: { timeout: 3000 },\n ExecuteFullError: { timeout: 3000 },\n SystemTimeoutError: { timeout: 3000 },\n ExpiredInQueue: { timeout: 3000 },\n // ErrorMetadata::feature_temporarily_unavailable() that typically indicate a deploy just happened\n VectorIndexesUnavailable: { timeout: 1000 },\n SearchIndexesUnavailable: { timeout: 1000 },\n TableSummariesUnavailable: { timeout: 1000 },\n // More ErrorMetadata::overloaded()\n VectorIndexTooLarge: { timeout: 3000 },\n SearchIndexTooLarge: { timeout: 3000 },\n TooManyWritesInTimePeriod: { timeout: 3000 },\n} as const satisfies Record<string, { timeout: number }>;\n\ntype ServerDisconnectError = keyof typeof serverDisconnectErrors | \"Unknown\";\n\nfunction classifyDisconnectError(s?: string): ServerDisconnectError {\n if (s === undefined) return \"Unknown\";\n // startsWith so more info could be at the end (although currently there isn't)\n\n for (const prefix of Object.keys(\n serverDisconnectErrors,\n ) as ServerDisconnectError[]) {\n if (s.startsWith(prefix)) {\n return prefix;\n }\n }\n return \"Unknown\";\n}\n\n/**\n * A wrapper around a websocket that handles errors, reconnection, and message\n * parsing.\n */\nexport class WebSocketManager {\n private socket: Socket;\n\n private connectionCount: number;\n private _hasEverConnected: boolean = false;\n private lastCloseReason:\n | \"InitialConnect\"\n | \"OnCloseInvoked\"\n | (string & {}) // a full serverErrorReason (not just the prefix) or a new one\n | null;\n\n // State for assembling the split-up Transition currently being received.\n private transitionChunkBuffer: {\n chunks: string[];\n totalParts: number;\n transitionId: string;\n } | null = null;\n\n /** Upon HTTPS/WSS failure, the first jittered backoff duration, in ms. */\n private readonly defaultInitialBackoff: number;\n\n /** We backoff exponentially, but we need to cap that--this is the jittered max. */\n private readonly maxBackoff: number;\n\n /** How many times have we failed consecutively? */\n private retries: number;\n\n /** How long before lack of server response causes us to initiate a reconnect,\n * in ms */\n private readonly serverInactivityThreshold: number;\n\n private reconnectDueToServerInactivityTimeout: ReturnType<\n typeof setTimeout\n > | null;\n\n /** Scheduled reconnect state: timeout handle and timing info */\n private scheduledReconnect: {\n timeout: ReturnType<typeof setTimeout>;\n scheduledAt: number;\n backoffMs: number;\n } | null = null;\n\n private networkOnlineHandler: (() => void) | null = null;\n\n /** Pending event to send after reconnecting due to network recovery */\n private pendingNetworkRecoveryInfo: { timeSavedMs: number } | null = null;\n\n private readonly uri: string;\n private readonly onOpen: (reconnectMetadata: ReconnectMetadata) => void;\n private readonly onResume: () => void;\n private readonly onMessage: (message: ServerMessage) => OnMessageResponse;\n private readonly webSocketConstructor: typeof WebSocket;\n private readonly logger: Logger;\n private readonly onServerDisconnectError:\n | ((message: string) => void)\n | undefined;\n\n constructor(\n uri: string,\n callbacks: {\n onOpen: (reconnectMetadata: ReconnectMetadata) => void;\n onResume: () => void;\n onMessage: (message: ServerMessage) => OnMessageResponse;\n onServerDisconnectError?: ((message: string) => void) | undefined;\n },\n webSocketConstructor: typeof WebSocket,\n logger: Logger,\n private readonly markConnectionStateDirty: () => void,\n private readonly debug: boolean,\n ) {\n this.webSocketConstructor = webSocketConstructor;\n this.socket = { state: \"disconnected\" };\n this.connectionCount = 0;\n this.lastCloseReason = \"InitialConnect\";\n\n // backoff for unknown errors\n this.defaultInitialBackoff = 1000;\n this.maxBackoff = 16000;\n this.retries = 0;\n\n // Ping messages (sync protocol Pings, not WebSocket protocol Pings) are\n // sent every 15s in the absence of other messages. But a single large\n // Transition or other downstream message can hog the line so this\n // threshold is set higher to prevent clients from giving up.\n this.serverInactivityThreshold = 60000;\n this.reconnectDueToServerInactivityTimeout = null;\n\n this.uri = uri;\n this.onOpen = callbacks.onOpen;\n this.onResume = callbacks.onResume;\n this.onMessage = callbacks.onMessage;\n this.onServerDisconnectError = callbacks.onServerDisconnectError;\n this.logger = logger;\n\n // Set up network online event listener\n this.setupNetworkListener();\n\n this.connect();\n }\n\n private setSocketState(state: Socket) {\n this.socket = state;\n this._logVerbose(\n `socket state changed: ${this.socket.state}, paused: ${\n \"paused\" in this.socket ? this.socket.paused : undefined\n }`,\n );\n this.markConnectionStateDirty();\n }\n\n private setupNetworkListener() {\n // Only set up listener if we're in a browser environment with addEventListener\n // (React Native has window but not addEventListener)\n if (\n typeof window === \"undefined\" ||\n typeof window.addEventListener !== \"function\"\n ) {\n return;\n }\n // Avoid registering duplicate listeners\n if (this.networkOnlineHandler !== null) {\n return;\n }\n\n this.networkOnlineHandler = () => {\n this._logVerbose(\"network online event detected\");\n this.tryReconnectImmediately();\n };\n\n window.addEventListener(\"online\", this.networkOnlineHandler);\n this._logVerbose(\"network online event listener registered\");\n }\n\n private cleanupNetworkListener() {\n if (\n this.networkOnlineHandler &&\n typeof window !== \"undefined\" &&\n typeof window.removeEventListener === \"function\"\n ) {\n window.removeEventListener(\"online\", this.networkOnlineHandler);\n this.networkOnlineHandler = null;\n this._logVerbose(\"network online event listener removed\");\n }\n }\n\n private assembleTransition(chunk: TransitionChunk): Transition | null {\n if (\n chunk.partNumber < 0 ||\n chunk.partNumber >= chunk.totalParts ||\n chunk.totalParts === 0 ||\n (this.transitionChunkBuffer &&\n (this.transitionChunkBuffer.totalParts !== chunk.totalParts ||\n this.transitionChunkBuffer.transitionId !== chunk.transitionId))\n ) {\n // Throwing an error doesn't crash the client, so clear the buffer.\n this.transitionChunkBuffer = null;\n throw new Error(\"Invalid TransitionChunk\");\n }\n\n if (this.transitionChunkBuffer === null) {\n this.transitionChunkBuffer = {\n chunks: [],\n totalParts: chunk.totalParts,\n transitionId: chunk.transitionId,\n };\n }\n\n if (chunk.partNumber !== this.transitionChunkBuffer.chunks.length) {\n // Throwing an error doesn't crash the client, so clear the buffer.\n const expectedLength = this.transitionChunkBuffer.chunks.length;\n this.transitionChunkBuffer = null;\n throw new Error(\n `TransitionChunk received out of order: expected part ${expectedLength}, got ${chunk.partNumber}`,\n );\n }\n\n this.transitionChunkBuffer.chunks.push(chunk.chunk);\n\n if (this.transitionChunkBuffer.chunks.length === chunk.totalParts) {\n const fullJson = this.transitionChunkBuffer.chunks.join(\"\");\n this.transitionChunkBuffer = null;\n\n const transition = parseServerMessage(JSON.parse(fullJson));\n if (transition.type !== \"Transition\") {\n throw new Error(\n `Expected Transition, got ${transition.type} after assembling chunks`,\n );\n }\n return transition;\n }\n\n return null;\n }\n\n private connect() {\n if (this.socket.state === \"terminated\") {\n return;\n }\n if (\n this.socket.state !== \"disconnected\" &&\n this.socket.state !== \"stopped\"\n ) {\n throw new Error(\n \"Didn't start connection from disconnected state: \" + this.socket.state,\n );\n }\n\n const ws = new this.webSocketConstructor(this.uri);\n this._logVerbose(\"constructed WebSocket\");\n this.setSocketState({\n state: \"connecting\",\n ws,\n paused: \"no\",\n });\n\n // Kick off server inactivity timer before WebSocket connection is established\n // so we can detect cases where handshake fails.\n // The `onopen` event only fires after the connection is established:\n // Source: https://datatracker.ietf.org/doc/html/rfc6455#page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and\n this.resetServerInactivityTimeout();\n\n ws.onopen = () => {\n this.logger.logVerbose(\"begin ws.onopen\");\n if (this.socket.state !== \"connecting\") {\n throw new Error(\"onopen called with socket not in connecting state\");\n }\n this.setSocketState({\n state: \"ready\",\n ws,\n paused: this.socket.paused === \"yes\" ? \"uninitialized\" : \"no\",\n });\n this.resetServerInactivityTimeout();\n if (this.socket.paused === \"no\") {\n this._hasEverConnected = true;\n this.onOpen({\n connectionCount: this.connectionCount,\n lastCloseReason: this.lastCloseReason,\n clientTs: monotonicMillis(),\n });\n }\n\n if (this.lastCloseReason !== \"InitialConnect\") {\n if (this.lastCloseReason) {\n this.logger.log(\n \"WebSocket reconnected at\",\n prettyNow(),\n \"after disconnect due to\",\n this.lastCloseReason,\n );\n } else {\n this.logger.log(\"WebSocket reconnected at\", prettyNow());\n }\n }\n\n this.connectionCount += 1;\n this.lastCloseReason = null;\n\n // Send event for network recovery reconnect if applicable\n if (this.pendingNetworkRecoveryInfo !== null) {\n const { timeSavedMs } = this.pendingNetworkRecoveryInfo;\n this.pendingNetworkRecoveryInfo = null;\n this.sendMessage({\n type: \"Event\",\n eventType: \"NetworkRecoveryReconnect\",\n event: { timeSavedMs },\n });\n this.logger.log(\n `Network recovery reconnect saved ~${Math.round(timeSavedMs / 1000)}s of waiting`,\n );\n }\n };\n // NB: The WebSocket API calls `onclose` even if connection fails, so we can route all error paths through `onclose`.\n ws.onerror = (error) => {\n this.transitionChunkBuffer = null;\n const message = (error as ErrorEvent).message;\n if (message) {\n this.logger.log(`WebSocket error message: ${message}`);\n }\n };\n ws.onmessage = (message) => {\n this.resetServerInactivityTimeout();\n const messageLength = message.data.length;\n let serverMessage = parseServerMessage(JSON.parse(message.data));\n this._logVerbose(`received ws message with type ${serverMessage.type}`);\n\n // Ping's only purpose is to reset the server inactivity timer.\n if (serverMessage.type === \"Ping\") {\n return;\n }\n\n // TransitionChunks never reach the main client logic.\n if (serverMessage.type === \"TransitionChunk\") {\n const transition = this.assembleTransition(serverMessage);\n if (!transition) {\n return;\n }\n serverMessage = transition;\n this._logVerbose(\n `assembled full ws message of type ${serverMessage.type}`,\n );\n }\n\n if (this.transitionChunkBuffer !== null) {\n this.transitionChunkBuffer = null;\n this.logger.log(\n `Received unexpected ${serverMessage.type} while buffering TransitionChunks`,\n );\n }\n\n if (serverMessage.type === \"Transition\") {\n this.reportLargeTransition({\n messageLength,\n transition: serverMessage,\n });\n }\n const response = this.onMessage(serverMessage);\n if (response.hasSyncedPastLastReconnect) {\n // Reset backoff to 0 once all outstanding requests are complete.\n this.retries = 0;\n this.markConnectionStateDirty();\n }\n };\n ws.onclose = (event) => {\n this._logVerbose(\"begin ws.onclose\");\n this.transitionChunkBuffer = null;\n if (this.lastCloseReason === null) {\n // event.reason is often an empty string\n this.lastCloseReason = event.reason || `closed with code ${event.code}`;\n }\n if (\n event.code !== CLOSE_NORMAL &&\n event.code !== CLOSE_GOING_AWAY && // This commonly gets fired on mobile apps when the app is backgrounded\n event.code !== CLOSE_NO_STATUS &&\n event.code !== CLOSE_NOT_FOUND // Note that we want to retry on a 404, as it can be transient during a push.\n ) {\n let msg = `WebSocket closed with code ${event.code}`;\n if (event.reason) {\n msg += `: ${event.reason}`;\n }\n this.logger.log(msg);\n if (this.onServerDisconnectError && event.reason) {\n // This callback is a unstable API, InternalServerErrors in particular may be removed\n // since they reflect expected temporary downtime. But until a quantitative measure\n // of uptime is reported this unstable API errs on the inclusive side.\n this.onServerDisconnectError(msg);\n }\n }\n const reason = classifyDisconnectError(event.reason);\n this.scheduleReconnect(reason);\n return;\n };\n }\n\n /**\n * @returns The state of the {@link Socket}.\n */\n socketState(): string {\n return this.socket.state;\n }\n\n /**\n * @param message - A ClientMessage to send.\n * @returns Whether the message (might have been) sent.\n */\n sendMessage(message: ClientMessage) {\n const messageForLog = {\n type: message.type,\n ...(message.type === \"Authenticate\" && message.tokenType === \"User\"\n ? {\n value: `...${message.value.slice(-7)}`,\n }\n : {}),\n };\n if (this.socket.state === \"ready\" && this.socket.paused === \"no\") {\n const encodedMessage = encodeClientMessage(message);\n const request = JSON.stringify(encodedMessage);\n let sent = false;\n try {\n this.socket.ws.send(request);\n sent = true;\n } catch (error: any) {\n this.logger.log(\n `Failed to send message on WebSocket, reconnecting: ${error}`,\n );\n this.closeAndReconnect(\"FailedToSendMessage\");\n }\n this._logVerbose(\n `${sent ? \"sent\" : \"failed to send\"} message with type ${message.type}: ${JSON.stringify(\n messageForLog,\n )}`,\n );\n return true;\n }\n this._logVerbose(\n `message not sent (socket state: ${this.socket.state}, paused: ${\"paused\" in this.socket ? this.socket.paused : undefined}): ${JSON.stringify(\n messageForLog,\n )}`,\n );\n\n return false;\n }\n\n private resetServerInactivityTimeout() {\n if (this.socket.state === \"terminated\") {\n // Don't reset any timers if we were trying to terminate.\n return;\n }\n if (this.reconnectDueToServerInactivityTimeout !== null) {\n clearTimeout(this.reconnectDueToServerInactivityTimeout);\n this.reconnectDueToServerInactivityTimeout = null;\n }\n this.reconnectDueToServerInactivityTimeout = setTimeout(() => {\n this.closeAndReconnect(\"InactiveServer\");\n }, this.serverInactivityThreshold);\n }\n\n private scheduleReconnect(reason: \"client\" | ServerDisconnectError) {\n // Cancel any existing scheduled reconnect to avoid multiple reconnects\n if (this.scheduledReconnect) {\n clearTimeout(this.scheduledReconnect.timeout);\n this.scheduledReconnect = null;\n }\n\n this.socket = { state: \"disconnected\" };\n const backoff = this.nextBackoff(reason);\n this.markConnectionStateDirty();\n this.logger.log(`Attempting reconnect in ${Math.round(backoff)}ms`);\n\n const scheduledAt = monotonicMillis();\n const timeoutId = setTimeout(() => {\n // Only proceed if this timeout hasn't been cleared\n if (this.scheduledReconnect?.timeout === timeoutId) {\n this.scheduledReconnect = null;\n this.connect();\n }\n }, backoff);\n\n this.scheduledReconnect = {\n timeout: timeoutId,\n scheduledAt,\n backoffMs: backoff,\n };\n }\n\n /**\n * Close the WebSocket and schedule a reconnect.\n *\n * This should be used when we hit an error and would like to restart the session.\n */\n private closeAndReconnect(closeReason: string) {\n this._logVerbose(`begin closeAndReconnect with reason ${closeReason}`);\n switch (this.socket.state) {\n case \"disconnected\":\n case \"terminated\":\n case \"stopped\":\n // Nothing to do if we don't have a WebSocket.\n return;\n case \"connecting\":\n case \"ready\": {\n this.lastCloseReason = closeReason;\n // Close the old socket asynchronously, we'll open a new socket in reconnect.\n void this.close();\n this.scheduleReconnect(\"client\");\n return;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n }\n }\n }\n\n /**\n * Close the WebSocket, being careful to clear the onclose handler to avoid re-entrant\n * calls. Use this instead of directly calling `ws.close()`\n *\n * It is the callers responsibility to update the state after this method is called so that the\n * closed socket is not accessible or used again after this method is called\n */\n private close(): Promise<void> {\n this.transitionChunkBuffer = null;\n switch (this.socket.state) {\n case \"disconnected\":\n case \"terminated\":\n case \"stopped\":\n // Nothing to do if we don't have a WebSocket.\n return Promise.resolve();\n case \"connecting\": {\n const ws = this.socket.ws;\n // Messages can still be received after close but we're not interested.\n ws.onmessage = (_message) => {\n this._logVerbose(\"Ignoring message received after close\");\n };\n return new Promise((r) => {\n ws.onclose = () => {\n this._logVerbose(\"Closed after connecting\");\n r();\n };\n ws.onopen = () => {\n this._logVerbose(\"Opened after connecting\");\n ws.close();\n };\n });\n }\n case \"ready\": {\n this._logVerbose(\"ws.close called\");\n const ws = this.socket.ws;\n // Messages can still be received after close but we're not interested.\n ws.onmessage = (_message) => {\n this._logVerbose(\"Ignoring message received after close\");\n };\n const result: Promise<void> = new Promise((r) => {\n ws.onclose = () => {\n r();\n };\n });\n ws.close();\n return result;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n return Promise.resolve();\n }\n }\n }\n\n /**\n * Close the WebSocket and do not reconnect.\n * @returns A Promise that resolves when the WebSocket `onClose` callback is called.\n */\n terminate(): Promise<void> {\n if (this.reconnectDueToServerInactivityTimeout) {\n clearTimeout(this.reconnectDueToServerInactivityTimeout);\n }\n if (this.scheduledReconnect) {\n clearTimeout(this.scheduledReconnect.timeout);\n this.scheduledReconnect = null;\n }\n this.cleanupNetworkListener();\n switch (this.socket.state) {\n case \"terminated\":\n case \"stopped\":\n case \"disconnected\":\n case \"connecting\":\n case \"ready\": {\n const result = this.close();\n this.setSocketState({ state: \"terminated\" });\n return result;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n throw new Error(\n `Invalid websocket state: ${(this.socket as any).state}`,\n );\n }\n }\n }\n\n stop(): Promise<void> {\n switch (this.socket.state) {\n case \"terminated\":\n // If we're terminating we ignore stop\n return Promise.resolve();\n case \"connecting\":\n case \"stopped\":\n case \"disconnected\":\n case \"ready\": {\n this.cleanupNetworkListener();\n const result = this.close();\n this.socket = { state: \"stopped\" };\n return result;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n return Promise.resolve();\n }\n }\n }\n\n /**\n * Create a new WebSocket after a previous `stop()`, unless `terminate()` was\n * called before.\n */\n tryRestart(): void {\n switch (this.socket.state) {\n case \"stopped\":\n break;\n case \"terminated\":\n case \"connecting\":\n case \"ready\":\n case \"disconnected\":\n this.logger.logVerbose(\"Restart called without stopping first\");\n return;\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n }\n }\n this.setupNetworkListener();\n this.connect();\n }\n\n pause(): void {\n switch (this.socket.state) {\n case \"disconnected\":\n case \"stopped\":\n case \"terminated\":\n // If already stopped or stopping ignore.\n return;\n case \"connecting\":\n case \"ready\": {\n this.socket = { ...this.socket, paused: \"yes\" };\n return;\n }\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n return;\n }\n }\n }\n\n /**\n * Try to reconnect immediately, canceling any scheduled reconnect.\n * This is useful when detecting network recovery.\n * Only takes action if we're in disconnected state (waiting to reconnect).\n */\n tryReconnectImmediately(): void {\n this._logVerbose(\"tryReconnectImmediately called\");\n\n // Only reconnect if we're in disconnected state (waiting to reconnect)\n if (this.socket.state !== \"disconnected\") {\n this._logVerbose(\n `tryReconnectImmediately called but socket state is ${this.socket.state}, no action taken`,\n );\n return;\n }\n\n // Track how much time we saved by reconnecting immediately\n let timeSavedMs: number | null = null;\n if (this.scheduledReconnect) {\n const elapsed = monotonicMillis() - this.scheduledReconnect.scheduledAt;\n timeSavedMs = Math.max(0, this.scheduledReconnect.backoffMs - elapsed);\n this._logVerbose(\n `would have waited ${Math.round(timeSavedMs)}ms more (backoff was ${Math.round(this.scheduledReconnect.backoffMs)}ms, elapsed ${Math.round(elapsed)}ms)`,\n );\n // Cancel the scheduled reconnect\n clearTimeout(this.scheduledReconnect.timeout);\n this.scheduledReconnect = null;\n this._logVerbose(\"canceled scheduled reconnect\");\n }\n\n this.logger.log(\"Network recovery detected, reconnecting immediately\");\n // Store the time saved to send as an event after we connect\n this.pendingNetworkRecoveryInfo =\n timeSavedMs !== null ? { timeSavedMs } : null;\n this.connect();\n }\n\n /**\n * Resume the state machine if previously paused.\n */\n resume(): void {\n switch (this.socket.state) {\n case \"connecting\":\n this.socket = { ...this.socket, paused: \"no\" };\n return;\n case \"ready\":\n if (this.socket.paused === \"uninitialized\") {\n this.socket = { ...this.socket, paused: \"no\" };\n this._hasEverConnected = true;\n this.onOpen({\n connectionCount: this.connectionCount,\n lastCloseReason: this.lastCloseReason,\n clientTs: monotonicMillis(),\n });\n } else if (this.socket.paused === \"yes\") {\n this.socket = { ...this.socket, paused: \"no\" };\n this.onResume();\n }\n return;\n case \"terminated\":\n case \"stopped\":\n case \"disconnected\":\n // Ignore resume if not paused, perhaps we already resumed.\n return;\n default: {\n // Enforce that the switch-case is exhaustive.\n this.socket satisfies never;\n }\n }\n this.connect();\n }\n\n connectionState(): {\n isConnected: boolean;\n hasEverConnected: boolean;\n connectionCount: number;\n connectionRetries: number;\n } {\n return {\n isConnected: this.socket.state === \"ready\",\n hasEverConnected: this._hasEverConnected,\n connectionCount: this.connectionCount,\n connectionRetries: this.retries,\n };\n }\n\n private _logVerbose(message: string) {\n this.logger.logVerbose(message);\n }\n\n private nextBackoff(reason: \"client\" | ServerDisconnectError): number {\n const initialBackoff: number =\n reason === \"client\"\n ? 100 // There's no evidence of a server problem, retry quickly\n : reason === \"Unknown\"\n ? this.defaultInitialBackoff\n : serverDisconnectErrors[reason].timeout;\n\n const baseBackoff = initialBackoff * Math.pow(2, this.retries);\n this.retries += 1;\n const actualBackoff = Math.min(baseBackoff, this.maxBackoff);\n const jitter = actualBackoff * (Math.random() - 0.5);\n return actualBackoff + jitter;\n }\n\n private reportLargeTransition({\n transition,\n messageLength,\n }: {\n transition: Transition;\n messageLength: number;\n }) {\n if (\n transition.clientClockSkew === undefined ||\n transition.serverTs === undefined\n ) {\n return;\n }\n\n const transitionTransitTime =\n monotonicMillis() - // client time now\n // clientClockSkew = (server time + upstream latency) - client time\n // clientClockSkew is \"how many milliseconds behind (slow) is the client clock\"\n // but the latency of the Connect message inflates this, making it appear further behind\n transition.clientClockSkew -\n transition.serverTs / 1_000_000; // server time when transition was sent\n const prettyTransitionTime = `${Math.round(transitionTransitTime)}ms`;\n const prettyMessageMB = `${Math.round(messageLength / 10_000) / 100}MB`;\n const bytesPerSecond = messageLength / (transitionTransitTime / 1000);\n const prettyBytesPerSecond = `${Math.round(bytesPerSecond / 10_000) / 100}MB per second`;\n this._logVerbose(\n `received ${prettyMessageMB} transition in ${prettyTransitionTime} at ${prettyBytesPerSecond}`,\n );\n\n // Warnings that will show up for *all users*, so don't be too aggressive.\n // These can be silenced (along with reconnection messages) by setting `logger: false` in client options.\n if (messageLength > 20_000_000) {\n // Big enough that the developer should be made aware of this.\n this.logger.log(\n `received query results totaling more that 20MB (${prettyMessageMB}) which will take a long time to download on slower connections`,\n );\n } else if (transitionTransitTime > 20_000) {\n // Long enough that a pattern of these should be interesting to a developer, but be aware that\n // weak connections, putting clients to sleep, backgrounding etc. could all cause this too.\n this.logger.log(\n `received query results totaling ${prettyMessageMB} which took more than 20s to arrive (${prettyTransitionTime})`,\n );\n }\n\n if (this.debug) {\n // debug means \"reportDebugInfoToConvex\" is set so this can be aggressive.\n this.sendMessage({\n type: \"Event\",\n eventType: \"ClientReceivedTransition\",\n event: { transitionTransitTime, messageLength },\n });\n }\n }\n}\n", "export function newSessionId() {\n return uuidv4();\n}\n\n// From https://stackoverflow.com/a/2117523\nfunction uuidv4() {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0,\n v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n", "export interface JwtDecodeOptions {\n header?: boolean;\n}\n\nexport interface JwtHeader {\n typ?: string;\n alg?: string;\n kid?: string;\n}\n\nexport interface JwtPayload {\n iss?: string;\n sub?: string;\n aud?: string[] | string;\n exp?: number;\n nbf?: number;\n iat?: number;\n jti?: string;\n}\n\nexport class InvalidTokenError extends Error {}\n\nInvalidTokenError.prototype.name = \"InvalidTokenError\";\n\nfunction b64DecodeUnicode(str: string) {\n return decodeURIComponent(\n atob(str).replace(/(.)/g, (_m, p) => {\n let code = (p as string).charCodeAt(0).toString(16).toUpperCase();\n if (code.length < 2) {\n code = \"0\" + code;\n }\n return \"%\" + code;\n }),\n );\n}\n\nfunction base64UrlDecode(str: string) {\n let output = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n switch (output.length % 4) {\n case 0:\n break;\n case 2:\n output += \"==\";\n break;\n case 3:\n output += \"=\";\n break;\n default:\n throw new Error(\"base64 string is not of the correct length\");\n }\n\n try {\n return b64DecodeUnicode(output);\n } catch {\n return atob(output);\n }\n}\n\nexport function jwtDecode<T = JwtHeader>(\n token: string,\n options: JwtDecodeOptions & { header: true },\n): T;\nexport function jwtDecode<T = JwtPayload>(\n token: string,\n options?: JwtDecodeOptions,\n): T;\nexport function jwtDecode<T = JwtHeader | JwtPayload>(\n token: string,\n options?: JwtDecodeOptions,\n): T {\n if (typeof token !== \"string\") {\n throw new InvalidTokenError(\"Invalid token specified: must be a string\");\n }\n\n options ||= {};\n\n const pos = options.header === true ? 0 : 1;\n const part = token.split(\".\")[pos];\n\n if (typeof part !== \"string\") {\n throw new InvalidTokenError(\n `Invalid token specified: missing part #${pos + 1}`,\n );\n }\n\n let decoded: string;\n try {\n decoded = base64UrlDecode(part);\n } catch (e) {\n throw new InvalidTokenError(\n `Invalid token specified: invalid base64 for part #${pos + 1} (${(e as Error).message})`,\n );\n }\n\n try {\n return JSON.parse(decoded) as T;\n } catch (e) {\n throw new InvalidTokenError(\n `Invalid token specified: invalid json for part #${pos + 1} (${(e as Error).message})`,\n );\n }\n}\n", "import { Logger } from \"../logging.js\";\nimport { LocalSyncState } from \"./local_state.js\";\nimport { AuthError, IdentityVersion, Transition } from \"./protocol.js\";\nimport { jwtDecode } from \"../../vendor/jwt-decode/index.js\";\n\n// setTimout uses 32 bit integer, so it can only\n// schedule about 24 days in the future.\nconst MAXIMUM_REFRESH_DELAY = 20 * 24 * 60 * 60 * 1000; // 20 days\n\nconst MAX_TOKEN_CONFIRMATION_ATTEMPTS = 2;\n\n/**\n * An async function returning a JWT. Depending on the auth providers\n * configured in convex/auth.config.ts, this may be a JWT-encoded OpenID\n * Connect Identity Token or a traditional JWT.\n *\n * `forceRefreshToken` is `true` if the server rejected a previously\n * returned token or the token is anticipated to expiring soon\n * based on its `exp` time.\n *\n * See {@link ConvexReactClient.setAuth}.\n *\n * @public\n */\nexport type AuthTokenFetcher = (args: {\n forceRefreshToken: boolean;\n}) => Promise<string | null | undefined>;\n\n/**\n * What is provided to the client.\n */\ntype AuthConfig = {\n fetchToken: AuthTokenFetcher;\n onAuthChange: (isAuthenticated: boolean) => void;\n};\n\n/**\n * In general we take 3 steps:\n * 1. Fetch a possibly cached token\n * 2. Immediately fetch a fresh token without using a cache\n * 3. Repeat step 2 before the end of the fresh token's lifetime\n *\n * When we fetch without using a cache we know when the token\n * will expire, and can schedule refetching it.\n *\n * If we get an error before a scheduled refetch, we go back\n * to step 2.\n */\ntype AuthState =\n | { state: \"noAuth\" }\n | {\n state: \"waitingForServerConfirmationOfCachedToken\";\n config: AuthConfig;\n hasRetried: boolean;\n }\n | {\n state: \"initialRefetch\";\n config: AuthConfig;\n }\n | {\n state: \"waitingForServerConfirmationOfFreshToken\";\n config: AuthConfig;\n hadAuth: boolean;\n token: string;\n }\n | {\n state: \"waitingForScheduledRefetch\";\n config: AuthConfig;\n refetchTokenTimeoutId: ReturnType<typeof setTimeout>;\n }\n // Special/weird state when we got a valid token\n // but could not fetch a new one.\n | {\n state: \"notRefetching\";\n config: AuthConfig;\n };\n\n/**\n * Handles the state transitions for auth. The server is the source\n * of truth.\n */\nexport class AuthenticationManager {\n private authState: AuthState = { state: \"noAuth\" };\n // Used to detect races involving `setConfig` calls\n // while a token is being fetched.\n private configVersion = 0;\n // Shared by the BaseClient so that the auth manager can easily inspect it\n private readonly syncState: LocalSyncState;\n // Passed down by BaseClient, sends a message to the server\n private readonly authenticate: (token: string) => IdentityVersion;\n private readonly stopSocket: () => Promise<void>;\n private readonly tryRestartSocket: () => void;\n private readonly pauseSocket: () => void;\n private readonly resumeSocket: () => void;\n // Passed down by BaseClient, sends a message to the server\n private readonly clearAuth: () => void;\n private readonly logger: Logger;\n private readonly refreshTokenLeewaySeconds: number;\n // Number of times we have attempted to confirm the latest token. We retry up\n // to `MAX_TOKEN_CONFIRMATION_ATTEMPTS` times.\n private tokenConfirmationAttempts = 0;\n constructor(\n syncState: LocalSyncState,\n callbacks: {\n authenticate: (token: string) => IdentityVersion;\n stopSocket: () => Promise<void>;\n tryRestartSocket: () => void;\n pauseSocket: () => void;\n resumeSocket: () => void;\n clearAuth: () => void;\n },\n config: {\n refreshTokenLeewaySeconds: number;\n logger: Logger;\n },\n ) {\n this.syncState = syncState;\n this.authenticate = callbacks.authenticate;\n this.stopSocket = callbacks.stopSocket;\n this.tryRestartSocket = callbacks.tryRestartSocket;\n this.pauseSocket = callbacks.pauseSocket;\n this.resumeSocket = callbacks.resumeSocket;\n this.clearAuth = callbacks.clearAuth;\n this.logger = config.logger;\n this.refreshTokenLeewaySeconds = config.refreshTokenLeewaySeconds;\n }\n\n async setConfig(\n fetchToken: AuthTokenFetcher,\n onChange: (isAuthenticated: boolean) => void,\n ) {\n this.resetAuthState();\n this._logVerbose(\"pausing WS for auth token fetch\");\n this.pauseSocket();\n const token = await this.fetchTokenAndGuardAgainstRace(fetchToken, {\n forceRefreshToken: false,\n });\n if (token.isFromOutdatedConfig) {\n return;\n }\n if (token.value) {\n this.setAuthState({\n state: \"waitingForServerConfirmationOfCachedToken\",\n config: { fetchToken, onAuthChange: onChange },\n hasRetried: false,\n });\n this.authenticate(token.value);\n } else {\n this.setAuthState({\n state: \"initialRefetch\",\n config: { fetchToken, onAuthChange: onChange },\n });\n // Try again with `forceRefreshToken: true`\n await this.refetchToken();\n }\n this._logVerbose(\"resuming WS after auth token fetch\");\n this.resumeSocket();\n }\n\n onTransition(serverMessage: Transition) {\n if (\n !this.syncState.isCurrentOrNewerAuthVersion(\n serverMessage.endVersion.identity,\n )\n ) {\n // This is a stale transition - client has moved on to\n // a newer auth version.\n return;\n }\n if (\n serverMessage.endVersion.identity <= serverMessage.startVersion.identity\n ) {\n // This transition did not change auth - it is not a response to Authenticate.\n return;\n }\n\n this._logVerbose(\n `auth state is ${this.authState.state} when handling transition`,\n );\n\n // This transition advanced the auth version, which means the token used was valid\n // and the client and server auth states are in sync.\n this.syncState.markAuthCompletion();\n\n if (this.authState.state === \"waitingForServerConfirmationOfCachedToken\") {\n this._logVerbose(\"server confirmed auth token is valid\");\n void this.refetchToken();\n this.authState.config.onAuthChange(true);\n return;\n }\n if (this.authState.state === \"waitingForServerConfirmationOfFreshToken\") {\n this._logVerbose(\"server confirmed new auth token is valid\");\n this.scheduleTokenRefetch(this.authState.token);\n this.tokenConfirmationAttempts = 0;\n if (!this.authState.hadAuth) {\n this.authState.config.onAuthChange(true);\n }\n }\n }\n\n onAuthError(serverMessage: AuthError) {\n // If the AuthError is not due to updating the token, and we're currently\n // waiting on the result of a token update, ignore.\n if (\n serverMessage.authUpdateAttempted === false &&\n (this.authState.state === \"waitingForServerConfirmationOfFreshToken\" ||\n this.authState.state === \"waitingForServerConfirmationOfCachedToken\")\n ) {\n this._logVerbose(\"ignoring non-auth token expired error\");\n return;\n }\n const { baseVersion } = serverMessage;\n // Versioned AuthErrors are ignored if the client advanced to\n // a newer auth identity\n // Error are reporting the previous version, since the server\n // didn't advance, hence `+ 1`.\n if (!this.syncState.isCurrentOrNewerAuthVersion(baseVersion + 1)) {\n this._logVerbose(\"ignoring auth error for previous auth attempt\");\n return;\n }\n void this.tryToReauthenticate(serverMessage);\n return;\n }\n\n // This is similar to `refetchToken` defined below, in fact we\n // don't represent them as different states, but it is different\n // in that we pause the WebSocket so that mutations\n // don't retry with bad auth.\n private async tryToReauthenticate(serverMessage: AuthError) {\n this._logVerbose(`attempting to reauthenticate: ${serverMessage.error}`);\n if (\n // No way to fetch another token, kaboom\n this.authState.state === \"noAuth\" ||\n // We failed on a fresh token. After a small number of retries, we give up\n // and clear the auth state to avoid infinite retries.\n (this.authState.state === \"waitingForServerConfirmationOfFreshToken\" &&\n this.tokenConfirmationAttempts >= MAX_TOKEN_CONFIRMATION_ATTEMPTS)\n ) {\n this.logger.error(\n `Failed to authenticate: \"${serverMessage.error}\", check your server auth config`,\n );\n if (this.syncState.hasAuth()) {\n this.syncState.clearAuth();\n }\n if (this.authState.state !== \"noAuth\") {\n this.setAndReportAuthFailed(this.authState.config.onAuthChange);\n }\n return;\n }\n if (this.authState.state === \"waitingForServerConfirmationOfFreshToken\") {\n this.tokenConfirmationAttempts++;\n this._logVerbose(\n `retrying reauthentication, ${MAX_TOKEN_CONFIRMATION_ATTEMPTS - this.tokenConfirmationAttempts} attempts remaining`,\n );\n }\n\n await this.stopSocket();\n const token = await this.fetchTokenAndGuardAgainstRace(\n this.authState.config.fetchToken,\n {\n forceRefreshToken: true,\n },\n );\n if (token.isFromOutdatedConfig) {\n return;\n }\n\n if (token.value && this.syncState.isNewAuth(token.value)) {\n this.authenticate(token.value);\n this.setAuthState({\n state: \"waitingForServerConfirmationOfFreshToken\",\n config: this.authState.config,\n token: token.value,\n hadAuth:\n this.authState.state === \"notRefetching\" ||\n this.authState.state === \"waitingForScheduledRefetch\",\n });\n } else {\n this._logVerbose(\"reauthentication failed, could not fetch a new token\");\n if (this.syncState.hasAuth()) {\n this.syncState.clearAuth();\n }\n this.setAndReportAuthFailed(this.authState.config.onAuthChange);\n }\n this.tryRestartSocket();\n }\n\n // Force refetch the token and schedule another refetch\n // before the token expires - an active client should never\n // need to reauthenticate.\n private async refetchToken() {\n if (this.authState.state === \"noAuth\") {\n return;\n }\n this._logVerbose(\"refetching auth token\");\n const token = await this.fetchTokenAndGuardAgainstRace(\n this.authState.config.fetchToken,\n {\n forceRefreshToken: true,\n },\n );\n if (token.isFromOutdatedConfig) {\n return;\n }\n\n if (token.value) {\n if (this.syncState.isNewAuth(token.value)) {\n this.setAuthState({\n state: \"waitingForServerConfirmationOfFreshToken\",\n hadAuth: this.syncState.hasAuth(),\n token: token.value,\n config: this.authState.config,\n });\n this.authenticate(token.value);\n } else {\n this.setAuthState({\n state: \"notRefetching\",\n config: this.authState.config,\n });\n }\n } else {\n this._logVerbose(\"refetching token failed\");\n if (this.syncState.hasAuth()) {\n this.clearAuth();\n }\n this.setAndReportAuthFailed(this.authState.config.onAuthChange);\n }\n // Restart in case this refetch was triggered via schedule during\n // a reauthentication attempt.\n this._logVerbose(\n \"restarting WS after auth token fetch (if currently stopped)\",\n );\n this.tryRestartSocket();\n }\n\n private scheduleTokenRefetch(token: string) {\n if (this.authState.state === \"noAuth\") {\n return;\n }\n const decodedToken = this.decodeToken(token);\n if (!decodedToken) {\n // This is no longer really possible, because\n // we wait on server response before scheduling token refetch,\n // and the server currently requires JWT tokens.\n this.logger.error(\n \"Auth token is not a valid JWT, cannot refetch the token\",\n );\n return;\n }\n // iat: issued at time, UTC seconds timestamp at which the JWT was issued\n // exp: expiration time, UTC seconds timestamp at which the JWT will expire\n const { iat, exp } = decodedToken as { iat?: number; exp?: number };\n if (!iat || !exp) {\n this.logger.error(\n \"Auth token does not have required fields, cannot refetch the token\",\n );\n return;\n }\n // Because the client and server clocks may be out of sync,\n // we only know that the token will expire after `exp - iat`,\n // and since we just fetched a fresh one we know when that\n // will happen.\n const tokenValiditySeconds = exp - iat;\n if (tokenValiditySeconds <= 2) {\n this.logger.error(\n \"Auth token does not live long enough, cannot refetch the token\",\n );\n return;\n }\n // Attempt to refresh the token `refreshTokenLeewaySeconds` before it expires,\n // or immediately if the token is already expiring soon.\n let delay = Math.min(\n MAXIMUM_REFRESH_DELAY,\n (tokenValiditySeconds - this.refreshTokenLeewaySeconds) * 1000,\n );\n if (delay <= 0) {\n // Refetch immediately, but this might be due to configuring a `refreshTokenLeewaySeconds`\n // that is too large compared to the token's actual lifetime.\n this.logger.warn(\n `Refetching auth token immediately, configured leeway ${this.refreshTokenLeewaySeconds}s is larger than the token's lifetime ${tokenValiditySeconds}s`,\n );\n delay = 0;\n }\n const refetchTokenTimeoutId = setTimeout(() => {\n this._logVerbose(\"running scheduled token refetch\");\n void this.refetchToken();\n }, delay);\n this.setAuthState({\n state: \"waitingForScheduledRefetch\",\n refetchTokenTimeoutId,\n config: this.authState.config,\n });\n this._logVerbose(\n `scheduled preemptive auth token refetching in ${delay}ms`,\n );\n }\n\n // Protects against simultaneous calls to `setConfig`\n // while we're fetching a token\n private async fetchTokenAndGuardAgainstRace(\n fetchToken: AuthTokenFetcher,\n fetchArgs: {\n forceRefreshToken: boolean;\n },\n ) {\n const originalConfigVersion = ++this.configVersion;\n this._logVerbose(\n `fetching token with config version ${originalConfigVersion}`,\n );\n const token = await fetchToken(fetchArgs);\n if (this.configVersion !== originalConfigVersion) {\n // This is a stale config\n this._logVerbose(\n `stale config version, expected ${originalConfigVersion}, got ${this.configVersion}`,\n );\n return { isFromOutdatedConfig: true };\n }\n return { isFromOutdatedConfig: false, value: token };\n }\n\n stop() {\n this.resetAuthState();\n // Bump this in case we are mid-token-fetch when we get stopped\n this.configVersion++;\n this._logVerbose(`config version bumped to ${this.configVersion}`);\n }\n\n private setAndReportAuthFailed(\n onAuthChange: (authenticated: boolean) => void,\n ) {\n onAuthChange(false);\n this.resetAuthState();\n }\n\n private resetAuthState() {\n this.setAuthState({ state: \"noAuth\" });\n }\n\n private setAuthState(newAuth: AuthState) {\n const authStateForLog =\n newAuth.state === \"waitingForServerConfirmationOfFreshToken\"\n ? {\n hadAuth: newAuth.hadAuth,\n state: newAuth.state,\n token: `...${newAuth.token.slice(-7)}`,\n }\n : { state: newAuth.state };\n this._logVerbose(\n `setting auth state to ${JSON.stringify(authStateForLog)}`,\n );\n switch (newAuth.state) {\n case \"waitingForScheduledRefetch\":\n case \"notRefetching\":\n case \"noAuth\":\n this.tokenConfirmationAttempts = 0;\n break;\n case \"waitingForServerConfirmationOfFreshToken\":\n case \"waitingForServerConfirmationOfCachedToken\":\n case \"initialRefetch\":\n break;\n default: {\n newAuth satisfies never;\n }\n }\n if (this.authState.state === \"waitingForScheduledRefetch\") {\n // TODO: this side-effect would be better situated with scheduling refetch\n clearTimeout(this.authState.refetchTokenTimeoutId);\n }\n this.authState = newAuth;\n }\n\n private decodeToken(token: string) {\n try {\n return jwtDecode(token);\n } catch (e) {\n this._logVerbose(\n `Error decoding token: ${e instanceof Error ? e.message : \"Unknown error\"}`,\n );\n return null;\n }\n }\n\n private _logVerbose(message: string) {\n this.logger.logVerbose(`${message} [v${this.configVersion}]`);\n }\n}\n", "// Marks share a global namespace with other developer code.\nconst markNames = [\n \"convexClientConstructed\",\n \"convexWebSocketOpen\",\n \"convexFirstMessageReceived\",\n] as const;\nexport type MarkName = (typeof markNames)[number];\n\n// Mark details are not reported to the server.\ntype MarkDetail = {\n sessionId: string;\n};\n\n// `PerformanceMark`s are efficient and show up in browser's performance\n// timeline. They can be cleared with `performance.clearMarks()`.\n// This is a memory leak, but a worthwhile one: automatic\n// cleanup would make in-browser debugging more difficult.\nexport function mark(name: MarkName, sessionId: string) {\n const detail: MarkDetail = { sessionId };\n // `performance` APIs exists in browsers, Node.js, Deno, and more but it\n // is not required by the Convex client.\n if (typeof performance === \"undefined\" || !performance.mark) return;\n performance.mark(name, { detail });\n}\n\n// `PerfomanceMark` has a built-in toJSON() but the return type varies\n// between implementations, e.g. Node.js returns details but Chrome does not.\nfunction performanceMarkToJson(mark: PerformanceMark): MarkJson {\n // Remove \"convex\" prefix\n let name = mark.name.slice(\"convex\".length);\n // lowercase the first letter\n name = name.charAt(0).toLowerCase() + name.slice(1);\n return {\n name,\n startTime: mark.startTime,\n };\n}\n\n// Similar to the return type of `PerformanceMark.toJson()`.\nexport type MarkJson = {\n name: string;\n // `startTime` is in milliseconds since the time origin like `performance.now()`.\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#the_time_origin\n startTime: number;\n};\n\nexport function getMarksReport(sessionId: string): MarkJson[] {\n if (typeof performance === \"undefined\" || !performance.getEntriesByName) {\n return [];\n }\n const allMarks: PerformanceMark[] = [];\n for (const name of markNames) {\n const marks = (\n performance\n .getEntriesByName(name)\n .filter((entry) => entry.entryType === \"mark\") as PerformanceMark[]\n ).filter((mark) => mark.detail.sessionId === sessionId);\n allMarks.push(...marks);\n }\n return allMarks.map(performanceMarkToJson);\n}\n", "/**\n * BaseConvexClient should not be used directly and does not provide a stable\n * interface. It is a \"Base\" client not because it expects to be inherited from\n * but because other clients are built around it.\n *\n * BaseConvexClient is not Convex Function type-aware: it deals\n * with queries as functions that return Value, not the specific value.\n * Use a higher-level library to get types.\n */\nimport { version } from \"../../index.js\";\nimport { convexToJson, Value } from \"../../values/index.js\";\nimport {\n createHybridErrorStacktrace,\n forwardData,\n instantiateDefaultLogger,\n instantiateNoopLogger,\n logFatalError,\n Logger,\n} from \"../logging.js\";\nimport { LocalSyncState } from \"./local_state.js\";\nimport { RequestManager } from \"./request_manager.js\";\nimport {\n OptimisticLocalStore,\n OptimisticUpdate,\n} from \"./optimistic_updates.js\";\nimport {\n OptimisticQueryResults,\n QueryResultsMap,\n} from \"./optimistic_updates_impl.js\";\nimport {\n ActionRequest,\n MutationRequest,\n QueryId,\n QueryJournal,\n ServerMessage,\n RequestId,\n TS,\n UserIdentityAttributes,\n} from \"./protocol.js\";\nimport { RemoteQuerySet } from \"./remote_query_set.js\";\nimport { QueryToken, serializePathAndArgs } from \"./udf_path_utils.js\";\nimport { ReconnectMetadata, WebSocketManager } from \"./web_socket_manager.js\";\nimport { newSessionId } from \"./session.js\";\nimport { FunctionResult } from \"./function_result.js\";\nimport {\n AuthenticationManager,\n AuthTokenFetcher,\n} from \"./authentication_manager.js\";\nexport { type AuthTokenFetcher } from \"./authentication_manager.js\";\nimport { getMarksReport, mark, MarkName } from \"./metrics.js\";\nimport { parseArgs, validateDeploymentUrl } from \"../../common/index.js\";\nimport { ConvexError } from \"../../values/errors.js\";\nimport { jwtDecode } from \"../../vendor/jwt-decode/index.js\";\n\n/**\n * Options for {@link BaseConvexClient}.\n *\n * @public\n */\nexport interface BaseConvexClientOptions {\n /**\n * Whether to prompt the user if they have unsaved changes pending\n * when navigating away or closing a web page.\n *\n * This is only possible when the `window` object exists, i.e. in a browser.\n *\n * The default value is `true` in browsers.\n */\n unsavedChangesWarning?: boolean;\n /**\n * Specifies an alternate\n * [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)\n * constructor to use for client communication with the Convex cloud.\n * The default behavior is to use `WebSocket` from the global environment.\n */\n webSocketConstructor?: typeof WebSocket;\n /**\n * Adds additional logging for debugging purposes.\n *\n * The default value is `false`.\n */\n verbose?: boolean;\n /**\n * A logger, `true`, or `false`. If not provided or `true`, logs to the console.\n * If `false`, logs are not printed anywhere.\n *\n * You can construct your own logger to customize logging to log elsewhere.\n * A logger is an object with 4 methods: log(), warn(), error(), and logVerbose().\n * These methods can receive multiple arguments of any types, like console.log().\n */\n logger?: Logger | boolean;\n /**\n * Sends additional metrics to Convex for debugging purposes.\n *\n * The default value is `false`.\n */\n reportDebugInfoToConvex?: boolean;\n /**\n * This API is experimental: it may change or disappear.\n *\n * A function to call on receiving abnormal WebSocket close messages from the\n * connected Convex deployment. The content of these messages is not stable,\n * it is an implementation detail that may change.\n *\n * Consider this API an observability stopgap until higher level codes with\n * recommendations on what to do are available, which could be a more stable\n * interface instead of `string`.\n *\n * Check `connectionState` for more quantitative metrics about connection status.\n */\n onServerDisconnectError?: (message: string) => void;\n /**\n * Skip validating that the Convex deployment URL looks like\n * `https://happy-animal-123.convex.cloud` or localhost.\n *\n * This can be useful if running a self-hosted Convex backend that uses a different\n * URL.\n *\n * The default value is `false`\n */\n skipConvexDeploymentUrlCheck?: boolean;\n /**\n * If using auth, the number of seconds before a token expires that we should refresh it.\n *\n * The default value is `10`.\n */\n authRefreshTokenLeewaySeconds?: number;\n /**\n * This API is experimental: it may change or disappear.\n *\n * Whether query, mutation, and action requests should be held back\n * until the first auth token can be sent.\n *\n * Opting into this behavior works well for pages that should\n * only be viewed by authenticated clients.\n *\n * Defaults to false, not waiting for an auth token.\n */\n expectAuth?: boolean;\n}\n\n/**\n * State describing the client's connection with the Convex backend.\n *\n * @public\n */\nexport type ConnectionState = {\n hasInflightRequests: boolean;\n isWebSocketConnected: boolean;\n timeOfOldestInflightRequest: Date | null;\n /**\n * True if the client has ever opened a WebSocket to the \"ready\" state.\n */\n hasEverConnected: boolean;\n /**\n * The number of times this client has connected to the Convex backend.\n *\n * A number of things can cause the client to reconnect -- server errors,\n * bad internet, auth expiring. But this number being high is an indication\n * that the client is having trouble keeping a stable connection.\n */\n connectionCount: number;\n /**\n * The number of times this client has tried (and failed) to connect to the Convex backend.\n */\n connectionRetries: number;\n /**\n * The number of mutations currently in flight.\n */\n inflightMutations: number;\n /**\n * The number of actions currently in flight.\n */\n inflightActions: number;\n};\n\n/**\n * Options for {@link BaseConvexClient.subscribe}.\n *\n * @public\n */\nexport interface SubscribeOptions {\n /**\n * An (optional) journal produced from a previous execution of this query\n * function.\n *\n * If there is an existing subscription to a query function with the same\n * name and arguments, this journal will have no effect.\n */\n journal?: QueryJournal;\n\n /**\n * @internal\n */\n componentPath?: string | undefined;\n}\n\n/**\n * Options for {@link BaseConvexClient.mutation}.\n *\n * @public\n */\nexport interface MutationOptions {\n /**\n * An optimistic update to apply along with this mutation.\n *\n * An optimistic update locally updates queries while a mutation is pending.\n * Once the mutation completes, the update will be rolled back.\n */\n optimisticUpdate?: OptimisticUpdate<any> | undefined;\n}\n\n/**\n * Type describing updates to a query within a `Transition`.\n *\n * @public\n */\nexport type QueryModification =\n // `undefined` generally comes from an optimistic update setting the query to be loading\n { kind: \"Updated\"; result: FunctionResult | undefined } | { kind: \"Removed\" };\n\n/**\n * Object describing a transition passed into the `onTransition` handler.\n *\n * These can be from receiving a transition from the server, or from applying an\n * optimistic update locally.\n *\n * @public\n */\nexport type Transition = {\n queries: Array<{ token: QueryToken; modification: QueryModification }>;\n reflectedMutations: Array<{ requestId: RequestId; result: FunctionResult }>;\n timestamp: TS;\n};\n\n/**\n * Low-level client for directly integrating state management libraries\n * with Convex.\n *\n * Most developers should use higher level clients, like\n * the {@link ConvexHttpClient} or the React hook based {@link react.ConvexReactClient}.\n *\n * @public\n */\nexport class BaseConvexClient {\n private readonly address: string;\n private readonly state: LocalSyncState;\n private readonly requestManager: RequestManager;\n private readonly webSocketManager: WebSocketManager;\n private readonly authenticationManager: AuthenticationManager;\n private remoteQuerySet: RemoteQuerySet;\n private readonly optimisticQueryResults: OptimisticQueryResults;\n private _transitionHandlerCounter = 0;\n private _nextRequestId: RequestId;\n private _onTransitionFns: Map<number, (transition: Transition) => void> =\n new Map();\n private readonly _sessionId: string;\n private firstMessageReceived = false;\n private readonly debug: boolean;\n private readonly logger: Logger;\n private maxObservedTimestamp: TS | undefined;\n private connectionStateSubscribers = new Map<\n number,\n (connectionState: ConnectionState) => void\n >();\n private nextConnectionStateSubscriberId: number = 0;\n private _lastPublishedConnectionState: ConnectionState | undefined;\n\n /**\n * @param address - The url of your Convex deployment, often provided\n * by an environment variable. E.g. `https://small-mouse-123.convex.cloud`.\n * @param onTransition - A callback receiving an array of query tokens\n * corresponding to query results that have changed -- additional handlers\n * can be added via `addOnTransitionHandler`.\n * @param options - See {@link BaseConvexClientOptions} for a full description.\n */\n constructor(\n address: string,\n onTransition: (updatedQueries: QueryToken[]) => void,\n options?: BaseConvexClientOptions,\n ) {\n if (typeof address === \"object\") {\n throw new Error(\n \"Passing a ClientConfig object is no longer supported. Pass the URL of the Convex deployment as a string directly.\",\n );\n }\n if (options?.skipConvexDeploymentUrlCheck !== true) {\n validateDeploymentUrl(address);\n }\n options = { ...options };\n const authRefreshTokenLeewaySeconds =\n options.authRefreshTokenLeewaySeconds ?? 10;\n let webSocketConstructor = options.webSocketConstructor;\n if (!webSocketConstructor && typeof WebSocket === \"undefined\") {\n throw new Error(\n \"No WebSocket global variable defined! To use Convex in an environment without WebSocket try the HTTP client: https://docs.convex.dev/api/classes/browser.ConvexHttpClient\",\n );\n }\n webSocketConstructor = webSocketConstructor || WebSocket;\n this.debug = options.reportDebugInfoToConvex ?? false;\n this.address = address;\n this.logger =\n options.logger === false\n ? instantiateNoopLogger({ verbose: options.verbose ?? false })\n : options.logger !== true && options.logger\n ? options.logger\n : instantiateDefaultLogger({ verbose: options.verbose ?? false });\n // Substitute http(s) with ws(s)\n const i = address.search(\"://\");\n if (i === -1) {\n throw new Error(\"Provided address was not an absolute URL.\");\n }\n const origin = address.substring(i + 3); // move past the double slash\n const protocol = address.substring(0, i);\n let wsProtocol;\n if (protocol === \"http\") {\n wsProtocol = \"ws\";\n } else if (protocol === \"https\") {\n wsProtocol = \"wss\";\n } else {\n throw new Error(`Unknown parent protocol ${protocol}`);\n }\n const wsUri = `${wsProtocol}://${origin}/api/${version}/sync`;\n\n this.state = new LocalSyncState();\n this.remoteQuerySet = new RemoteQuerySet(\n (queryId) => this.state.queryPath(queryId),\n this.logger,\n );\n this.requestManager = new RequestManager(\n this.logger,\n this.markConnectionStateDirty,\n );\n\n // This is a callback for AuthenticationManager (which can't call\n // this synchronously, the callback wouldn't work) so the initial\n // pause for expectAuth we call it at the end of this constructor.\n const pauseSocket = () => {\n this.webSocketManager.pause();\n this.state.pause();\n };\n this.authenticationManager = new AuthenticationManager(\n this.state,\n {\n authenticate: (token) => {\n const message = this.state.setAuth(token);\n this.webSocketManager.sendMessage(message);\n return message.baseVersion;\n },\n stopSocket: () => this.webSocketManager.stop(),\n tryRestartSocket: () => this.webSocketManager.tryRestart(),\n pauseSocket,\n resumeSocket: () => this.webSocketManager.resume(),\n clearAuth: () => {\n this.clearAuth();\n },\n },\n {\n logger: this.logger,\n refreshTokenLeewaySeconds: authRefreshTokenLeewaySeconds,\n },\n );\n this.optimisticQueryResults = new OptimisticQueryResults();\n this.addOnTransitionHandler((transition) => {\n onTransition(transition.queries.map((q) => q.token));\n });\n this._nextRequestId = 0;\n this._sessionId = newSessionId();\n\n const { unsavedChangesWarning } = options;\n if (\n typeof window === \"undefined\" ||\n typeof window.addEventListener === \"undefined\"\n ) {\n if (unsavedChangesWarning === true) {\n throw new Error(\n \"unsavedChangesWarning requested, but window.addEventListener not found! Remove {unsavedChangesWarning: true} from Convex client options.\",\n );\n }\n } else if (unsavedChangesWarning !== false) {\n // Listen for tab close events and notify the user on unsaved changes.\n window.addEventListener(\"beforeunload\", (e) => {\n if (this.requestManager.hasIncompleteRequests()) {\n // There are 3 different ways to trigger this pop up so just try all of\n // them.\n\n e.preventDefault();\n // This confirmation message doesn't actually appear in most modern\n // browsers but we tried.\n const confirmationMessage =\n \"Are you sure you want to leave? Your changes may not be saved.\";\n // Recommended method for legacy (IE) browsers.\n // casts to avoid deprecation notices\n ((e || (window as any).event) as any).returnValue =\n confirmationMessage;\n return confirmationMessage;\n }\n });\n }\n\n this.webSocketManager = new WebSocketManager(\n wsUri,\n {\n onOpen: (reconnectMetadata: ReconnectMetadata) => {\n // We have a new WebSocket!\n this.mark(\"convexWebSocketOpen\");\n this.webSocketManager.sendMessage({\n ...reconnectMetadata,\n type: \"Connect\",\n sessionId: this._sessionId,\n maxObservedTimestamp: this.maxObservedTimestamp,\n });\n\n // Throw out our remote query, reissue queries\n // and outstanding mutations, and reauthenticate.\n this.remoteQuerySet = new RemoteQuerySet(\n (queryId) => this.state.queryPath(queryId),\n this.logger,\n );\n const [querySetModification, authModification] = this.state.restart();\n if (authModification) {\n this.webSocketManager.sendMessage(authModification);\n }\n this.webSocketManager.sendMessage(querySetModification);\n for (const message of this.requestManager.restart()) {\n this.webSocketManager.sendMessage(message);\n }\n },\n onResume: () => {\n const [querySetModification, authModification] = this.state.resume();\n if (authModification) {\n this.webSocketManager.sendMessage(authModification);\n }\n if (querySetModification) {\n this.webSocketManager.sendMessage(querySetModification);\n }\n for (const message of this.requestManager.resume()) {\n this.webSocketManager.sendMessage(message);\n }\n },\n onMessage: (serverMessage: ServerMessage) => {\n // Metrics events grow linearly with reconnection attempts so this\n // conditional prevents n^2 metrics reporting.\n if (!this.firstMessageReceived) {\n this.firstMessageReceived = true;\n this.mark(\"convexFirstMessageReceived\");\n this.reportMarks();\n }\n switch (serverMessage.type) {\n case \"Transition\": {\n this.observedTimestamp(serverMessage.endVersion.ts);\n this.authenticationManager.onTransition(serverMessage);\n this.remoteQuerySet.transition(serverMessage);\n this.state.transition(serverMessage);\n const completedRequests = this.requestManager.removeCompleted(\n this.remoteQuerySet.timestamp(),\n );\n this.notifyOnQueryResultChanges(completedRequests);\n break;\n }\n case \"MutationResponse\": {\n if (serverMessage.success) {\n this.observedTimestamp(serverMessage.ts);\n }\n const completedMutationInfo =\n this.requestManager.onResponse(serverMessage);\n if (completedMutationInfo !== null) {\n this.notifyOnQueryResultChanges(\n new Map([\n [\n completedMutationInfo.requestId,\n completedMutationInfo.result,\n ],\n ]),\n );\n }\n break;\n }\n case \"ActionResponse\": {\n this.requestManager.onResponse(serverMessage);\n break;\n }\n case \"AuthError\": {\n this.authenticationManager.onAuthError(serverMessage);\n break;\n }\n case \"FatalError\": {\n const error = logFatalError(this.logger, serverMessage.error);\n void this.webSocketManager.terminate();\n throw error;\n }\n default: {\n serverMessage satisfies never;\n }\n }\n\n return {\n hasSyncedPastLastReconnect: this.hasSyncedPastLastReconnect(),\n };\n },\n onServerDisconnectError: options.onServerDisconnectError,\n },\n webSocketConstructor,\n this.logger,\n this.markConnectionStateDirty,\n this.debug,\n );\n this.mark(\"convexClientConstructed\");\n\n // Begin client in a paused state waiting for an auth token.\n if (options.expectAuth) {\n pauseSocket();\n }\n }\n\n /**\n * Return true if there is outstanding work from prior to the time of the most recent restart.\n * This indicates that the client has not proven itself to have gotten past the issue that\n * potentially led to the restart. Use this to influence when to reset backoff after a failure.\n */\n private hasSyncedPastLastReconnect() {\n const hasSyncedPastLastReconnect =\n this.requestManager.hasSyncedPastLastReconnect() &&\n this.state.hasSyncedPastLastReconnect();\n return hasSyncedPastLastReconnect;\n }\n\n private observedTimestamp(observedTs: TS) {\n if (\n this.maxObservedTimestamp === undefined ||\n this.maxObservedTimestamp.lessThanOrEqual(observedTs)\n ) {\n this.maxObservedTimestamp = observedTs;\n }\n }\n\n getMaxObservedTimestamp() {\n return this.maxObservedTimestamp;\n }\n\n /**\n * Compute the current query results based on the remoteQuerySet and the\n * current optimistic updates and call `onTransition` for all the changed\n * queries.\n *\n * @param completedMutations - A set of mutation IDs whose optimistic updates\n * are no longer needed.\n */\n private notifyOnQueryResultChanges(\n completedRequests: Map<RequestId, FunctionResult>,\n ) {\n const remoteQueryResults: Map<QueryId, FunctionResult> =\n this.remoteQuerySet.remoteQueryResults();\n const queryTokenToValue: QueryResultsMap = new Map();\n for (const [queryId, result] of remoteQueryResults) {\n const queryToken = this.state.queryToken(queryId);\n // It's possible that we've already unsubscribed to this query but\n // the server hasn't learned about that yet. If so, ignore this one.\n\n if (queryToken !== null) {\n const query = {\n result,\n udfPath: this.state.queryPath(queryId)!,\n args: this.state.queryArgs(queryId)!,\n };\n queryTokenToValue.set(queryToken, query);\n }\n }\n\n // Query tokens that are new (because of new server results or new local optimistic updates)\n // or differ from old values (because of changes from local optimistic updates or new results\n // from the server).\n const changedQueryTokens =\n this.optimisticQueryResults.ingestQueryResultsFromServer(\n queryTokenToValue,\n new Set(completedRequests.keys()),\n );\n\n this.handleTransition({\n queries: changedQueryTokens.map((token) => {\n const optimisticResult =\n this.optimisticQueryResults.rawQueryResult(token);\n return {\n token,\n modification: {\n kind: \"Updated\" as const,\n result: optimisticResult,\n },\n };\n }),\n reflectedMutations: Array.from(completedRequests).map(\n ([requestId, result]) => ({\n requestId,\n result,\n }),\n ),\n timestamp: this.remoteQuerySet.timestamp(),\n });\n }\n\n private handleTransition(transition: Transition) {\n for (const fn of this._onTransitionFns.values()) {\n fn(transition);\n }\n }\n\n /**\n * Add a handler that will be called on a transition.\n *\n * Any external side effects (e.g. setting React state) should be handled here.\n *\n * @param fn\n *\n * @returns\n */\n addOnTransitionHandler(fn: (transition: Transition) => void) {\n const id = this._transitionHandlerCounter++;\n this._onTransitionFns.set(id, fn);\n return () => this._onTransitionFns.delete(id);\n }\n\n /**\n * Get the current JWT auth token and decoded claims.\n */\n getCurrentAuthClaims():\n | { token: string; decoded: Record<string, any> }\n | undefined {\n const authToken = this.state.getAuth();\n let decoded: Record<string, any> = {};\n if (authToken && authToken.tokenType === \"User\") {\n try {\n decoded = authToken ? jwtDecode(authToken.value) : {};\n } catch {\n decoded = {};\n }\n } else {\n return undefined;\n }\n return { token: authToken.value, decoded };\n }\n\n /**\n * Set the authentication token to be used for subsequent queries and mutations.\n * `fetchToken` will be called automatically again if a token expires.\n * `fetchToken` should return `null` if the token cannot be retrieved, for example\n * when the user's rights were permanently revoked.\n * @param fetchToken - an async function returning the JWT-encoded OpenID Connect Identity Token\n * @param onChange - a callback that will be called when the authentication status changes\n */\n setAuth(\n fetchToken: AuthTokenFetcher,\n onChange: (isAuthenticated: boolean) => void,\n ) {\n void this.authenticationManager.setConfig(fetchToken, onChange);\n }\n\n hasAuth() {\n return this.state.hasAuth();\n }\n\n /** @internal */\n setAdminAuth(value: string, fakeUserIdentity?: UserIdentityAttributes) {\n const message = this.state.setAdminAuth(value, fakeUserIdentity);\n this.webSocketManager.sendMessage(message);\n }\n\n clearAuth() {\n const message = this.state.clearAuth();\n this.webSocketManager.sendMessage(message);\n }\n\n /**\n * Subscribe to a query function.\n *\n * Whenever this query's result changes, the `onTransition` callback\n * passed into the constructor will be called.\n *\n * @param name - The name of the query.\n * @param args - An arguments object for the query. If this is omitted, the\n * arguments will be `{}`.\n * @param options - A {@link SubscribeOptions} options object for this query.\n\n * @returns An object containing a {@link QueryToken} corresponding to this\n * query and an `unsubscribe` callback.\n */\n subscribe(\n name: string,\n args?: Record<string, Value>,\n options?: SubscribeOptions,\n ): { queryToken: QueryToken; unsubscribe: () => void } {\n const argsObject = parseArgs(args);\n\n const { modification, queryToken, unsubscribe } = this.state.subscribe(\n name,\n argsObject,\n options?.journal,\n options?.componentPath,\n );\n if (modification !== null) {\n this.webSocketManager.sendMessage(modification);\n }\n return {\n queryToken,\n unsubscribe: () => {\n const modification = unsubscribe();\n if (modification) {\n this.webSocketManager.sendMessage(modification);\n }\n },\n };\n }\n\n /**\n * A query result based only on the current, local state.\n *\n * The only way this will return a value is if we're already subscribed to the\n * query or its value has been set optimistically.\n */\n localQueryResult(\n udfPath: string,\n args?: Record<string, Value>,\n ): Value | undefined {\n const argsObject = parseArgs(args);\n const queryToken = serializePathAndArgs(udfPath, argsObject);\n return this.optimisticQueryResults.queryResult(queryToken);\n }\n\n /**\n * Get query result by query token based on current, local state\n *\n * The only way this will return a value is if we're already subscribed to the\n * query or its value has been set optimistically.\n *\n * @internal\n */\n localQueryResultByToken(queryToken: QueryToken): Value | undefined {\n return this.optimisticQueryResults.queryResult(queryToken);\n }\n\n /**\n * Whether local query result is available for a token.\n *\n * This method does not throw if the result is an error.\n *\n * @internal\n */\n hasLocalQueryResultByToken(queryToken: QueryToken): boolean {\n return this.optimisticQueryResults.hasQueryResult(queryToken);\n }\n\n /**\n * @internal\n */\n localQueryLogs(\n udfPath: string,\n args?: Record<string, Value>,\n ): string[] | undefined {\n const argsObject = parseArgs(args);\n const queryToken = serializePathAndArgs(udfPath, argsObject);\n return this.optimisticQueryResults.queryLogs(queryToken);\n }\n\n /**\n * Retrieve the current {@link QueryJournal} for this query function.\n *\n * If we have not yet received a result for this query, this will be `undefined`.\n *\n * @param name - The name of the query.\n * @param args - The arguments object for this query.\n * @returns The query's {@link QueryJournal} or `undefined`.\n */\n queryJournal(\n name: string,\n args?: Record<string, Value>,\n ): QueryJournal | undefined {\n const argsObject = parseArgs(args);\n const queryToken = serializePathAndArgs(name, argsObject);\n return this.state.queryJournal(queryToken);\n }\n\n /**\n * Get the current {@link ConnectionState} between the client and the Convex\n * backend.\n *\n * @returns The {@link ConnectionState} with the Convex backend.\n */\n connectionState(): ConnectionState {\n const wsConnectionState = this.webSocketManager.connectionState();\n return {\n hasInflightRequests: this.requestManager.hasInflightRequests(),\n isWebSocketConnected: wsConnectionState.isConnected,\n hasEverConnected: wsConnectionState.hasEverConnected,\n connectionCount: wsConnectionState.connectionCount,\n connectionRetries: wsConnectionState.connectionRetries,\n timeOfOldestInflightRequest:\n this.requestManager.timeOfOldestInflightRequest(),\n inflightMutations: this.requestManager.inflightMutations(),\n inflightActions: this.requestManager.inflightActions(),\n };\n }\n\n /**\n * Call this whenever the connection state may have changed in a way that could\n * require publishing it. Schedules a possibly update.\n */\n private markConnectionStateDirty = () => {\n void Promise.resolve().then(() => {\n const curConnectionState = this.connectionState();\n if (\n JSON.stringify(curConnectionState) !==\n JSON.stringify(this._lastPublishedConnectionState)\n ) {\n this._lastPublishedConnectionState = curConnectionState;\n for (const cb of this.connectionStateSubscribers.values()) {\n // One of these callback throwing will prevent other callbacks\n // from running but will not leave the client in a undefined state.\n cb(curConnectionState);\n }\n }\n });\n };\n\n /**\n * Subscribe to the {@link ConnectionState} between the client and the Convex\n * backend, calling a callback each time it changes.\n *\n * Subscribed callbacks will be called when any part of ConnectionState changes.\n * ConnectionState may grow in future versions (e.g. to provide a array of\n * inflight requests) in which case callbacks would be called more frequently.\n *\n * @returns An unsubscribe function to stop listening.\n */\n subscribeToConnectionState(\n cb: (connectionState: ConnectionState) => void,\n ): () => void {\n const id = this.nextConnectionStateSubscriberId++;\n this.connectionStateSubscribers.set(id, cb);\n return () => {\n this.connectionStateSubscribers.delete(id);\n };\n }\n\n /**\n * Execute a mutation function.\n *\n * @param name - The name of the mutation.\n * @param args - An arguments object for the mutation. If this is omitted,\n * the arguments will be `{}`.\n * @param options - A {@link MutationOptions} options object for this mutation.\n\n * @returns - A promise of the mutation's result.\n */\n async mutation(\n name: string,\n args?: Record<string, Value>,\n options?: MutationOptions,\n ): Promise<any> {\n const result = await this.mutationInternal(name, args, options);\n if (!result.success) {\n if (result.errorData !== undefined) {\n throw forwardData(\n result,\n new ConvexError(\n createHybridErrorStacktrace(\"mutation\", name, result),\n ),\n );\n }\n throw new Error(createHybridErrorStacktrace(\"mutation\", name, result));\n }\n return result.value;\n }\n\n /**\n * @internal\n */\n async mutationInternal(\n udfPath: string,\n args?: Record<string, Value>,\n options?: MutationOptions,\n componentPath?: string,\n ): Promise<FunctionResult> {\n const { mutationPromise } = this.enqueueMutation(\n udfPath,\n args,\n options,\n componentPath,\n );\n return mutationPromise;\n }\n\n /**\n * @internal\n */\n enqueueMutation(\n udfPath: string,\n args?: Record<string, Value>,\n options?: MutationOptions,\n componentPath?: string,\n ): { requestId: RequestId; mutationPromise: Promise<FunctionResult> } {\n const mutationArgs = parseArgs(args);\n this.tryReportLongDisconnect();\n const requestId = this.nextRequestId;\n this._nextRequestId++;\n\n if (options !== undefined) {\n const optimisticUpdate = options.optimisticUpdate;\n if (optimisticUpdate !== undefined) {\n const wrappedUpdate = (localQueryStore: OptimisticLocalStore) => {\n const result: unknown = optimisticUpdate(\n localQueryStore,\n mutationArgs,\n );\n if (result instanceof Promise) {\n this.logger.warn(\n \"Optimistic update handler returned a Promise. Optimistic updates should be synchronous.\",\n );\n }\n };\n\n const changedQueryTokens =\n this.optimisticQueryResults.applyOptimisticUpdate(\n wrappedUpdate,\n requestId,\n );\n\n const changedQueries = changedQueryTokens.map((token) => {\n const localResult = this.localQueryResultByToken(token);\n return {\n token,\n modification: {\n kind: \"Updated\" as const,\n result:\n localResult === undefined\n ? undefined\n : {\n success: true as const,\n value: localResult,\n logLines: [],\n },\n },\n };\n });\n this.handleTransition({\n queries: changedQueries,\n reflectedMutations: [],\n timestamp: this.remoteQuerySet.timestamp(),\n });\n }\n }\n\n const message: MutationRequest = {\n type: \"Mutation\",\n requestId,\n udfPath,\n componentPath,\n args: [convexToJson(mutationArgs)],\n };\n const mightBeSent = this.webSocketManager.sendMessage(message);\n const mutationPromise = this.requestManager.request(message, mightBeSent);\n return {\n requestId,\n mutationPromise,\n };\n }\n\n /**\n * Execute an action function.\n *\n * @param name - The name of the action.\n * @param args - An arguments object for the action. If this is omitted,\n * the arguments will be `{}`.\n * @returns A promise of the action's result.\n */\n async action(name: string, args?: Record<string, Value>): Promise<any> {\n const result = await this.actionInternal(name, args);\n if (!result.success) {\n if (result.errorData !== undefined) {\n throw forwardData(\n result,\n new ConvexError(createHybridErrorStacktrace(\"action\", name, result)),\n );\n }\n throw new Error(createHybridErrorStacktrace(\"action\", name, result));\n }\n return result.value;\n }\n\n /**\n * @internal\n */\n async actionInternal(\n udfPath: string,\n args?: Record<string, Value>,\n componentPath?: string,\n ): Promise<FunctionResult> {\n const actionArgs = parseArgs(args);\n const requestId = this.nextRequestId;\n this._nextRequestId++;\n this.tryReportLongDisconnect();\n\n const message: ActionRequest = {\n type: \"Action\",\n requestId,\n udfPath,\n componentPath,\n args: [convexToJson(actionArgs)],\n };\n\n const mightBeSent = this.webSocketManager.sendMessage(message);\n return this.requestManager.request(message, mightBeSent);\n }\n\n /**\n * Close any network handles associated with this client and stop all subscriptions.\n *\n * Call this method when you're done with an {@link BaseConvexClient} to\n * dispose of its sockets and resources.\n *\n * @returns A `Promise` fulfilled when the connection has been completely closed.\n */\n async close(): Promise<void> {\n this.authenticationManager.stop();\n return this.webSocketManager.terminate();\n }\n\n /**\n * Return the address for this client, useful for creating a new client.\n *\n * Not guaranteed to match the address with which this client was constructed:\n * it may be canonicalized.\n */\n get url() {\n return this.address;\n }\n\n /**\n * @internal\n */\n get nextRequestId() {\n return this._nextRequestId;\n }\n\n /**\n * @internal\n */\n get sessionId() {\n return this._sessionId;\n }\n\n // Instance property so that `mark()` doesn't need to be called as a method.\n private mark = (name: MarkName) => {\n if (this.debug) {\n mark(name, this.sessionId);\n }\n };\n\n /**\n * Reports performance marks to the server. This should only be called when\n * we have a functional websocket.\n */\n private reportMarks() {\n if (this.debug) {\n const report = getMarksReport(this.sessionId);\n this.webSocketManager.sendMessage({\n type: \"Event\",\n eventType: \"ClientConnect\",\n event: report,\n });\n }\n }\n\n private tryReportLongDisconnect() {\n if (!this.debug) {\n return;\n }\n const timeOfOldestRequest =\n this.connectionState().timeOfOldestInflightRequest;\n if (\n timeOfOldestRequest === null ||\n Date.now() - timeOfOldestRequest.getTime() <= 60 * 1000\n ) {\n return;\n }\n const endpoint = `${this.address}/api/debug_event`;\n fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Convex-Client\": `npm-${version}`,\n },\n body: JSON.stringify({ event: \"LongWebsocketDisconnect\" }),\n })\n .then((response) => {\n if (!response.ok) {\n this.logger.warn(\n \"Analytics request failed with response:\",\n response.body,\n );\n }\n })\n .catch((error) => {\n this.logger.warn(\"Analytics response failed with error:\", error);\n });\n }\n}\n", "import type { PaginationResult } from \"../../server/index.js\";\nimport type { Infer, Value } from \"../../values/index.js\";\nimport type { paginationOptsValidator } from \"../../server/index.js\";\n\nexport type PaginationStatus =\n | \"LoadingFirstPage\"\n | \"CanLoadMore\"\n | \"LoadingMore\"\n | \"Exhausted\";\n\nexport type PaginatedQueryResult<T> = {\n results: T[];\n status: PaginationStatus;\n loadMore: LoadMoreOfPaginatedQuery;\n};\n\n/**\n * Returns whether loading more was actually initiated; in cases where\n * a paginated query is already loading more items or there are no more\n * items available, calling loadMore() may do nothing.\n */\nexport type LoadMoreOfPaginatedQuery = (numItems: number) => boolean;\n\n// The arguments for each page query.\nexport function asPaginationArgs(value: Value): Record<string, Value> & {\n paginationOpts: Infer<typeof paginationOptsValidator>;\n} {\n if (typeof (value as any).paginationOpts.numItems !== \"number\") {\n throw new Error(`Not valid paginated query args: ${JSON.stringify(value)}`);\n }\n return value as unknown as Record<string, Value> & {\n paginationOpts: Infer<typeof paginationOptsValidator>;\n };\n}\n\n/**\n * Validates that a Value is a valid pagination result and returns it cast to PaginationResult.\n */\nexport function asPaginationResult(value: Value): PaginationResult<Value> {\n if (\n typeof value !== \"object\" ||\n value === null ||\n !Array.isArray((value as any).page) ||\n typeof (value as any).isDone !== \"boolean\" ||\n typeof (value as any).continueCursor !== \"string\"\n ) {\n throw new Error(`Not a valid paginated query result: ${value?.toString()}`);\n }\n return value as unknown as PaginationResult<Value>;\n}\n", "/**\n * PaginatedQueryClient maps subscriptions to paginated queries to the\n * individual page queries and handles page splits.\n *\n * In order to process all modified queries, paginated and normal, in the same\n * synchronous call the PaginatedQueryClient transition should be used exclusively.\n *\n * Like the BaseConvexClient, this client is not Convex Function type-aware: it deals\n * with queries as functions that return Value, not the specific value.\n * Use a higher-level library to get types.\n */\n\nimport { Value } from \"../../values/index.js\";\nimport {\n PaginatedQueryToken,\n QueryToken,\n serializePaginatedPathAndArgs,\n canonicalizeUdfPath,\n} from \"./udf_path_utils.js\";\nimport { BaseConvexClient, Transition } from \"./client.js\";\nimport {\n PaginatedQueryResult,\n PaginationStatus,\n asPaginationResult,\n} from \"./pagination.js\";\nimport { TS } from \"./protocol.js\";\nimport { Long } from \"../../vendor/long.js\";\n\ntype QueryPageKey = number;\n\n/**\n * Represents a paginated query subscription with multiple pages.\n *\n * To know the order of pages it's necessary to consult `pageKeys`.\n * The pages in this array are active, they constitute a gapless sequence of results.\n * Some pages are not in this array: they may be waiting for data for a page split.\n */\ntype LocalPaginatedQuery = {\n token: PaginatedQueryToken;\n canonicalizedUdfPath: string;\n args: Record<string, Value>; // WITHOUT paginationOpts\n numSubscribers: number;\n options: { initialNumItems: number };\n nextPageKey: QueryPageKey;\n pageKeys: QueryPageKey[]; // These pages make up the active page queries.\n // Map page keys to their query subscriptions\n pageKeyToQuery: Map<\n QueryPageKey,\n { queryToken: QueryToken; unsubscribe: () => void }\n >;\n ongoingSplits: Map<QueryPageKey, [QueryPageKey, QueryPageKey]>;\n skip: boolean;\n\n // Give separate uses of the query separate identities,\n // which may be removed in the future to improve caching.\n id: number;\n};\n\nexport interface SubscribeToPaginatedQueryOptions {\n initialNumItems: number;\n id: number;\n}\n\ntype AnyPaginatedQueryResult = PaginatedQueryResult<Value>;\n\nexport type PaginatedQueryModification =\n | { kind: \"Updated\"; result: AnyPaginatedQueryResult | undefined }\n | { kind: \"Removed\" };\n\nexport type ExtendedTransition = Transition & {\n paginatedQueries: Array<{\n token: PaginatedQueryToken;\n modification: PaginatedQueryModification;\n }>;\n};\n\nexport class PaginatedQueryClient {\n private paginatedQuerySet: Map<PaginatedQueryToken, LocalPaginatedQuery> =\n new Map();\n // hold onto a real Transition so we can construct synthetic ones with that timestamp\n private lastTransitionTs: TS;\n\n constructor(\n private client: BaseConvexClient,\n private onTransition: (transition: ExtendedTransition) => void,\n ) {\n // Nonsense initial value to construct synthetic Transitions\n this.lastTransitionTs = Long.fromNumber(0);\n this.client.addOnTransitionHandler((transition: Transition) =>\n this.onBaseTransition(transition),\n );\n }\n\n /**\n * Subscribe to a paginated query.\n *\n * @param name - The name of the paginated query function\n * @param args - Arguments for the query (excluding paginationOpts)\n * @param options - Pagination options including initialNumItems\n * @returns Object with paginatedQueryToken and unsubscribe function\n */\n subscribe(\n name: string,\n args: Record<string, Value>,\n options: SubscribeToPaginatedQueryOptions,\n ): {\n paginatedQueryToken: PaginatedQueryToken;\n unsubscribe: () => void;\n } {\n const canonicalizedUdfPath = canonicalizeUdfPath(name);\n // Note that only the expected options are included in the serialization.\n const token = serializePaginatedPathAndArgs(\n canonicalizedUdfPath,\n args,\n options,\n );\n\n const unsubscribe = () => this.removePaginatedQuerySubscriber(token);\n\n const existingEntry = this.paginatedQuerySet.get(token);\n if (existingEntry) {\n existingEntry.numSubscribers += 1;\n return {\n paginatedQueryToken: token,\n unsubscribe,\n };\n }\n\n // Create new paginated query\n this.paginatedQuerySet.set(token, {\n token,\n canonicalizedUdfPath,\n args,\n numSubscribers: 1,\n options: { initialNumItems: options.initialNumItems },\n nextPageKey: 0,\n pageKeys: [],\n pageKeyToQuery: new Map(),\n ongoingSplits: new Map(),\n skip: false,\n id: options.id,\n });\n\n this.addPageToPaginatedQuery(token, null, options.initialNumItems);\n\n return {\n paginatedQueryToken: token,\n unsubscribe,\n };\n }\n\n /**\n * Get current results for a paginated query based on local state.\n *\n * Throws an error when one of the pages has errored.\n */\n localQueryResult(\n name: string,\n args: Record<string, Value>,\n options: { initialNumItems: number; id: number },\n ): AnyPaginatedQueryResult | undefined {\n const canonicalizedUdfPath = canonicalizeUdfPath(name);\n const token = serializePaginatedPathAndArgs(\n canonicalizedUdfPath,\n args,\n options,\n );\n return this.localQueryResultByToken(token);\n }\n\n /**\n * @internal\n */\n localQueryResultByToken(\n token: PaginatedQueryToken,\n ): AnyPaginatedQueryResult | undefined {\n // undefined is probably the wrong value! Should be a real paginated query result for loading!\n // Butit's confusing why we'd ever get this, I guess some flows call localQueryResult before\n // subscribing? That's proabbly fair but is it consistent with the normal client?\n // What is the invariant here, will a token always exist? Or can a lookup occur at any time?\n const paginatedQuery = this.paginatedQuerySet.get(token);\n if (!paginatedQuery) {\n return undefined;\n }\n\n const activePages = this.activePageQueryTokens(paginatedQuery);\n if (activePages.length === 0) {\n return {\n results: [],\n status: \"LoadingFirstPage\",\n loadMore: (numItems: number) => {\n return this.loadMoreOfPaginatedQuery(token, numItems);\n },\n };\n }\n\n let allResults: Value[] = [];\n\n // Some page is loading (this isn't supposed to happen to any page but the last)\n let hasUndefined = false;\n let isDone = false;\n\n for (const pageToken of activePages) {\n // This throws, don't catch it, it should bubble up.\n // It might be a InvalidCursor Error. If it is, this query\n // should be reset (for now, use a new ID to ensure new state).\n //\n // In the future this might be caught and dealt with here but\n // an ID-based solution won't work here, ID is an intrinsic property\n // of this paginated query.\n const result = this.client.localQueryResultByToken(pageToken);\n\n if (result === undefined) {\n hasUndefined = true;\n isDone = false;\n continue;\n }\n\n const paginationResult = asPaginationResult(result);\n allResults = allResults.concat(paginationResult.page);\n // logic only relevant to the last page, we just happen to run it each time\n isDone = !!paginationResult.isDone;\n }\n\n let status: PaginationStatus;\n if (hasUndefined) {\n status = allResults.length === 0 ? \"LoadingFirstPage\" : \"LoadingMore\";\n } else if (isDone) {\n status = \"Exhausted\";\n } else {\n status = \"CanLoadMore\";\n }\n\n return {\n results: allResults,\n status,\n loadMore: (numItems: number) => {\n return this.loadMoreOfPaginatedQuery(token, numItems);\n },\n };\n }\n\n private onBaseTransition(transition: Transition) {\n const changedBaseTokens = transition.queries.map((q) => q.token);\n const changed = this.queriesContainingTokens(changedBaseTokens);\n\n let paginatedQueries: Array<{\n token: PaginatedQueryToken;\n modification: PaginatedQueryModification;\n }> = [];\n\n if (changed.length > 0) {\n this.processPaginatedQuerySplits(changed, (token) =>\n this.client.localQueryResultByToken(token),\n );\n\n paginatedQueries = changed.map((token) => ({\n token,\n modification: {\n kind: \"Updated\" as const,\n result: this.localQueryResultByToken(token),\n },\n }));\n }\n\n const extendedTransition: ExtendedTransition = {\n ...transition,\n paginatedQueries,\n };\n\n this.onTransition(extendedTransition);\n }\n\n /**\n * Load more items for a paginated query.\n *\n * This *always* causes a transition, the status of the query\n * has probably changed from \"CanLoadMore\" to \"LoadingMore\".\n * Data might have changed too: maybe a subscription to this page\n * query already exists (unlikely but possible) or this page query\n * has an optimistic update providing some initial data.\n *\n * @internal\n */\n private loadMoreOfPaginatedQuery(\n token: PaginatedQueryToken,\n numItems: number,\n ): boolean {\n this.mustGetPaginatedQuery(token);\n\n const lastPageToken = this.queryTokenForLastPageOfPaginatedQuery(token);\n const lastPageResult = this.client.localQueryResultByToken(lastPageToken);\n\n if (!lastPageResult) {\n // Still loading a page and concurrent loads are not allowed\n return false;\n }\n\n const paginationResult = asPaginationResult(lastPageResult);\n if (paginationResult.isDone) {\n // No more pages available\n return false;\n }\n\n this.addPageToPaginatedQuery(\n token,\n paginationResult.continueCursor,\n numItems,\n );\n\n const loadMoreTransition: ExtendedTransition = {\n timestamp: this.lastTransitionTs,\n reflectedMutations: [],\n queries: [],\n paginatedQueries: [\n {\n token,\n modification: {\n kind: \"Updated\" as const,\n result: this.localQueryResultByToken(token),\n },\n },\n ],\n };\n this.onTransition(loadMoreTransition);\n\n return true;\n }\n\n /**\n * @internal\n */\n private queriesContainingTokens(\n queryTokens: QueryToken[],\n ): PaginatedQueryToken[] {\n if (queryTokens.length === 0) {\n return [];\n }\n\n const changed: PaginatedQueryToken[] = [];\n const queryTokenSet = new Set(queryTokens);\n\n for (const [paginatedToken, paginatedQuery] of this.paginatedQuerySet) {\n for (const pageToken of this.allQueryTokens(paginatedQuery)) {\n if (queryTokenSet.has(pageToken)) {\n changed.push(paginatedToken);\n break;\n }\n }\n }\n\n return changed;\n }\n\n /**\n * @internal\n */\n private processPaginatedQuerySplits(\n changed: PaginatedQueryToken[],\n getResult: (token: QueryToken) => Value | undefined,\n ): void {\n for (const paginatedQueryToken of changed) {\n const paginatedQuery = this.mustGetPaginatedQuery(paginatedQueryToken);\n\n // These properties are all mutable, the destructure here is optional.\n const { ongoingSplits, pageKeyToQuery, pageKeys } = paginatedQuery;\n\n // Check for any completed splits\n for (const [pageKey, [splitKey1, splitKey2]] of ongoingSplits) {\n const bothNewPagesLoaded =\n getResult(pageKeyToQuery.get(splitKey1)!.queryToken) !== undefined &&\n getResult(pageKeyToQuery.get(splitKey2)!.queryToken) !== undefined;\n\n if (bothNewPagesLoaded) {\n this.completePaginatedQuerySplit(\n paginatedQuery,\n pageKey,\n splitKey1,\n splitKey2,\n );\n }\n }\n\n // Check each active page for splits needed\n for (const pageKey of pageKeys) {\n if (ongoingSplits.has(pageKey)) {\n continue; // Already splitting\n }\n\n const pageToken = pageKeyToQuery.get(pageKey)!.queryToken;\n const pageResult = getResult(pageToken);\n if (!pageResult) {\n continue;\n }\n const result = asPaginationResult(pageResult);\n\n // Check if this page needs splitting\n const shouldSplit =\n result.splitCursor &&\n (result.pageStatus === \"SplitRecommended\" ||\n result.pageStatus === \"SplitRequired\" ||\n // This client-driven page splitting condition will change in the future.\n result.page.length > paginatedQuery.options.initialNumItems * 2);\n\n if (shouldSplit) {\n this.splitPaginatedQueryPage(\n paginatedQuery,\n pageKey,\n result.splitCursor!, // we just checked\n result.continueCursor,\n );\n }\n }\n }\n }\n\n private splitPaginatedQueryPage(\n paginatedQuery: LocalPaginatedQuery,\n pageKey: QueryPageKey,\n splitCursor: string,\n continueCursor: string | null,\n ): void {\n const splitKey1 = paginatedQuery.nextPageKey++;\n const splitKey2 = paginatedQuery.nextPageKey++;\n\n const paginationOpts: Value = {\n cursor: continueCursor,\n numItems: paginatedQuery.options.initialNumItems,\n id: paginatedQuery.id,\n };\n\n // First split page: same cursor as original, but add endCursor at splitCursor\n const firstSubscription = this.client.subscribe(\n paginatedQuery.canonicalizedUdfPath,\n {\n ...paginatedQuery.args,\n paginationOpts: {\n ...paginationOpts,\n cursor: null, // Start from beginning for first split\n endCursor: splitCursor,\n },\n },\n );\n paginatedQuery.pageKeyToQuery.set(splitKey1, firstSubscription);\n\n // Second split page: cursor starts at splitCursor, endCursor is the original continueCursor\n const secondSubscription = this.client.subscribe(\n paginatedQuery.canonicalizedUdfPath,\n {\n ...paginatedQuery.args,\n paginationOpts: {\n ...paginationOpts,\n cursor: splitCursor,\n endCursor: continueCursor,\n },\n },\n );\n paginatedQuery.pageKeyToQuery.set(splitKey2, secondSubscription);\n\n paginatedQuery.ongoingSplits.set(pageKey, [splitKey1, splitKey2]);\n }\n\n /**\n * @internal\n */\n private addPageToPaginatedQuery(\n token: PaginatedQueryToken,\n continueCursor: string | null,\n numItems: number,\n ): { queryToken: QueryToken; unsubscribe: () => void } {\n const paginatedQuery = this.mustGetPaginatedQuery(token);\n const pageKey = paginatedQuery.nextPageKey++;\n\n const paginationOpts: Value = {\n cursor: continueCursor,\n numItems,\n id: paginatedQuery.id,\n };\n\n const pageArgs = {\n ...paginatedQuery.args,\n paginationOpts,\n };\n\n const subscription = this.client.subscribe(\n paginatedQuery.canonicalizedUdfPath,\n pageArgs,\n );\n\n paginatedQuery.pageKeys.push(pageKey);\n paginatedQuery.pageKeyToQuery.set(pageKey, subscription);\n return subscription;\n }\n\n private removePaginatedQuerySubscriber(token: PaginatedQueryToken): void {\n const paginatedQuery = this.paginatedQuerySet.get(token);\n if (!paginatedQuery) {\n return;\n }\n\n paginatedQuery.numSubscribers -= 1;\n if (paginatedQuery.numSubscribers > 0) {\n return;\n }\n\n // Remove all page subscriptions by calling their unsubscribe callbacks\n for (const subscription of paginatedQuery.pageKeyToQuery.values()) {\n subscription.unsubscribe();\n }\n\n this.paginatedQuerySet.delete(token);\n }\n\n private completePaginatedQuerySplit(\n paginatedQuery: LocalPaginatedQuery,\n pageKey: QueryPageKey,\n splitKey1: QueryPageKey,\n splitKey2: QueryPageKey,\n ): void {\n const originalQuery = paginatedQuery.pageKeyToQuery.get(pageKey)!;\n paginatedQuery.pageKeyToQuery.delete(pageKey);\n const pageIndex = paginatedQuery.pageKeys.indexOf(pageKey);\n paginatedQuery.pageKeys.splice(pageIndex, 1, splitKey1, splitKey2);\n paginatedQuery.ongoingSplits.delete(pageKey);\n originalQuery.unsubscribe();\n }\n\n /** The query tokens for all active pages, in result order */\n private activePageQueryTokens(\n paginatedQuery: LocalPaginatedQuery,\n ): QueryToken[] {\n return paginatedQuery.pageKeys.map(\n (pageKey) => paginatedQuery.pageKeyToQuery.get(pageKey)!.queryToken,\n );\n }\n\n private allQueryTokens(paginatedQuery: LocalPaginatedQuery): QueryToken[] {\n return Array.from(paginatedQuery.pageKeyToQuery.values()).map(\n (sub) => sub.queryToken,\n );\n }\n\n private queryTokenForLastPageOfPaginatedQuery(\n token: PaginatedQueryToken,\n ): QueryToken {\n const paginatedQuery = this.mustGetPaginatedQuery(token);\n const lastPageKey =\n paginatedQuery.pageKeys[paginatedQuery.pageKeys.length - 1];\n if (lastPageKey === undefined) {\n throw new Error(`No pages for paginated query ${token}`);\n }\n return paginatedQuery.pageKeyToQuery.get(lastPageKey)!.queryToken;\n }\n\n private mustGetPaginatedQuery(\n token: PaginatedQueryToken,\n ): LocalPaginatedQuery {\n const paginatedQuery = this.paginatedQuerySet.get(token);\n if (!paginatedQuery) {\n throw new Error(\"paginated query no longer exists for token \" + token);\n }\n return paginatedQuery;\n }\n}\n", "// Inspired by https://tanstack.com/query/v5/docs/framework/react/guides/query-options\nimport type { FunctionArgs, FunctionReference } from \"../server/api.js\";\n\n/**\n * Options for a Convex query: the query function reference and its arguments.\n *\n * Used with the object-form overload of {@link useQuery}.\n *\n * @public\n */\nexport type QueryOptions<Query extends FunctionReference<\"query\">> = {\n /**\n * The query function to run.\n */\n query: Query;\n /**\n * The arguments to the query function.\n */\n args: FunctionArgs<Query>;\n};\n\n/**\n * Creates a type-safe {@link QueryOptions} object for a Convex query.\n *\n * This is an identity function that exists to provide type inference \u2014 passing\n * your query and args through this helper ensures TypeScript infers the correct\n * `Query` type parameter, which enables precise return types on hooks like\n * {@link useQuery}.\n *\n * ```typescript\n * const opts = convexQueryOptions({\n * query: api.users.getById,\n * args: { id: userId },\n * });\n * // opts is typed as QueryOptions<typeof api.users.getById>\n * client.prewarmQuery(opts);\n * ```\n *\n * @param options - The query and its arguments.\n * @returns The same object, typed as `QueryOptions<Query>`.\n * @internal\n */\nexport function convexQueryOptions<Query extends FunctionReference<\"query\">>(\n options: QueryOptions<Query>,\n): QueryOptions<Query> {\n return options;\n}\n", "import { BaseConvexClient } from \"../browser/index.js\";\nimport type {\n OptimisticUpdate,\n PaginatedQueryToken,\n QueryToken,\n PaginationStatus,\n} from \"../browser/index.js\";\nimport React, { useCallback, useContext, useMemo } from \"react\";\nimport { convexToJson, Value } from \"../values/index.js\";\nimport { QueryJournal } from \"../browser/sync/protocol.js\";\nimport {\n AuthTokenFetcher,\n BaseConvexClientOptions,\n ConnectionState,\n} from \"../browser/sync/client.js\";\nimport type { UserIdentityAttributes } from \"../browser/sync/protocol.js\";\nimport { RequestForQueries, useQueries } from \"./use_queries.js\";\nimport { useSubscription } from \"./use_subscription.js\";\nimport { parseArgs } from \"../common/index.js\";\nimport {\n ArgsAndOptions,\n FunctionArgs,\n FunctionReference,\n FunctionReturnType,\n OptionalRestArgs,\n getFunctionName,\n makeFunctionReference,\n} from \"../server/api.js\";\nimport { EmptyObject } from \"../server/registration.js\";\nimport {\n instantiateDefaultLogger,\n instantiateNoopLogger,\n Logger,\n} from \"../browser/logging.js\";\nimport type { QueryOptions } from \"../browser/query_options.js\";\nimport { LoadMoreOfPaginatedQuery } from \"../browser/sync/pagination.js\";\nimport {\n PaginatedQueryClient,\n ExtendedTransition,\n} from \"../browser/sync/paginated_query_client.js\";\n\n// When no arguments are passed, extend subscriptions (for APIs that do this by default)\n// for this amount after the subscription would otherwise be dropped.\nconst DEFAULT_EXTEND_SUBSCRIPTION_FOR = 5_000;\n\nif (typeof React === \"undefined\") {\n throw new Error(\"Required dependency 'react' not found\");\n}\n\n// TODO Typedoc doesn't generate documentation for the comment below perhaps\n// because it's a callable interface.\n/**\n * An interface to execute a Convex mutation function on the server.\n *\n * @public\n */\nexport interface ReactMutation<Mutation extends FunctionReference<\"mutation\">> {\n /**\n * Execute the mutation on the server, returning a `Promise` of its return value.\n *\n * @param args - Arguments for the mutation to pass up to the server.\n * @returns The return value of the server-side function call.\n */\n (...args: OptionalRestArgs<Mutation>): Promise<FunctionReturnType<Mutation>>;\n\n /**\n * Define an optimistic update to apply as part of this mutation.\n *\n * This is a temporary update to the local query results to facilitate a\n * fast, interactive UI. It enables query results to update before a mutation\n * executed on the server.\n *\n * When the mutation is invoked, the optimistic update will be applied.\n *\n * Optimistic updates can also be used to temporarily remove queries from the\n * client and create loading experiences until a mutation completes and the\n * new query results are synced.\n *\n * The update will be automatically rolled back when the mutation is fully\n * completed and queries have been updated.\n *\n * @param optimisticUpdate - The optimistic update to apply.\n * @returns A new `ReactMutation` with the update configured.\n *\n * @public\n */\n withOptimisticUpdate<T extends OptimisticUpdate<FunctionArgs<Mutation>>>(\n optimisticUpdate: T &\n (ReturnType<T> extends Promise<any>\n ? \"Optimistic update handlers must be synchronous\"\n : {}),\n ): ReactMutation<Mutation>;\n}\n\n// Exported only for testing.\nexport function createMutation(\n mutationReference: FunctionReference<\"mutation\">,\n client: ConvexReactClient,\n update?: OptimisticUpdate<any>,\n): ReactMutation<any> {\n function mutation(args?: Record<string, Value>): Promise<unknown> {\n assertNotAccidentalArgument(args);\n\n return client.mutation(mutationReference, args, {\n optimisticUpdate: update,\n });\n }\n mutation.withOptimisticUpdate = function withOptimisticUpdate(\n optimisticUpdate: OptimisticUpdate<any>,\n ): ReactMutation<any> {\n if (update !== undefined) {\n throw new Error(\n `Already specified optimistic update for mutation ${getFunctionName(\n mutationReference,\n )}`,\n );\n }\n return createMutation(mutationReference, client, optimisticUpdate);\n };\n return mutation as ReactMutation<any>;\n}\n\n/**\n * An interface to execute a Convex action on the server.\n *\n * @public\n */\nexport interface ReactAction<Action extends FunctionReference<\"action\">> {\n /**\n * Execute the function on the server, returning a `Promise` of its return value.\n *\n * @param args - Arguments for the function to pass up to the server.\n * @returns The return value of the server-side function call.\n * @public\n */\n (...args: OptionalRestArgs<Action>): Promise<FunctionReturnType<Action>>;\n}\n\nfunction createAction(\n actionReference: FunctionReference<\"action\">,\n client: ConvexReactClient,\n): ReactAction<any> {\n return function (args?: Record<string, Value>): Promise<unknown> {\n return client.action(actionReference, args);\n } as ReactAction<any>;\n}\n\n// Watches should be stateless: in QueriesObserver we create a watch just to get\n// the current value.\n/**\n * A watch on the output of a Convex query function.\n *\n * @public\n */\nexport interface Watch<T> {\n /**\n * Initiate a watch on the output of a query.\n *\n * This will subscribe to this query and call\n * the callback whenever the query result changes.\n *\n * **Important: If the client is already subscribed to this query with the\n * same arguments this callback will not be invoked until the query result is\n * updated.** To get the current, local result call\n * {@link react.Watch.localQueryResult}.\n *\n * @param callback - Function that is called whenever the query result changes.\n * @returns - A function that disposes of the subscription.\n */\n onUpdate(callback: () => void): () => void;\n\n /**\n * Get the current result of a query.\n *\n * This will only return a result if we're already subscribed to the query\n * and have received a result from the server or the query value has been set\n * optimistically.\n *\n * @returns The result of the query or `undefined` if it isn't known.\n * @throws An error if the query encountered an error on the server.\n */\n localQueryResult(): T | undefined;\n\n /**\n * @internal\n */\n localQueryLogs(): string[] | undefined;\n\n /**\n * Get the current {@link browser.QueryJournal} for this query.\n *\n * If we have not yet received a result for this query, this will be `undefined`.\n */\n journal(): QueryJournal | undefined;\n}\n\n/**\n * A watch on the output of a paginated Convex query function.\n *\n * @public\n */\nexport interface PaginatedWatch<T> {\n /**\n * Initiate a watch on the output of a paginated query.\n *\n * This will subscribe to this query and call\n * the callback whenever the query result changes.\n *\n * @param callback - Function that is called whenever the query result changes.\n * @returns - A function that disposes of the subscription.\n */\n onUpdate(callback: () => void): () => void;\n\n /**\n * Get the current result of a paginated query.\n *\n * @returns The current results, status, and loadMore function, or `undefined` if not loaded.\n */\n localQueryResult():\n | {\n results: T[];\n status: PaginationStatus;\n loadMore: LoadMoreOfPaginatedQuery;\n }\n | undefined;\n}\n\n/**\n * Options for {@link ConvexReactClient.watchQuery}.\n *\n * @public\n */\nexport interface WatchQueryOptions {\n /**\n * An (optional) journal produced from a previous execution of this query\n * function.\n *\n * If there is an existing subscription to a query function with the same\n * name and arguments, this journal will have no effect.\n */\n journal?: QueryJournal;\n\n /**\n * @internal\n */\n componentPath?: string;\n}\n\n/**\n * Options for {@link ConvexReactClient.watchPaginatedQuery}.\n *\n * @internal\n */\nexport interface WatchPaginatedQueryOptions {\n /**\n * The initial number of items to load.\n */\n initialNumItems: number;\n\n // We may be able to remove this in the future, but to preserve the existing behavior of\n // usePaginatedQuery() it's still here.\n id: number;\n\n /**\n * @internal\n */\n componentPath?: string;\n}\n\n/**\n * Options for {@link ConvexReactClient.mutation}.\n *\n * @public\n */\nexport interface MutationOptions<Args extends Record<string, Value>> {\n /**\n * An optimistic update to apply along with this mutation.\n *\n * An optimistic update locally updates queries while a mutation is pending.\n * Once the mutation completes, the update will be rolled back.\n */\n optimisticUpdate?: OptimisticUpdate<Args> | undefined;\n}\n\n/**\n * Options for {@link ConvexReactClient}.\n *\n * @public\n */\nexport interface ConvexReactClientOptions extends BaseConvexClientOptions {}\n\n/**\n * A Convex client for use within React.\n *\n * This loads reactive queries and executes mutations over a WebSocket.\n *\n * @public\n */\nexport class ConvexReactClient {\n private address: string;\n private cachedSync?: BaseConvexClient | undefined;\n private cachedPaginatedQueryClient?: PaginatedQueryClient | undefined;\n private listeners: Map<QueryToken | PaginatedQueryToken, Set<() => void>>;\n private options: ConvexReactClientOptions;\n // \"closed\" means this client is done, not just that the underlying WS connection is closed.\n private closed = false;\n private _logger: Logger;\n\n private adminAuth?: string;\n private fakeUserIdentity?: UserIdentityAttributes | undefined;\n\n /**\n * @param address - The url of your Convex deployment, often provided\n * by an environment variable. E.g. `https://small-mouse-123.convex.cloud`.\n * @param options - See {@link ConvexReactClientOptions} for a full description.\n */\n constructor(address: string, options?: ConvexReactClientOptions) {\n // Validate address immediately since validation by the lazily-instantiated\n // internal client does not occur synchronously.\n if (address === undefined) {\n throw new Error(\n \"No address provided to ConvexReactClient.\\n\" +\n \"If trying to deploy to production, make sure to follow all the instructions found at https://docs.convex.dev/production/hosting/\\n\" +\n \"If running locally, make sure to run `convex dev` and ensure the .env.local file is populated.\",\n );\n }\n if (typeof address !== \"string\") {\n throw new Error(\n `ConvexReactClient requires a URL like 'https://happy-otter-123.convex.cloud', received something of type ${typeof address} instead.`,\n );\n }\n if (!address.includes(\"://\")) {\n throw new Error(\"Provided address was not an absolute URL.\");\n }\n this.address = address;\n this.listeners = new Map();\n this._logger =\n options?.logger === false\n ? instantiateNoopLogger({ verbose: options?.verbose ?? false })\n : options?.logger !== true && options?.logger\n ? options.logger\n : instantiateDefaultLogger({ verbose: options?.verbose ?? false });\n this.options = { ...options, logger: this._logger };\n }\n\n /**\n * Return the address for this client, useful for creating a new client.\n *\n * Not guaranteed to match the address with which this client was constructed:\n * it may be canonicalized.\n */\n get url() {\n return this.address;\n }\n\n /**\n * Lazily instantiate the `BaseConvexClient` so we don't create the WebSocket\n * when server-side rendering.\n *\n * @internal\n */\n get sync() {\n if (this.closed) {\n throw new Error(\"ConvexReactClient has already been closed.\");\n }\n if (this.cachedSync) {\n return this.cachedSync;\n }\n // BaseConvexClient and paginated query client are always created together.\n this.cachedSync = new BaseConvexClient(\n this.address,\n () => {}, // Use the PaginatedQueryClient's transition instead.\n this.options,\n );\n if (this.adminAuth) {\n this.cachedSync.setAdminAuth(this.adminAuth, this.fakeUserIdentity);\n }\n this.cachedPaginatedQueryClient = new PaginatedQueryClient(\n this.cachedSync,\n (transition) => this.handleTransition(transition),\n );\n return this.cachedSync;\n }\n\n /**\n * Lazily instantiate the `PaginatedQueryClient` so we don't create it\n * when server-side rendering.\n *\n * @internal\n */\n get paginatedQueryClient() {\n // access sync to instantiate the clients\n this.sync;\n if (this.cachedPaginatedQueryClient) {\n return this.cachedPaginatedQueryClient;\n }\n throw new Error(\"Should already be instantiated\");\n }\n\n /**\n * Set the authentication token to be used for subsequent queries and mutations.\n * `fetchToken` will be called automatically again if a token expires.\n * `fetchToken` should return `null` if the token cannot be retrieved, for example\n * when the user's rights were permanently revoked.\n * @param fetchToken - an async function returning the JWT-encoded OpenID Connect Identity Token\n * @param onChange - a callback that will be called when the authentication status changes\n */\n setAuth(\n fetchToken: AuthTokenFetcher,\n onChange?: (isAuthenticated: boolean) => void,\n ) {\n if (typeof fetchToken === \"string\") {\n throw new Error(\n \"Passing a string to ConvexReactClient.setAuth is no longer supported, \" +\n \"please upgrade to passing in an async function to handle reauthentication.\",\n );\n }\n this.sync.setAuth(\n fetchToken,\n onChange ??\n (() => {\n // Do nothing\n }),\n );\n }\n\n /**\n * Clear the current authentication token if set.\n */\n clearAuth() {\n this.sync.clearAuth();\n }\n\n /**\n * @internal\n */\n setAdminAuth(token: string, identity?: UserIdentityAttributes) {\n this.adminAuth = token;\n this.fakeUserIdentity = identity;\n if (this.closed) {\n throw new Error(\"ConvexReactClient has already been closed.\");\n }\n if (this.cachedSync) {\n this.sync.setAdminAuth(token, identity);\n }\n }\n\n /**\n * Construct a new {@link Watch} on a Convex query function.\n *\n * **Most application code should not call this method directly. Instead use\n * the {@link useQuery} hook.**\n *\n * The act of creating a watch does nothing, a Watch is stateless.\n *\n * @param query - A {@link server.FunctionReference} for the public query to run.\n * @param args - An arguments object for the query. If this is omitted,\n * the arguments will be `{}`.\n * @param options - A {@link WatchQueryOptions} options object for this query.\n *\n * @returns The {@link Watch} object.\n */\n watchQuery<Query extends FunctionReference<\"query\">>(\n query: Query,\n ...argsAndOptions: ArgsAndOptions<Query, WatchQueryOptions>\n ): Watch<FunctionReturnType<Query>> {\n const [args, options] = argsAndOptions;\n const name = getFunctionName(query);\n\n return {\n onUpdate: (callback) => {\n const { queryToken, unsubscribe } = this.sync.subscribe(\n name as string,\n args,\n options,\n );\n\n const currentListeners = this.listeners.get(queryToken);\n if (currentListeners !== undefined) {\n currentListeners.add(callback);\n } else {\n this.listeners.set(queryToken, new Set([callback]));\n }\n\n return () => {\n if (this.closed) {\n return;\n }\n\n const currentListeners = this.listeners.get(queryToken)!;\n currentListeners.delete(callback);\n if (currentListeners.size === 0) {\n this.listeners.delete(queryToken);\n }\n unsubscribe();\n };\n },\n\n localQueryResult: () => {\n // Use the cached client because we can't have a query result if we don't\n // even have a client yet!\n if (this.cachedSync) {\n return this.cachedSync.localQueryResult(name, args);\n }\n return undefined;\n },\n\n localQueryLogs: () => {\n if (this.cachedSync) {\n return this.cachedSync.localQueryLogs(name, args);\n }\n return undefined;\n },\n\n journal: () => {\n if (this.cachedSync) {\n return this.cachedSync.queryJournal(name, args);\n }\n return undefined;\n },\n };\n }\n\n // Let's try out a queryOptions-style API.\n // This method is similar to the React Query API `queryClient.prefetchQuery()`.\n // In the future an ensureQueryData(): Promise<Data> method could exist.\n /**\n * Indicates likely future interest in a query subscription.\n *\n * The implementation currently immediately subscribes to a query. In the future this method\n * may prioritize some queries over others, fetch the query result without subscribing, or\n * do nothing in slow network connections or high load scenarios.\n *\n * To use this in a React component, call useQuery() and ignore the return value.\n *\n * @param queryOptions - A query (function reference from an api object) and its args, plus\n * an optional extendSubscriptionFor for how long to subscribe to the query.\n */\n prewarmQuery<Query extends FunctionReference<\"query\">>(\n queryOptions: QueryOptions<Query> & { extendSubscriptionFor?: number },\n ) {\n const extendSubscriptionFor =\n queryOptions.extendSubscriptionFor ?? DEFAULT_EXTEND_SUBSCRIPTION_FOR;\n const watch = this.watchQuery(queryOptions.query, queryOptions.args || {});\n const unsubscribe = watch.onUpdate(() => {});\n setTimeout(unsubscribe, extendSubscriptionFor);\n }\n\n /**\n * Construct a new {@link PaginatedWatch} on a Convex paginated query function.\n *\n * **Most application code should not call this method directly. Instead use\n * the {@link usePaginatedQuery} hook.**\n *\n * The act of creating a watch does nothing, a Watch is stateless.\n *\n * @param query - A {@link server.FunctionReference} for the public query to run.\n * @param args - An arguments object for the query. If this is omitted,\n * the arguments will be `{}`.\n * @param options - A {@link WatchPaginatedQueryOptions} options object for this query.\n *\n * @returns The {@link PaginatedWatch} object.\n *\n * @internal\n */\n watchPaginatedQuery<Query extends FunctionReference<\"query\">>(\n query: Query,\n args: Query[\"_args\"],\n options: WatchPaginatedQueryOptions,\n ): PaginatedWatch<FunctionReturnType<Query>> {\n const name = getFunctionName(query);\n\n return {\n onUpdate: (callback) => {\n const { paginatedQueryToken, unsubscribe } =\n this.paginatedQueryClient.subscribe(name, args || {}, options);\n\n const currentListeners = this.listeners.get(paginatedQueryToken);\n if (currentListeners !== undefined) {\n currentListeners.add(callback);\n } else {\n this.listeners.set(paginatedQueryToken, new Set([callback]));\n }\n\n return () => {\n if (this.closed) {\n return;\n }\n\n const currentListeners = this.listeners.get(paginatedQueryToken)!;\n currentListeners.delete(callback);\n if (currentListeners.size === 0) {\n this.listeners.delete(paginatedQueryToken);\n }\n unsubscribe();\n };\n },\n\n localQueryResult: () => {\n // Use our new paginated query client\n return this.paginatedQueryClient.localQueryResult(name, args, options);\n },\n };\n }\n\n /**\n * Execute a mutation function.\n *\n * @param mutation - A {@link server.FunctionReference} for the public mutation\n * to run.\n * @param args - An arguments object for the mutation. If this is omitted,\n * the arguments will be `{}`.\n * @param options - A {@link MutationOptions} options object for the mutation.\n * @returns A promise of the mutation's result.\n */\n mutation<Mutation extends FunctionReference<\"mutation\">>(\n mutation: Mutation,\n ...argsAndOptions: ArgsAndOptions<\n Mutation,\n MutationOptions<FunctionArgs<Mutation>>\n >\n ): Promise<FunctionReturnType<Mutation>> {\n const [args, options] = argsAndOptions;\n const name = getFunctionName(mutation);\n return this.sync.mutation(name, args, options);\n }\n\n /**\n * Execute an action function.\n *\n * @param action - A {@link server.FunctionReference} for the public action\n * to run.\n * @param args - An arguments object for the action. If this is omitted,\n * the arguments will be `{}`.\n * @returns A promise of the action's result.\n */\n action<Action extends FunctionReference<\"action\">>(\n action: Action,\n ...args: OptionalRestArgs<Action>\n ): Promise<FunctionReturnType<Action>> {\n const name = getFunctionName(action);\n return this.sync.action(name, ...args);\n }\n\n /**\n * Fetch a query result once.\n *\n * **Most application code should subscribe to queries instead, using\n * the {@link useQuery} hook.**\n *\n * @param query - A {@link server.FunctionReference} for the public query\n * to run.\n * @param args - An arguments object for the query. If this is omitted,\n * the arguments will be `{}`.\n * @returns A promise of the query's result.\n */\n query<Query extends FunctionReference<\"query\">>(\n query: Query,\n ...args: OptionalRestArgs<Query>\n ): Promise<FunctionReturnType<Query>> {\n const watch = this.watchQuery(query, ...args);\n const existingResult = watch.localQueryResult();\n if (existingResult !== undefined) {\n return Promise.resolve(existingResult);\n }\n return new Promise((resolve, reject) => {\n const unsubscribe = watch.onUpdate(() => {\n unsubscribe();\n try {\n resolve(watch.localQueryResult());\n } catch (e) {\n reject(e);\n }\n });\n });\n }\n\n /**\n * Get the current {@link ConnectionState} between the client and the Convex\n * backend.\n *\n * @returns The {@link ConnectionState} with the Convex backend.\n */\n connectionState(): ConnectionState {\n return this.sync.connectionState();\n }\n\n /**\n * Subscribe to the {@link ConnectionState} between the client and the Convex\n * backend, calling a callback each time it changes.\n *\n * Subscribed callbacks will be called when any part of ConnectionState changes.\n * ConnectionState may grow in future versions (e.g. to provide a array of\n * inflight requests) in which case callbacks would be called more frequently.\n * ConnectionState may also *lose* properties in future versions as we figure\n * out what information is most useful. As such this API is considered unstable.\n *\n * @returns An unsubscribe function to stop listening.\n */\n subscribeToConnectionState(\n cb: (connectionState: ConnectionState) => void,\n ): () => void {\n return this.sync.subscribeToConnectionState(cb);\n }\n\n /**\n * Get the logger for this client.\n *\n * @returns The {@link Logger} for this client.\n */\n get logger(): Logger {\n return this._logger;\n }\n\n /**\n * Close any network handles associated with this client and stop all subscriptions.\n *\n * Call this method when you're done with a {@link ConvexReactClient} to\n * dispose of its sockets and resources.\n *\n * @returns A `Promise` fulfilled when the connection has been completely closed.\n */\n async close(): Promise<void> {\n this.closed = true;\n // Prevent outstanding React batched updates from invoking listeners.\n this.listeners = new Map();\n if (this.cachedPaginatedQueryClient) {\n this.cachedPaginatedQueryClient = undefined;\n }\n if (this.cachedSync) {\n const sync = this.cachedSync;\n this.cachedSync = undefined;\n await sync.close();\n }\n }\n\n /**\n * Handle transitions from both base client and paginated client.\n * This ensures all transitions are processed synchronously and in order.\n */\n private handleTransition(transition: ExtendedTransition) {\n const simple = transition.queries.map((q) => q.token);\n const paginated = transition.paginatedQueries.map((q) => q.token);\n this.transition([...simple, ...paginated]);\n }\n\n private transition(updatedQueries: (QueryToken | PaginatedQueryToken)[]) {\n for (const queryToken of updatedQueries) {\n const callbacks = this.listeners.get(queryToken);\n if (callbacks) {\n for (const callback of callbacks) {\n callback();\n }\n }\n }\n }\n}\n\nconst ConvexContext = React.createContext<ConvexReactClient>(\n undefined as unknown as ConvexReactClient, // in the future this will be a mocked client for testing\n);\n\n/**\n * Get the {@link ConvexReactClient} within a React component.\n *\n * This relies on the {@link ConvexProvider} being above in the React component tree.\n *\n * @returns The active {@link ConvexReactClient} object, or `undefined`.\n *\n * @public\n */\nexport function useConvex(): ConvexReactClient {\n return useContext(ConvexContext);\n}\n\n/**\n * Provides an active Convex {@link ConvexReactClient} to descendants of this component.\n *\n * Wrap your app in this component to use Convex hooks `useQuery`,\n * `useMutation`, and `useConvex`.\n *\n * @param props - an object with a `client` property that refers to a {@link ConvexReactClient}.\n *\n * @public\n */\nexport const ConvexProvider: React.FC<{\n client: ConvexReactClient;\n children?: React.ReactNode;\n}> = ({ client, children }) => {\n return React.createElement(\n ConvexContext.Provider,\n { value: client },\n children,\n );\n};\n\nexport type OptionalRestArgsOrSkip<FuncRef extends FunctionReference<any>> =\n FuncRef[\"_args\"] extends EmptyObject\n ? [args?: EmptyObject | \"skip\"]\n : [args: FuncRef[\"_args\"] | \"skip\"];\n\n/**\n * Result returned by object-form {@link useQuery_experimental}.\n *\n * @public\n */\nexport type UseQueryResult<QueryResult, ThrowOnError extends boolean = false> =\n | { status: \"pending\" }\n | { status: \"success\"; data: QueryResult }\n | (ThrowOnError extends true ? never : { status: \"error\"; error: Error });\n\ntype UseQueryOptions<\n Query extends FunctionReference<\"query\">,\n ThrowOnError extends boolean,\n> = {\n query: Query;\n args: FunctionArgs<Query> | \"skip\";\n throwOnError?: ThrowOnError;\n};\n\n/**\n * Load a reactive query within a React component.\n *\n * This React hook subscribes to a Convex query and causes a rerender whenever\n * the query result changes. The subscription is managed automatically --\n * it starts when the component mounts and stops when it unmounts.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @example\n * ```tsx\n * import { useQuery } from \"convex/react\";\n * import { api } from \"../convex/_generated/api\";\n *\n * function TaskList() {\n * // Reactively loads tasks, re-renders when data changes:\n * const tasks = useQuery(api.tasks.list, { completed: false });\n *\n * // Returns `undefined` while loading:\n * if (tasks === undefined) return <div>Loading...</div>;\n *\n * return tasks.map((task) => <div key={task._id}>{task.text}</div>);\n * }\n *\n * // Pass \"skip\" to conditionally disable the query:\n * function MaybeProfile({ userId }: { userId?: Id<\"users\"> }) {\n * const profile = useQuery(\n * api.users.get,\n * userId ? { userId } : \"skip\",\n * );\n * // ...\n * }\n * ```\n *\n * @param query - a {@link server.FunctionReference} for the public query to run\n * like `api.dir1.dir2.filename.func`.\n * @param args - The arguments to the query function or the string `\"skip\"` if the\n * query should not be loaded.\n * @returns the result of the query. Returns `undefined` while loading.\n *\n * @see https://docs.convex.dev/client/react#fetching-data\n * @public\n */\nexport function useQuery<Query extends FunctionReference<\"query\">>(\n query: Query,\n ...args: OptionalRestArgsOrSkip<Query>\n): Query[\"_returnType\"] | undefined {\n const skip = args[0] === \"skip\";\n const argsObject = args[0] === \"skip\" ? {} : parseArgs(args[0]);\n const queryReference =\n typeof query === \"string\"\n ? makeFunctionReference<\"query\", any, any>(query)\n : query;\n\n const queryName = getFunctionName(queryReference);\n\n const queries = useMemo(\n () =>\n skip\n ? ({} as RequestForQueries)\n : { query: { query: queryReference, args: argsObject } },\n // Stringify args so args that are semantically the same don't trigger a\n // rerender. Saves developers from adding `useMemo` on every args usage.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(convexToJson(argsObject)), queryName, skip],\n );\n\n const results = useQueries(queries);\n const result = results[\"query\"];\n\n if (result instanceof Error) {\n throw result;\n }\n return result;\n}\n\n/**\n * Load a reactive query within a React component using an options object.\n *\n * This is an experimental form of {@link useQuery} that accepts a single\n * {@link UseQueryOptions} object instead of positional arguments.\n *\n * Consumers are expected to check the returned object `status` field to\n * make proper use of the result. If an error occurs, it will be present\n * in the result object unless `throwOnError` is `true`, in which case\n * the error will be thrown instead.\n *\n * @example\n * ```tsx\n * import { useQuery_experimental as useQuery } from \"convex/react\";\n * import { api } from \"../convex/_generated/api\";\n *\n * function TaskList() {\n * const state = useQuery({ query: api.tasks.list, args: { completed: false } });\n *\n * if (state.status === \"pending\") return <div>Loading...</div>;\n * if (state.status === \"error\") return <div>Error: {state.error.message}</div>;\n * return state.data.map((task) => <div key={task._id}>{task.text}</div>);\n * }\n * ```\n *\n * @param options - Query options. Pass `args: \"skip\"` to disable the query.\n * @returns the current query state as a {@link UseQueryResult} object.\n *\n * @see https://docs.convex.dev/client/react#fetching-data\n * @public\n */\nexport function useQuery_experimental<\n Query extends FunctionReference<\"query\">,\n ThrowOnError extends boolean = false,\n>(\n options: UseQueryOptions<Query, ThrowOnError>,\n): UseQueryResult<Query[\"_returnType\"], ThrowOnError>;\n\nexport function useQuery_experimental<\n Query extends FunctionReference<\"query\">,\n ThrowOnError extends boolean = false,\n>(\n options: UseQueryOptions<Query, ThrowOnError>,\n): UseQueryResult<Query[\"_returnType\"], false> {\n const throwOnError = options.throwOnError ?? false;\n const queryReference =\n typeof options.query === \"string\"\n ? (makeFunctionReference<\"query\", any, any>(options.query) as Query)\n : options.query;\n const skip = options.args === \"skip\";\n const argsObject = !skip\n ? parseArgs(options.args as Record<string, Value>)\n : {};\n\n const queryName = getFunctionName(queryReference);\n const queries = useMemo(\n () =>\n skip\n ? ({} as RequestForQueries)\n : { query: { query: queryReference, args: argsObject } },\n // Stringify args so args that are semantically the same don't trigger a\n // rerender. Saves developers from adding `useMemo` on every args usage.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(convexToJson(argsObject)), queryName, skip],\n );\n\n const results = useQueries(queries);\n const result = results[\"query\"];\n\n if (result instanceof Error) {\n if (throwOnError) {\n throw result;\n }\n return {\n error: result,\n status: \"error\",\n };\n }\n\n if (result === undefined) {\n return {\n status: \"pending\",\n };\n }\n\n return {\n data: result,\n status: \"success\",\n };\n}\n\n/**\n * Construct a new {@link ReactMutation}.\n *\n * Returns a function that you can call to execute a Convex mutation. The\n * returned function is stable across renders (same reference identity), so\n * it can be safely used in dependency arrays and memoization.\n *\n * Mutations can optionally be configured with\n * [optimistic updates](https://docs.convex.dev/client/react/optimistic-updates)\n * for instant UI feedback.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @example\n * ```tsx\n * import { useMutation } from \"convex/react\";\n * import { api } from \"../convex/_generated/api\";\n *\n * function CreateTask() {\n * const createTask = useMutation(api.tasks.create);\n *\n * const handleClick = async () => {\n * await createTask({ text: \"New task\" });\n * };\n *\n * return <button onClick={handleClick}>Add Task</button>;\n * }\n * ```\n *\n * @param mutation - A {@link server.FunctionReference} for the public mutation\n * to run like `api.dir1.dir2.filename.func`.\n * @returns The {@link ReactMutation} object with that name.\n *\n * @see https://docs.convex.dev/client/react#editing-data\n * @public\n */\nexport function useMutation<Mutation extends FunctionReference<\"mutation\">>(\n mutation: Mutation,\n): ReactMutation<Mutation> {\n const mutationReference =\n typeof mutation === \"string\"\n ? makeFunctionReference<\"mutation\", any, any>(mutation)\n : mutation;\n\n const convex = useContext(ConvexContext);\n if (convex === undefined) {\n throw new Error(\n \"Could not find Convex client! `useMutation` must be used in the React component \" +\n \"tree under `ConvexProvider`. Did you forget it? \" +\n \"See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app\",\n );\n }\n return useMemo(\n () => createMutation(mutationReference, convex),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [convex, getFunctionName(mutationReference)],\n );\n}\n\n/**\n * Construct a new {@link ReactAction}.\n *\n * Returns a function that you can call to execute a Convex action. Actions\n * can call third-party APIs and perform side effects. The returned function\n * is stable across renders (same reference identity).\n *\n * **Error handling:** Actions can fail (e.g., if an external API is down).\n * Always wrap action calls in try/catch or handle the rejected promise.\n *\n * **Note:** In most cases, calling an action directly from a client is an\n * anti-pattern. Prefer having the client call a mutation that captures the\n * user's intent (by writing to the database) and then schedules the action\n * via `ctx.scheduler.runAfter`. This ensures the intent is durably recorded\n * even if the client disconnects.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @example\n * ```tsx\n * import { useAction } from \"convex/react\";\n * import { api } from \"../convex/_generated/api\";\n *\n * function GenerateSummary() {\n * const generate = useAction(api.ai.generateSummary);\n *\n * const handleClick = async () => {\n * try {\n * const summary = await generate({ text: \"Some long text...\" });\n * console.log(summary);\n * } catch (error) {\n * console.error(\"Action failed:\", error);\n * }\n * };\n *\n * return <button onClick={handleClick}>Generate</button>;\n * }\n * ```\n *\n * @param action - A {@link server.FunctionReference} for the public action\n * to run like `api.dir1.dir2.filename.func`.\n * @returns The {@link ReactAction} object with that name.\n *\n * @see https://docs.convex.dev/functions/actions#calling-actions-from-clients\n * @public\n */\nexport function useAction<Action extends FunctionReference<\"action\">>(\n action: Action,\n): ReactAction<Action> {\n const convex = useContext(ConvexContext);\n const actionReference =\n typeof action === \"string\"\n ? makeFunctionReference<\"action\", any, any>(action)\n : action;\n\n if (convex === undefined) {\n throw new Error(\n \"Could not find Convex client! `useAction` must be used in the React component \" +\n \"tree under `ConvexProvider`. Did you forget it? \" +\n \"See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app\",\n );\n }\n return useMemo(\n () => createAction(actionReference, convex),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [convex, getFunctionName(actionReference)],\n );\n}\n\n/**\n * React hook to get the current {@link ConnectionState} and subscribe to changes.\n *\n * This hook returns the current connection state and automatically rerenders\n * when any part of the connection state changes (e.g., when going online/offline,\n * when requests start/complete, etc.).\n *\n * The shape of ConnectionState may change in the future which may cause this\n * hook to rerender more frequently.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @returns The current {@link ConnectionState} with the Convex backend.\n *\n * @public\n */\nexport function useConvexConnectionState(): ConnectionState {\n const convex = useContext(ConvexContext);\n if (convex === undefined) {\n throw new Error(\n \"Could not find Convex client! `useConvexConnectionState` must be used in the React component \" +\n \"tree under `ConvexProvider`. Did you forget it? \" +\n \"See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app\",\n );\n }\n\n const getCurrentValue = useCallback(() => {\n return convex.connectionState();\n }, [convex]);\n\n const subscribe = useCallback(\n (callback: () => void) => {\n return convex.subscribeToConnectionState(() => {\n callback();\n });\n },\n [convex],\n );\n\n return useSubscription({ getCurrentValue, subscribe });\n}\n\n// When a function is called with a single argument that looks like a\n// React SyntheticEvent it was likely called as an event handler.\nfunction assertNotAccidentalArgument(value: any) {\n // these are properties of a React.SyntheticEvent\n // https://reactjs.org/docs/events.html\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"bubbles\" in value &&\n \"persist\" in value &&\n \"isDefaultPrevented\" in value\n ) {\n throw new Error(\n `Convex function called with SyntheticEvent object. Did you use a Convex function as an event handler directly? Event handlers like onClick receive an event object as their first argument. These SyntheticEvent objects are not valid Convex values. Try wrapping the function like \\`const handler = () => myMutation();\\` and using \\`handler\\` in the event handler.`,\n );\n }\n}\n", "import { useEffect, useState } from \"react\";\n\n/*\nThis code is taken from https://gist.github.com/bvaughn/e25397f70e8c65b0ae0d7c90b731b189\nbecause correct subscriptions in async React is complex!\n\nIt could probably be replaced with `useSyncExternalStore()`.\n\nThe MIT License (MIT)\nCopyright \u00A9 2023 Brian Vaughn\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \u201CSoftware\u201D), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \u201CAS IS\u201D, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n/**\n * Hook used for safely managing subscriptions in concurrent mode.\n *\n * In order to avoid removing and re-adding subscriptions each time this hook is called,\n * the parameters passed to this hook should be memoized in some way\u2013\n * either by wrapping the entire params object with useMemo()\n * or by wrapping the individual callbacks with useCallback().\n *\n * @internal\n */\nexport function useSubscription<Value>({\n // (Synchronously) returns the current value of our subscription.\n getCurrentValue,\n\n // This function is passed an event handler to attach to the subscription.\n // It should return an unsubscribe function that removes the handler.\n subscribe,\n}: {\n getCurrentValue: () => Value;\n subscribe: (callback: () => void) => () => void;\n}): Value {\n // Read the current value from our subscription.\n // When this value changes, we'll schedule an update with React.\n // It's important to also store the hook params so that we can check for staleness.\n // (See the comment in checkForUpdates() below for more info.)\n const [state, setState] = useState(() => ({\n getCurrentValue,\n subscribe,\n value: getCurrentValue(),\n }));\n\n let valueToReturn = state.value;\n\n // If parameters have changed since our last render, schedule an update with its current value.\n if (\n state.getCurrentValue !== getCurrentValue ||\n state.subscribe !== subscribe\n ) {\n // If the subscription has been updated, we'll schedule another update with React.\n // React will process this update immediately, so the old subscription value won't be committed.\n // It is still nice to avoid returning a mismatched value though, so let's override the return value.\n valueToReturn = getCurrentValue();\n\n setState({\n getCurrentValue,\n subscribe,\n value: valueToReturn,\n });\n }\n\n // It is important not to subscribe while rendering because this can lead to memory leaks.\n // (Learn more at reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects)\n // Instead, we wait until the commit phase to attach our handler.\n //\n // We intentionally use a passive effect (useEffect) rather than a synchronous one (useLayoutEffect)\n // so that we don't stretch the commit phase.\n // This also has an added benefit when multiple components are subscribed to the same source:\n // It allows each of the event handlers to safely schedule work without potentially removing an another handler.\n // (Learn more at https://codesandbox.io/s/k0yvr5970o)\n useEffect(() => {\n let didUnsubscribe = false;\n\n const checkForUpdates = () => {\n // It's possible that this callback will be invoked even after being unsubscribed,\n // if it's removed as a result of a subscription event/update.\n // In this case, React will log a DEV warning about an update from an unmounted component.\n // We can avoid triggering that warning with this check.\n if (didUnsubscribe) {\n return;\n }\n\n setState((prevState) => {\n // Ignore values from stale sources!\n // Since we subscribe an unsubscribe in a passive effect,\n // it's possible that this callback will be invoked for a stale (previous) subscription.\n // This check avoids scheduling an update for that stale subscription.\n if (\n prevState.getCurrentValue !== getCurrentValue ||\n prevState.subscribe !== subscribe\n ) {\n return prevState;\n }\n\n // Some subscriptions will auto-invoke the handler, even if the value hasn't changed.\n // If the value hasn't changed, no update is needed.\n // Return state as-is so React can bail out and avoid an unnecessary render.\n const value = getCurrentValue();\n if (prevState.value === value) {\n return prevState;\n }\n\n return { ...prevState, value };\n });\n };\n const unsubscribe = subscribe(checkForUpdates);\n\n // Because we're subscribing in a passive effect,\n // it's possible that an update has occurred between render and our effect handler.\n // Check for this and schedule an update if work has occurred.\n checkForUpdates();\n\n return () => {\n didUnsubscribe = true;\n unsubscribe();\n };\n }, [getCurrentValue, subscribe]);\n\n // Return the current value for our caller to use while rendering.\n return valueToReturn;\n}\n", "import { convexToJson, Value } from \"../values/index.js\";\nimport { PaginatedWatch, Watch } from \"./client.js\";\nimport { QueryJournal } from \"../browser/sync/protocol.js\";\nimport { FunctionReference, getFunctionName } from \"../server/api.js\";\nimport { RequestForQueries } from \"./use_queries.js\";\nimport { PaginatedQueryResult } from \"../browser/sync/pagination.js\";\nimport { SubscribeToPaginatedQueryOptions } from \"../browser/sync/paginated_query_client.js\";\n\ntype Identifier = string;\n\ntype QueryInfo = {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n watch: Watch<Value> | PaginatedWatch<Value>;\n unsubscribe: () => void;\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n};\n\nexport interface CreateWatch {\n (\n query: FunctionReference<\"query\">,\n args: Record<string, Value>,\n options: {\n journal?: QueryJournal;\n // Just the existence of this option makes this a paginated query\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n },\n ): Watch<Value> | PaginatedWatch<Value>;\n}\n\n/**\n * A class for observing the results of multiple queries at the same time.\n *\n * Any time the result of a query changes, the listeners are notified.\n */\nexport class QueriesObserver {\n public createWatch: CreateWatch;\n private queries: Record<Identifier, QueryInfo>;\n private listeners: Set<() => void>;\n\n constructor(createWatch: CreateWatch) {\n this.createWatch = createWatch;\n this.queries = {};\n this.listeners = new Set();\n }\n\n setQueries(\n newQueries: Record<\n Identifier,\n {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n }\n >,\n ) {\n // Add the new queries before unsubscribing from the old ones so that\n // the deduping in the `ConvexReactClient` can help if there are duplicates.\n for (const identifier of Object.keys(newQueries)) {\n const { query, args, paginationOptions } = newQueries[identifier];\n // Might throw\n getFunctionName(query);\n\n if (this.queries[identifier] === undefined) {\n // No existing query => add it.\n this.addQuery(\n identifier,\n query,\n args,\n paginationOptions ? { paginationOptions } : {},\n );\n } else {\n const existingInfo = this.queries[identifier];\n\n if (\n getFunctionName(query) !== getFunctionName(existingInfo.query) ||\n JSON.stringify(convexToJson(args)) !==\n JSON.stringify(convexToJson(existingInfo.args)) ||\n JSON.stringify(paginationOptions) !==\n JSON.stringify(existingInfo.paginationOptions)\n ) {\n // Existing query that doesn't match => remove the old and add the new.\n this.removeQuery(identifier);\n this.addQuery(\n identifier,\n query,\n args,\n paginationOptions ? { paginationOptions } : {},\n );\n }\n }\n }\n\n // Prune all the existing queries that we no longer need.\n for (const identifier of Object.keys(this.queries)) {\n if (newQueries[identifier] === undefined) {\n this.removeQuery(identifier);\n }\n }\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n getLocalResults(\n queries: RequestForQueries,\n ): Record<\n Identifier,\n Value | undefined | Error | PaginatedQueryResult<Value>\n > {\n const result: Record<\n Identifier,\n Value | Error | undefined | PaginatedQueryResult<Value>\n > = {};\n for (const identifier of Object.keys(queries)) {\n const { query, args } = queries[identifier];\n const paginationOptions = queries[identifier].paginationOptions;\n\n // Might throw\n getFunctionName(query);\n\n // Note: We're not gonna watch, we could save some allocations\n // by getting a reference to the client directly instead.\n const watch = this.createWatch(\n query,\n args,\n paginationOptions ? { paginationOptions } : {},\n );\n\n let value: Value | undefined | Error | PaginatedQueryResult<Value>;\n try {\n value = watch.localQueryResult();\n } catch (e) {\n // Only collect instances of `Error` because thats how callers\n // will distinguish errors from normal results.\n if (e instanceof Error) {\n value = e;\n } else {\n throw e;\n }\n }\n result[identifier] = value;\n }\n return result;\n }\n\n setCreateWatch(createWatch: CreateWatch) {\n this.createWatch = createWatch;\n // If we have a new watch, we might be using a new Convex client.\n // Recreate all the watches being careful to preserve the journals.\n for (const identifier of Object.keys(this.queries)) {\n const { query, args, watch, paginationOptions } =\n this.queries[identifier];\n const journal = \"journal\" in watch ? watch.journal() : undefined;\n this.removeQuery(identifier);\n this.addQuery(identifier, query, args, {\n ...(journal ? { journal } : []),\n ...(paginationOptions ? { paginationOptions } : {}),\n });\n }\n }\n\n destroy() {\n for (const identifier of Object.keys(this.queries)) {\n this.removeQuery(identifier);\n }\n this.listeners = new Set();\n }\n\n private addQuery(\n identifier: Identifier,\n query: FunctionReference<\"query\">,\n args: Record<string, Value>,\n {\n paginationOptions,\n journal,\n }: {\n paginationOptions?: SubscribeToPaginatedQueryOptions;\n journal?: QueryJournal;\n },\n ) {\n if (this.queries[identifier] !== undefined) {\n throw new Error(\n `Tried to add a new query with identifier ${identifier} when it already exists.`,\n );\n }\n const watch = this.createWatch(query, args, {\n ...(journal ? { journal } : []),\n ...(paginationOptions ? { paginationOptions } : {}),\n });\n const unsubscribe = watch.onUpdate(() => this.notifyListeners());\n this.queries[identifier] = {\n query,\n args,\n watch,\n unsubscribe,\n ...(paginationOptions ? { paginationOptions } : {}),\n };\n }\n\n private removeQuery(identifier: Identifier) {\n const info = this.queries[identifier];\n if (info === undefined) {\n throw new Error(`No query found with identifier ${identifier}.`);\n }\n info.unsubscribe();\n delete this.queries[identifier];\n }\n\n private notifyListeners(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n", "import { useState } from \"react\";\n\nimport { FunctionReference, getFunctionName } from \"../server/api.js\";\nimport {\n PaginatedQueryReference,\n PaginatedQueryArgs,\n PaginatedQueryItem,\n UsePaginatedQueryReturnType,\n} from \"./use_paginated_query.js\";\nimport { convexToJson, Value } from \"../values/value.js\";\nimport { useQueries } from \"./use_queries.js\";\nimport { PaginatedQueryResult } from \"../browser/sync/pagination.js\";\nimport { SubscribeToPaginatedQueryOptions } from \"../browser/sync/paginated_query_client.js\";\nimport { ConvexError } from \"../values/errors.js\";\nimport { useConvex } from \"./client.js\";\n\n/**\n * Options for object-form {@link usePaginatedQuery_experimental}.\n *\n * @public\n */\nexport type UsePaginatedQueryOptions<\n Query extends PaginatedQueryReference,\n ThrowOnError extends boolean = false,\n> = {\n query: Query;\n args: PaginatedQueryArgs<Query> | \"skip\";\n initialNumItems: number;\n /**\n * When `true` (default for positional form), errors are thrown and caught\n * by an error boundary. When `false` (default for object form), errors are\n * returned as `{ status: \"Error\", error: Error }` instead of being thrown.\n */\n throwOnError?: ThrowOnError;\n};\n\n/**\n * Return type of the object-form {@link usePaginatedQuery_experimental} overload.\n *\n * Uses lowercase query status (`\"pending\" | \"success\" | \"error\"`) and a\n * `canLoadMore` boolean instead of the TitleCase pagination status strings\n * used by the positional form.\n *\n * @public\n */\nexport type UsePaginatedQueryObjectReturnType<\n Query extends PaginatedQueryReference,\n ThrowOnError extends boolean = false,\n> =\n | {\n data: PaginatedQueryItem<Query>[] | undefined;\n status: \"pending\";\n canLoadMore: false;\n isLoading: true;\n error: undefined;\n loadMore: (numItems: number) => void;\n }\n | {\n data: PaginatedQueryItem<Query>[];\n status: \"success\";\n canLoadMore: boolean;\n isLoading: false;\n error: undefined;\n loadMore: (numItems: number) => void;\n }\n | (ThrowOnError extends true\n ? never\n : {\n data: PaginatedQueryItem<Query>[];\n status: \"error\";\n canLoadMore: false;\n isLoading: false;\n error: Error;\n loadMore: (numItems: number) => void;\n });\n\ntype UsePaginatedQueryState = {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n id: number;\n queries: {\n paginatedQuery?: {\n query: FunctionReference<\"query\">;\n args: Record<string, Value>;\n paginationOptions: SubscribeToPaginatedQueryOptions;\n };\n };\n skip: boolean;\n};\n\n/**\n * Experimental new usePaginatedQuery implementation that will replace the current one\n * in the future.\n *\n * Load data reactively from a paginated query to a create a growing list.\n *\n * This is an alternate implementation that relies on new client pagination logic.\n *\n * This can be used to power \"infinite scroll\" UIs.\n *\n * This hook must be used with public query references that match\n * {@link PaginatedQueryReference}.\n *\n * `usePaginatedQuery` concatenates all the pages of results into a single list\n * and manages the continuation cursors when requesting more items.\n *\n * Example usage:\n * ```typescript\n * const { results, status, isLoading, loadMore } = usePaginatedQuery(\n * api.messages.list,\n * { channel: \"#general\" },\n * { initialNumItems: 5 }\n * );\n * ```\n *\n * If the query reference or arguments change, the pagination state will be reset\n * to the first page. Similarly, if any of the pages result in an InvalidCursor\n * error or an error associated with too much data, the pagination state will also\n * reset to the first page.\n *\n * To learn more about pagination, see [Paginated Queries](https://docs.convex.dev/database/pagination).\n *\n * @param query - A FunctionReference to the public query function to run.\n * @param args - The arguments object for the query function, excluding\n * the `paginationOpts` property. That property is injected by this hook.\n * @param options - An object specifying the `initialNumItems` to be loaded in\n * the first page.\n * @returns A {@link UsePaginatedQueryResult} that includes the currently loaded\n * items, the status of the pagination, and a `loadMore` function.\n *\n * @public\n */\nexport function usePaginatedQuery_experimental<\n Query extends PaginatedQueryReference,\n>(\n query: Query,\n args: PaginatedQueryArgs<Query> | \"skip\",\n // Future options this hook might accept:\n // - maximumRowsRead\n // - maximumBytesRead\n // - a cursor for where to start? although probably no endCursor\n options: { initialNumItems: number },\n): UsePaginatedQueryReturnType<Query>;\n\n/**\n * Experimental new usePaginatedQuery implementation that accepts an options object\n * rather than positional arguments.\n *\n * @param options - A {@link UsePaginatedQueryOptions} object including `query` and `args`.\n * @returns A {@link UsePaginatedQueryObjectReturnType} object with `data`, `status`,\n * `canLoadMore`, `isLoading`, `error`, and `loadMore`. `status` is `\"pending\"` while\n * loading, `\"success\"` when data is available, or `\"error\"` if the query threw.\n * When `throwOnError` is `true`, the `\"error\"` status is excluded from the return\n * type since errors will be thrown instead.\n * `canLoadMore` is `true` only when idle and more pages exist.\n *\n * @public\n */\nexport function usePaginatedQuery_experimental<\n Query extends PaginatedQueryReference,\n ThrowOnError extends boolean = false,\n>(\n options: UsePaginatedQueryOptions<Query, ThrowOnError>,\n): UsePaginatedQueryObjectReturnType<Query, ThrowOnError>;\n\nexport function usePaginatedQuery_experimental<\n Query extends PaginatedQueryReference,\n>(\n queryOrOptions: Query | UsePaginatedQueryOptions<Query>,\n args?: PaginatedQueryArgs<Query> | \"skip\",\n // Future options this hook might accept:\n // - maximumRowsRead\n // - maximumBytesRead\n // - a cursor for where to start? although probably no endCursor\n options?: { initialNumItems: number },\n):\n | UsePaginatedQueryReturnType<Query>\n | UsePaginatedQueryObjectReturnType<Query> {\n const isObjectOptions =\n typeof queryOrOptions === \"object\" &&\n queryOrOptions !== null &&\n \"query\" in queryOrOptions;\n\n const query = isObjectOptions ? queryOrOptions.query : queryOrOptions;\n const queryArgs = isObjectOptions ? queryOrOptions.args : args;\n const throwOnError = isObjectOptions\n ? (queryOrOptions.throwOnError ?? false)\n : true;\n const initialOptions = isObjectOptions\n ? { initialNumItems: queryOrOptions.initialNumItems }\n : options;\n\n if (\n typeof initialOptions?.initialNumItems !== \"number\" ||\n initialOptions.initialNumItems < 0\n ) {\n throw new Error(\n `\\`options.initialNumItems\\` must be a positive number. Received \\`${initialOptions?.initialNumItems}\\`.`,\n );\n }\n const skip = queryArgs === \"skip\";\n const argsObject = skip ? {} : queryArgs;\n\n const convexClient = useConvex();\n const logger = convexClient.logger;\n\n // The identity of createInitialState changes each time!\n const createInitialState: () => UsePaginatedQueryState = () => {\n const id = nextPaginationId();\n return {\n query,\n args: argsObject as Record<string, Value>,\n id,\n // Queries will contain zero or one queries forever.\n queries: skip\n ? ({} as UsePaginatedQueryState[\"queries\"])\n : {\n paginatedQuery: {\n query,\n args: {\n ...argsObject,\n },\n paginationOptions: {\n initialNumItems: initialOptions.initialNumItems,\n id,\n },\n },\n },\n skip,\n };\n };\n\n const [state, setState] =\n useState<UsePaginatedQueryState>(createInitialState);\n\n // `currState` is the state that we'll render based on.\n let currState = state;\n // New function, args, or skip? New paginated query!\n if (\n getFunctionName(query) !== getFunctionName(state.query) ||\n JSON.stringify(convexToJson(argsObject as Value)) !==\n JSON.stringify(convexToJson(state.args)) ||\n skip !== state.skip\n ) {\n currState = createInitialState();\n setState(currState);\n }\n // currState.queries is just a single query; we use useQueries\n // because it's the lower-level ook sthat supports pagination options.\n const resultsObject = useQueries(currState.queries);\n\n // skip\n if (!(\"paginatedQuery\" in resultsObject)) {\n if (!skip) {\n throw new Error(\"Why is it missing?\");\n }\n const internalResult = {\n results: [] as Query[\"_returnType\"][\"page\"],\n status: \"LoadingFirstPage\" as const,\n isLoading: true as const,\n loadMore: function skipNOP(_numItems: number) {\n return false;\n },\n };\n if (isObjectOptions) {\n return reshapeToObjectForm2(\n internalResult,\n ) as unknown as UsePaginatedQueryObjectReturnType<Query>;\n }\n return internalResult as unknown as UsePaginatedQueryReturnType<Query>;\n }\n const result = resultsObject.paginatedQuery as\n | PaginatedQueryResult<Query[\"_returnType\"][\"page\"][number]>\n | Error;\n\n // TODO this is a weird mix of responsibilities:\n // - is it the hook's job to render the initial loading state?\n // - or is it the paginated query's job to render the approproate loading state?\n // It comes back to why we'd ever get undefined when asking about a query; have we not yet called subscribe for it?\n if (result === undefined) {\n const internalResult = {\n results: [] as Query[\"_returnType\"][\"page\"],\n loadMore: () => false,\n isLoading: true as const,\n status: \"LoadingFirstPage\" as const,\n };\n if (isObjectOptions) {\n return reshapeToObjectForm2(\n internalResult,\n ) as unknown as UsePaginatedQueryObjectReturnType<Query>;\n }\n return internalResult as unknown as UsePaginatedQueryReturnType<Query>;\n }\n\n if (result instanceof Error) {\n if (\n result.message.includes(\"InvalidCursor\") ||\n (result instanceof ConvexError &&\n typeof result.data === \"object\" &&\n result.data?.isConvexSystemError === true &&\n result.data?.paginationError === \"InvalidCursor\")\n ) {\n // - InvalidCursor: If the cursor is invalid, probably the paginated\n // database query was data-dependent and changed underneath us. The\n // cursor in the params or journal no longer matches the current\n // database query.\n\n // In all cases, we want to restart pagination to throw away all our\n // existing cursors.\n logger.warn(\n \"usePaginatedQuery hit error, resetting pagination state: \" +\n result.message,\n );\n setState(createInitialState);\n const internalResult = {\n results: [] as Query[\"_returnType\"][\"page\"],\n loadMore: () => false,\n isLoading: true as const,\n status: \"LoadingFirstPage\" as const,\n };\n if (isObjectOptions) {\n return reshapeToObjectForm2(\n internalResult,\n ) as unknown as UsePaginatedQueryObjectReturnType<Query>;\n }\n return internalResult as unknown as UsePaginatedQueryReturnType<Query>;\n } else {\n if (throwOnError) {\n throw result;\n }\n const internalResult = {\n results: [] as Query[\"_returnType\"][\"page\"],\n loadMore: () => false,\n isLoading: false as const,\n status: \"Error\" as const,\n error: result,\n };\n if (isObjectOptions) {\n return reshapeToObjectForm2(\n internalResult,\n ) as unknown as UsePaginatedQueryObjectReturnType<Query>;\n }\n return internalResult as unknown as UsePaginatedQueryReturnType<Query>;\n }\n }\n\n const internalResult = {\n ...result,\n loadMore: (num: number) => {\n return result.loadMore(num);\n },\n isLoading:\n result.status === \"LoadingFirstPage\"\n ? (true as const)\n : result.status === \"LoadingMore\"\n ? (true as const)\n : (false as const),\n };\n if (isObjectOptions) {\n return reshapeToObjectForm2(\n internalResult,\n ) as unknown as UsePaginatedQueryObjectReturnType<Query>;\n }\n return internalResult as unknown as UsePaginatedQueryReturnType<Query>;\n}\n\n/**\n * Reshape the internal TitleCase pagination result into the object-form\n * return type with lowercase `status`, `canLoadMore`, and `data`.\n */\nfunction reshapeToObjectForm2<Item>(internal: {\n results: Item[];\n status: string;\n isLoading: boolean;\n loadMore: (...args: any[]) => any;\n error?: Error;\n}) {\n const { results, loadMore } = internal;\n if (internal.status === \"Error\" && \"error\" in internal) {\n return {\n data: results,\n status: \"error\" as const,\n canLoadMore: false as const,\n isLoading: false as const,\n error: internal.error,\n loadMore,\n };\n }\n if (\n internal.status === \"LoadingFirstPage\" ||\n internal.status === \"LoadingMore\"\n ) {\n return {\n data: internal.status === \"LoadingFirstPage\" ? undefined : results,\n status: \"pending\" as const,\n canLoadMore: false as const,\n isLoading: true as const,\n error: undefined,\n loadMore,\n };\n }\n // CanLoadMore or Exhausted\n return {\n data: results,\n status: \"success\" as const,\n canLoadMore: internal.status === \"CanLoadMore\",\n isLoading: false as const,\n error: undefined,\n loadMore,\n };\n}\n\nlet paginationId = 0;\n/**\n * See ./use_paginated_query for the purpose, but we may be able to get rid of this soon.\n *\n * @returns The pagination ID.\n */\nfunction nextPaginationId(): number {\n paginationId++;\n return paginationId;\n}\n\n/**\n * Reset pagination id for tests only, so tests know what it is.\n */\nexport function resetPaginationId() {\n paginationId = 0;\n}\n", "import React from \"react\";\nimport { ReactNode } from \"react\";\nimport { useConvexAuth } from \"./ConvexAuthState.js\";\n\n/**\n * Renders children if the client is authenticated.\n *\n * @public\n */\nexport function Authenticated({ children }: { children: ReactNode }) {\n const { isLoading, isAuthenticated } = useConvexAuth();\n if (isLoading || !isAuthenticated) {\n return null;\n }\n return <>{children}</>;\n}\n\n/**\n * Renders children if the client is using authentication but is not authenticated.\n *\n * @public\n */\nexport function Unauthenticated({ children }: { children: ReactNode }) {\n const { isLoading, isAuthenticated } = useConvexAuth();\n if (isLoading || isAuthenticated) {\n return null;\n }\n return <>{children}</>;\n}\n\n/**\n * Renders children if the client isn't using authentication or is in the process\n * of authenticating.\n *\n * @public\n */\nexport function AuthLoading({ children }: { children: ReactNode }) {\n const { isLoading } = useConvexAuth();\n if (!isLoading) {\n return null;\n }\n return <>{children}</>;\n}\n", "import React, {\n createContext,\n ReactNode,\n useContext,\n useEffect,\n useState,\n} from \"react\";\nimport { AuthTokenFetcher } from \"../browser/sync/client.js\";\nimport { ConvexProvider } from \"./client.js\";\n\n// Until we can import from our own entry points (requires TypeScript 4.7),\n// just describe the interface enough to help users pass the right type.\ntype IConvexReactClient = {\n setAuth(\n fetchToken: AuthTokenFetcher,\n onChange: (isAuthenticated: boolean) => void,\n ): void;\n clearAuth(): void;\n};\n\n/**\n * Type representing the state of an auth integration with Convex.\n *\n * @public\n */\nexport type ConvexAuthState = {\n isLoading: boolean;\n isAuthenticated: boolean;\n};\n\nconst ConvexAuthContext = createContext<ConvexAuthState>(undefined as any);\n\n/**\n * Get the {@link ConvexAuthState} within a React component.\n *\n * This relies on a Convex auth integration provider being above in the React\n * component tree.\n *\n * @returns The current {@link ConvexAuthState}.\n *\n * @public\n */\nexport function useConvexAuth(): {\n isLoading: boolean;\n isAuthenticated: boolean;\n} {\n const authContext = useContext(ConvexAuthContext);\n if (authContext === undefined) {\n throw new Error(\n \"Could not find `ConvexProviderWithAuth` (or `ConvexProviderWithClerk` \" +\n \"or `ConvexProviderWithAuth0`) \" +\n \"as an ancestor component. This component may be missing, or you \" +\n \"might have two instances of the `convex/react` module loaded in your \" +\n \"project.\",\n );\n }\n return authContext;\n}\n\n/**\n * A replacement for {@link ConvexProvider} which additionally provides\n * {@link ConvexAuthState} to descendants of this component.\n *\n * Use this to integrate any auth provider with Convex. The `useAuth` prop\n * should be a React hook that returns the provider's authentication state\n * and a function to fetch a JWT access token.\n *\n * If the `useAuth` prop function updates causing a rerender then auth state\n * will transition to loading and the `fetchAccessToken()` function called again.\n *\n * See [Custom Auth Integration](https://docs.convex.dev/auth/advanced/custom-auth) for more information.\n *\n * @public\n */\nexport function ConvexProviderWithAuth({\n children,\n client,\n useAuth,\n}: {\n children?: ReactNode;\n client: IConvexReactClient;\n useAuth: () => {\n isLoading: boolean;\n isAuthenticated: boolean;\n fetchAccessToken: (args: {\n forceRefreshToken: boolean;\n }) => Promise<string | null>;\n };\n}) {\n const {\n isLoading: authProviderLoading,\n isAuthenticated: authProviderAuthenticated,\n fetchAccessToken,\n } = useAuth();\n const [isConvexAuthenticated, setIsConvexAuthenticated] = useState<\n boolean | null\n >(null);\n\n // If the useAuth went back to the authProviderLoading state (which is unusual but possible)\n // reset the Convex auth state to null so that we can correctly\n // transition the state from \"loading\" to \"authenticated\"\n // without going through \"unauthenticated\".\n if (authProviderLoading && isConvexAuthenticated !== null) {\n setIsConvexAuthenticated(null);\n }\n\n // If the useAuth goes to not authenticated then isConvexAuthenticated should reflect that.\n if (\n !authProviderLoading &&\n !authProviderAuthenticated &&\n isConvexAuthenticated !== false\n ) {\n setIsConvexAuthenticated(false);\n }\n\n return (\n <ConvexAuthContext.Provider\n value={{\n isLoading: isConvexAuthenticated === null,\n isAuthenticated:\n authProviderAuthenticated && (isConvexAuthenticated ?? false),\n }}\n >\n <ConvexAuthStateFirstEffect\n authProviderAuthenticated={authProviderAuthenticated}\n fetchAccessToken={fetchAccessToken}\n authProviderLoading={authProviderLoading}\n client={client}\n setIsConvexAuthenticated={setIsConvexAuthenticated}\n />\n <ConvexProvider client={client as any}>{children}</ConvexProvider>\n <ConvexAuthStateLastEffect\n authProviderAuthenticated={authProviderAuthenticated}\n fetchAccessToken={fetchAccessToken}\n authProviderLoading={authProviderLoading}\n client={client}\n setIsConvexAuthenticated={setIsConvexAuthenticated}\n />\n </ConvexAuthContext.Provider>\n );\n}\n\n// First child ensures we `setAuth` before\n// other child components subscribe to queries via `useEffect`.\nfunction ConvexAuthStateFirstEffect({\n authProviderAuthenticated,\n fetchAccessToken,\n authProviderLoading,\n client,\n setIsConvexAuthenticated,\n}: {\n authProviderAuthenticated: boolean;\n fetchAccessToken: (args: {\n forceRefreshToken: boolean;\n }) => Promise<string | null>;\n authProviderLoading: boolean;\n client: IConvexReactClient;\n setIsConvexAuthenticated: React.Dispatch<\n React.SetStateAction<boolean | null>\n >;\n}) {\n useEffect(() => {\n let isThisEffectRelevant = true;\n if (authProviderAuthenticated) {\n client.setAuth(fetchAccessToken, (backendReportsIsAuthenticated) => {\n if (isThisEffectRelevant) {\n setIsConvexAuthenticated(() => backendReportsIsAuthenticated);\n }\n });\n return () => {\n isThisEffectRelevant = false;\n\n // If unmounting or something changed before we finished fetching the token\n // we shouldn't transition to a loaded state.\n setIsConvexAuthenticated((isConvexAuthenticated) =>\n isConvexAuthenticated ? false : null,\n );\n };\n }\n }, [\n authProviderAuthenticated,\n fetchAccessToken,\n authProviderLoading,\n client,\n setIsConvexAuthenticated,\n ]);\n return null;\n}\n\n// Last child ensures we `clearAuth` last,\n// so that queries from unmounted sibling components\n// unsubscribe first and don't rerun without auth on the server\nfunction ConvexAuthStateLastEffect({\n authProviderAuthenticated,\n fetchAccessToken,\n authProviderLoading,\n client,\n setIsConvexAuthenticated,\n}: {\n authProviderAuthenticated: boolean;\n fetchAccessToken: (args: {\n forceRefreshToken: boolean;\n }) => Promise<string | null>;\n authProviderLoading: boolean;\n client: IConvexReactClient;\n setIsConvexAuthenticated: React.Dispatch<\n React.SetStateAction<boolean | null>\n >;\n}) {\n useEffect(() => {\n // If rendered with authProviderAuthenticated=true then clear that auth on in cleanup.\n if (authProviderAuthenticated) {\n return () => {\n client.clearAuth();\n // Set state back to loading in case this is a transition from one\n // fetchToken function to another which signals a new auth context,\n // e.g. a new orgId from Clerk. Auth context changes like this\n // return isAuthenticated: true from useAuth() but if\n // useAuth reports isAuthenticated: false on the next render\n // then this null value will be overridden to false.\n setIsConvexAuthenticated(() => null);\n };\n }\n }, [\n authProviderAuthenticated,\n fetchAccessToken,\n authProviderLoading,\n client,\n setIsConvexAuthenticated,\n ]);\n return null;\n}\n", "import { useMemo } from \"react\";\nimport { useQuery } from \"../react/client.js\";\nimport { FunctionReference, makeFunctionReference } from \"../server/api.js\";\nimport { jsonToConvex } from \"../values/index.js\";\n\n/**\n * The preloaded query payload, which should be passed to a client component\n * and passed to {@link usePreloadedQuery}.\n *\n * @public\n */\nexport type Preloaded<Query extends FunctionReference<\"query\">> = {\n __type: Query;\n _name: string;\n _argsJSON: string;\n _valueJSON: string;\n};\n\n/**\n * Load a reactive query within a React component using a `Preloaded` payload\n * from a Server Component returned by {@link nextjs.preloadQuery}.\n *\n * This React hook contains internal state that will cause a rerender\n * whenever the query result changes.\n *\n * Throws an error if not used under {@link ConvexProvider}.\n *\n * @param preloadedQuery - The `Preloaded` query payload from a Server Component.\n * @returns the result of the query. Initially returns the result fetched\n * by the Server Component. Subsequently returns the result fetched by the client.\n *\n * @public\n */\nexport function usePreloadedQuery<Query extends FunctionReference<\"query\">>(\n preloadedQuery: Preloaded<Query>,\n): Query[\"_returnType\"] {\n const args = useMemo(\n () => jsonToConvex(preloadedQuery._argsJSON),\n [preloadedQuery._argsJSON],\n ) as Query[\"_args\"];\n const preloadedResult = useMemo(\n () => jsonToConvex(preloadedQuery._valueJSON),\n [preloadedQuery._valueJSON],\n );\n const result = useQuery(\n makeFunctionReference(preloadedQuery._name) as Query,\n args,\n );\n return result === undefined ? preloadedResult : result;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_react", "arr", "value", "aLength", "bLength", "import_react", "functionName", "version", "code", "mark", "modification", "import_react", "React", "currentListeners", "import_react", "nextPaginationId", "internalResult", "paginationId", "import_react", "import_react", "React", "React", "import_react"]
7
7
  }