convex 1.44.0 → 1.45.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/browser.bundle.js +1 -1
  3. package/dist/browser.bundle.js.map +1 -1
  4. package/dist/cjs/cli/convexExport.js +1 -1
  5. package/dist/cjs/cli/convexExport.js.map +1 -1
  6. package/dist/cjs/cli/index.js +2 -32
  7. package/dist/cjs/cli/index.js.map +2 -2
  8. package/dist/cjs/cli/lib/api.js +11 -5
  9. package/dist/cjs/cli/lib/api.js.map +2 -2
  10. package/dist/cjs/cli/lib/convexExport.js +12 -1
  11. package/dist/cjs/cli/lib/convexExport.js.map +2 -2
  12. package/dist/cjs/cli/lib/dashboard.js.map +2 -2
  13. package/dist/cjs/cli/lib/generatedFunctionLogsApi.js.map +1 -1
  14. package/dist/cjs/cli/lib/localDeployment/upgrade.js +23 -188
  15. package/dist/cjs/cli/lib/localDeployment/upgrade.js.map +3 -3
  16. package/dist/cjs/cli/lib/mcp/tools/index.js.map +1 -1
  17. package/dist/cjs/cli/mcp.js +60 -63
  18. package/dist/cjs/cli/mcp.js.map +2 -2
  19. package/dist/cjs/index.js +1 -1
  20. package/dist/cjs/index.js.map +1 -1
  21. package/dist/cjs-types/cli/lib/api.d.ts.map +1 -1
  22. package/dist/cjs-types/cli/lib/convexExport.d.ts +1 -0
  23. package/dist/cjs-types/cli/lib/convexExport.d.ts.map +1 -1
  24. package/dist/cjs-types/cli/lib/dashboard.d.ts.map +1 -1
  25. package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts +2 -0
  26. package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
  27. package/dist/cjs-types/cli/lib/localDeployment/upgrade.d.ts +2 -0
  28. package/dist/cjs-types/cli/lib/localDeployment/upgrade.d.ts.map +1 -1
  29. package/dist/cjs-types/cli/lib/mcp/tools/index.d.ts +1 -1
  30. package/dist/cjs-types/cli/lib/mcp/tools/index.d.ts.map +1 -1
  31. package/dist/cjs-types/cli/mcp.d.ts +3 -0
  32. package/dist/cjs-types/cli/mcp.d.ts.map +1 -1
  33. package/dist/cjs-types/index.d.ts +1 -1
  34. package/dist/cjs-types/index.d.ts.map +1 -1
  35. package/dist/cli.bundle.cjs +25565 -21249
  36. package/dist/cli.bundle.cjs.map +4 -4
  37. package/dist/esm/cli/convexExport.js +1 -1
  38. package/dist/esm/cli/convexExport.js.map +1 -1
  39. package/dist/esm/cli/index.js +2 -32
  40. package/dist/esm/cli/index.js.map +2 -2
  41. package/dist/esm/cli/lib/api.js +11 -5
  42. package/dist/esm/cli/lib/api.js.map +2 -2
  43. package/dist/esm/cli/lib/convexExport.js +16 -3
  44. package/dist/esm/cli/lib/convexExport.js.map +2 -2
  45. package/dist/esm/cli/lib/dashboard.js.map +2 -2
  46. package/dist/esm/cli/lib/localDeployment/upgrade.js +22 -190
  47. package/dist/esm/cli/lib/localDeployment/upgrade.js.map +2 -2
  48. package/dist/esm/cli/lib/mcp/tools/index.js.map +1 -1
  49. package/dist/esm/cli/mcp.js +60 -67
  50. package/dist/esm/cli/mcp.js.map +2 -2
  51. package/dist/esm/index.js +1 -1
  52. package/dist/esm/index.js.map +1 -1
  53. package/dist/esm-types/cli/lib/api.d.ts.map +1 -1
  54. package/dist/esm-types/cli/lib/convexExport.d.ts +1 -0
  55. package/dist/esm-types/cli/lib/convexExport.d.ts.map +1 -1
  56. package/dist/esm-types/cli/lib/dashboard.d.ts.map +1 -1
  57. package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts +2 -0
  58. package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
  59. package/dist/esm-types/cli/lib/localDeployment/upgrade.d.ts +2 -0
  60. package/dist/esm-types/cli/lib/localDeployment/upgrade.d.ts.map +1 -1
  61. package/dist/esm-types/cli/lib/mcp/tools/index.d.ts +1 -1
  62. package/dist/esm-types/cli/lib/mcp/tools/index.d.ts.map +1 -1
  63. package/dist/esm-types/cli/mcp.d.ts +3 -0
  64. package/dist/esm-types/cli/mcp.d.ts.map +1 -1
  65. package/dist/esm-types/index.d.ts +1 -1
  66. package/dist/esm-types/index.d.ts.map +1 -1
  67. package/dist/react.bundle.js +1 -1
  68. package/dist/react.bundle.js.map +1 -1
  69. package/package.json +3 -3
  70. package/src/cli/convexExport.ts +1 -1
  71. package/src/cli/index.ts +2 -35
  72. package/src/cli/lib/api.ts +11 -5
  73. package/src/cli/lib/convexExport.ts +21 -0
  74. package/src/cli/lib/dashboard.ts +2 -0
  75. package/src/cli/lib/generatedFunctionLogsApi.ts +2 -0
  76. package/src/cli/lib/localDeployment/upgrade.ts +34 -207
  77. package/src/cli/lib/mcp/tools/index.ts +1 -1
  78. package/src/cli/mcp.ts +64 -72
  79. package/src/index.ts +1 -1
  80. package/dist/cjs-types/browser/http_client.test.d.ts +0 -2
  81. package/dist/cjs-types/browser/http_client.test.d.ts.map +0 -1
  82. package/dist/cjs-types/browser/query_options.test.d.ts +0 -2
  83. package/dist/cjs-types/browser/query_options.test.d.ts.map +0 -1
  84. package/dist/cjs-types/browser/simple_client.test.d.ts +0 -2
  85. package/dist/cjs-types/browser/simple_client.test.d.ts.map +0 -1
  86. package/dist/cjs-types/browser/sync/client.test.d.ts +0 -5
  87. package/dist/cjs-types/browser/sync/client.test.d.ts.map +0 -1
  88. package/dist/cjs-types/browser/sync/client_node.test.d.ts +0 -2
  89. package/dist/cjs-types/browser/sync/client_node.test.d.ts.map +0 -1
  90. package/dist/cjs-types/browser/sync/client_node_test_helpers.d.ts +0 -44
  91. package/dist/cjs-types/browser/sync/client_node_test_helpers.d.ts.map +0 -1
  92. package/dist/cjs-types/browser/sync/local_state.test.d.ts +0 -2
  93. package/dist/cjs-types/browser/sync/local_state.test.d.ts.map +0 -1
  94. package/dist/cjs-types/browser/sync/optimistic_query_set.test.d.ts +0 -2
  95. package/dist/cjs-types/browser/sync/optimistic_query_set.test.d.ts.map +0 -1
  96. package/dist/cjs-types/browser/sync/paginated_query_client.test.d.ts +0 -2
  97. package/dist/cjs-types/browser/sync/paginated_query_client.test.d.ts.map +0 -1
  98. package/dist/cjs-types/browser/sync/protocol.test.d.ts +0 -5
  99. package/dist/cjs-types/browser/sync/protocol.test.d.ts.map +0 -1
  100. package/dist/cjs-types/browser/sync/request_manager.test.d.ts +0 -2
  101. package/dist/cjs-types/browser/sync/request_manager.test.d.ts.map +0 -1
  102. package/dist/cjs-types/bundler/fs.test.d.ts +0 -2
  103. package/dist/cjs-types/bundler/fs.test.d.ts.map +0 -1
  104. package/dist/cjs-types/bundler/index.test.d.ts +0 -2
  105. package/dist/cjs-types/bundler/index.test.d.ts.map +0 -1
  106. package/dist/cjs-types/cli/codegen_templates/api.test.d.ts +0 -2
  107. package/dist/cjs-types/cli/codegen_templates/api.test.d.ts.map +0 -1
  108. package/dist/cjs-types/cli/codegen_templates/common.test.d.ts +0 -2
  109. package/dist/cjs-types/cli/codegen_templates/common.test.d.ts.map +0 -1
  110. package/dist/cjs-types/cli/codegen_templates/templates.test.d.ts +0 -2
  111. package/dist/cjs-types/cli/codegen_templates/templates.test.d.ts.map +0 -1
  112. package/dist/cjs-types/cli/codegen_templates/validator_helpers.test.d.ts +0 -2
  113. package/dist/cjs-types/cli/codegen_templates/validator_helpers.test.d.ts.map +0 -1
  114. package/dist/cjs-types/cli/configure.test.d.ts +0 -2
  115. package/dist/cjs-types/cli/configure.test.d.ts.map +0 -1
  116. package/dist/cjs-types/cli/deploymentCreate.test.d.ts +0 -2
  117. package/dist/cjs-types/cli/deploymentCreate.test.d.ts.map +0 -1
  118. package/dist/cjs-types/cli/deploymentSelect.test.d.ts +0 -2
  119. package/dist/cjs-types/cli/deploymentSelect.test.d.ts.map +0 -1
  120. package/dist/cjs-types/cli/deploymentSelection.test.d.ts +0 -2
  121. package/dist/cjs-types/cli/deploymentSelection.test.d.ts.map +0 -1
  122. package/dist/cjs-types/cli/deploymentToken.test.d.ts +0 -2
  123. package/dist/cjs-types/cli/deploymentToken.test.d.ts.map +0 -1
  124. package/dist/cjs-types/cli/dev.test.d.ts +0 -2
  125. package/dist/cjs-types/cli/dev.test.d.ts.map +0 -1
  126. package/dist/cjs-types/cli/envDefault.test.d.ts +0 -2
  127. package/dist/cjs-types/cli/envDefault.test.d.ts.map +0 -1
  128. package/dist/cjs-types/cli/lib/aiFiles/agentsmd.test.d.ts +0 -2
  129. package/dist/cjs-types/cli/lib/aiFiles/agentsmd.test.d.ts.map +0 -1
  130. package/dist/cjs-types/cli/lib/aiFiles/claudemd.test.d.ts +0 -2
  131. package/dist/cjs-types/cli/lib/aiFiles/claudemd.test.d.ts.map +0 -1
  132. package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.test.d.ts +0 -2
  133. package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.test.d.ts.map +0 -1
  134. package/dist/cjs-types/cli/lib/aiFiles/index.test.d.ts +0 -2
  135. package/dist/cjs-types/cli/lib/aiFiles/index.test.d.ts.map +0 -1
  136. package/dist/cjs-types/cli/lib/aiFiles/integration.test.d.ts +0 -2
  137. package/dist/cjs-types/cli/lib/aiFiles/integration.test.d.ts.map +0 -1
  138. package/dist/cjs-types/cli/lib/aiFiles/prompt.test.d.ts +0 -2
  139. package/dist/cjs-types/cli/lib/aiFiles/prompt.test.d.ts.map +0 -1
  140. package/dist/cjs-types/cli/lib/aiFiles/state.test.d.ts +0 -2
  141. package/dist/cjs-types/cli/lib/aiFiles/state.test.d.ts.map +0 -1
  142. package/dist/cjs-types/cli/lib/aiFiles/utils.test.d.ts +0 -2
  143. package/dist/cjs-types/cli/lib/aiFiles/utils.test.d.ts.map +0 -1
  144. package/dist/cjs-types/cli/lib/codegen.test.d.ts +0 -2
  145. package/dist/cjs-types/cli/lib/codegen.test.d.ts.map +0 -1
  146. package/dist/cjs-types/cli/lib/components.test.d.ts +0 -2
  147. package/dist/cjs-types/cli/lib/components.test.d.ts.map +0 -1
  148. package/dist/cjs-types/cli/lib/config.test.d.ts +0 -2
  149. package/dist/cjs-types/cli/lib/config.test.d.ts.map +0 -1
  150. package/dist/cjs-types/cli/lib/deployment.test.d.ts +0 -2
  151. package/dist/cjs-types/cli/lib/deployment.test.d.ts.map +0 -1
  152. package/dist/cjs-types/cli/lib/deploymentSelector.test.d.ts +0 -2
  153. package/dist/cjs-types/cli/lib/deploymentSelector.test.d.ts.map +0 -1
  154. package/dist/cjs-types/cli/lib/env.test.d.ts +0 -2
  155. package/dist/cjs-types/cli/lib/env.test.d.ts.map +0 -1
  156. package/dist/cjs-types/cli/lib/expiration.test.d.ts +0 -2
  157. package/dist/cjs-types/cli/lib/expiration.test.d.ts.map +0 -1
  158. package/dist/cjs-types/cli/lib/extractDeploymentNameForWorkOS.test.d.ts +0 -2
  159. package/dist/cjs-types/cli/lib/extractDeploymentNameForWorkOS.test.d.ts.map +0 -1
  160. package/dist/cjs-types/cli/lib/formatEnvValueForDotfile.test.d.ts +0 -2
  161. package/dist/cjs-types/cli/lib/formatEnvValueForDotfile.test.d.ts.map +0 -1
  162. package/dist/cjs-types/cli/lib/formatTargetedDeployment.test.d.ts +0 -2
  163. package/dist/cjs-types/cli/lib/formatTargetedDeployment.test.d.ts.map +0 -1
  164. package/dist/cjs-types/cli/lib/fsUtils.test.d.ts +0 -2
  165. package/dist/cjs-types/cli/lib/fsUtils.test.d.ts.map +0 -1
  166. package/dist/cjs-types/cli/lib/generateDocs.test.d.ts +0 -2
  167. package/dist/cjs-types/cli/lib/generateDocs.test.d.ts.map +0 -1
  168. package/dist/cjs-types/cli/lib/indexes.test.d.ts +0 -2
  169. package/dist/cjs-types/cli/lib/indexes.test.d.ts.map +0 -1
  170. package/dist/cjs-types/cli/lib/localDeployment/run.test.d.ts +0 -2
  171. package/dist/cjs-types/cli/lib/localDeployment/run.test.d.ts.map +0 -1
  172. package/dist/cjs-types/cli/lib/localDeployment/secrets.test.d.ts +0 -2
  173. package/dist/cjs-types/cli/lib/localDeployment/secrets.test.d.ts.map +0 -1
  174. package/dist/cjs-types/cli/lib/run.test.d.ts +0 -2
  175. package/dist/cjs-types/cli/lib/run.test.d.ts.map +0 -1
  176. package/dist/cjs-types/cli/lib/runTestFunction.test.d.ts +0 -2
  177. package/dist/cjs-types/cli/lib/runTestFunction.test.d.ts.map +0 -1
  178. package/dist/cjs-types/cli/lib/typecheck.test.d.ts +0 -2
  179. package/dist/cjs-types/cli/lib/typecheck.test.d.ts.map +0 -1
  180. package/dist/cjs-types/cli/lib/updates.test.d.ts +0 -2
  181. package/dist/cjs-types/cli/lib/updates.test.d.ts.map +0 -1
  182. package/dist/cjs-types/cli/lib/utils/hash.test.d.ts +0 -2
  183. package/dist/cjs-types/cli/lib/utils/hash.test.d.ts.map +0 -1
  184. package/dist/cjs-types/cli/lib/utils/utils.test.d.ts +0 -2
  185. package/dist/cjs-types/cli/lib/utils/utils.test.d.ts.map +0 -1
  186. package/dist/cjs-types/cli/lib/versionApi.test.d.ts +0 -2
  187. package/dist/cjs-types/cli/lib/versionApi.test.d.ts.map +0 -1
  188. package/dist/cjs-types/cli/lib/workos/environmentApi.test.d.ts +0 -2
  189. package/dist/cjs-types/cli/lib/workos/environmentApi.test.d.ts.map +0 -1
  190. package/dist/cjs-types/cli/lib/workos/workos.test.d.ts +0 -2
  191. package/dist/cjs-types/cli/lib/workos/workos.test.d.ts.map +0 -1
  192. package/dist/cjs-types/cli/login.test.d.ts +0 -2
  193. package/dist/cjs-types/cli/login.test.d.ts.map +0 -1
  194. package/dist/cjs-types/common/index.test.d.ts +0 -2
  195. package/dist/cjs-types/common/index.test.d.ts.map +0 -1
  196. package/dist/cjs-types/nextjs/nextjs.test.d.ts +0 -2
  197. package/dist/cjs-types/nextjs/nextjs.test.d.ts.map +0 -1
  198. package/dist/cjs-types/react/ConvexAuthState.test.d.ts +0 -2
  199. package/dist/cjs-types/react/ConvexAuthState.test.d.ts.map +0 -1
  200. package/dist/cjs-types/react/auth_helpers.test.d.ts +0 -2
  201. package/dist/cjs-types/react/auth_helpers.test.d.ts.map +0 -1
  202. package/dist/cjs-types/react/auth_websocket.test.d.ts +0 -2
  203. package/dist/cjs-types/react/auth_websocket.test.d.ts.map +0 -1
  204. package/dist/cjs-types/react/client.test.d.ts +0 -2
  205. package/dist/cjs-types/react/client.test.d.ts.map +0 -1
  206. package/dist/cjs-types/react/client_provided_base_client.test.d.ts +0 -2
  207. package/dist/cjs-types/react/client_provided_base_client.test.d.ts.map +0 -1
  208. package/dist/cjs-types/react/queries_observer.test.d.ts +0 -2
  209. package/dist/cjs-types/react/queries_observer.test.d.ts.map +0 -1
  210. package/dist/cjs-types/react/react_node.test.d.ts +0 -2
  211. package/dist/cjs-types/react/react_node.test.d.ts.map +0 -1
  212. package/dist/cjs-types/react/use_paginated_query.test.d.ts +0 -2
  213. package/dist/cjs-types/react/use_paginated_query.test.d.ts.map +0 -1
  214. package/dist/cjs-types/react/use_queries.test.d.ts +0 -5
  215. package/dist/cjs-types/react/use_queries.test.d.ts.map +0 -1
  216. package/dist/cjs-types/react/use_query.test.d.ts +0 -5
  217. package/dist/cjs-types/react/use_query.test.d.ts.map +0 -1
  218. package/dist/cjs-types/react/use_query_object_options.test.d.ts +0 -5
  219. package/dist/cjs-types/react/use_query_object_options.test.d.ts.map +0 -1
  220. package/dist/cjs-types/react/use_query_result.test.d.ts +0 -5
  221. package/dist/cjs-types/react/use_query_result.test.d.ts.map +0 -1
  222. package/dist/cjs-types/react-auth0/ConvexProviderWithAuth0.test.d.ts +0 -2
  223. package/dist/cjs-types/react-auth0/ConvexProviderWithAuth0.test.d.ts.map +0 -1
  224. package/dist/cjs-types/react-clerk/ConvexProviderWithClerk.test.d.ts +0 -2
  225. package/dist/cjs-types/react-clerk/ConvexProviderWithClerk.test.d.ts.map +0 -1
  226. package/dist/cjs-types/server/api.intersect.test.d.ts +0 -2
  227. package/dist/cjs-types/server/api.intersect.test.d.ts.map +0 -1
  228. package/dist/cjs-types/server/api.test.d.ts +0 -2
  229. package/dist/cjs-types/server/api.test.d.ts.map +0 -1
  230. package/dist/cjs-types/server/audit_logging.test.d.ts +0 -2
  231. package/dist/cjs-types/server/audit_logging.test.d.ts.map +0 -1
  232. package/dist/cjs-types/server/components/index.test.d.ts +0 -2
  233. package/dist/cjs-types/server/components/index.test.d.ts.map +0 -1
  234. package/dist/cjs-types/server/cron.test.d.ts +0 -2
  235. package/dist/cjs-types/server/cron.test.d.ts.map +0 -1
  236. package/dist/cjs-types/server/data_model.test.d.ts +0 -2
  237. package/dist/cjs-types/server/data_model.test.d.ts.map +0 -1
  238. package/dist/cjs-types/server/database.test.d.ts +0 -2
  239. package/dist/cjs-types/server/database.test.d.ts.map +0 -1
  240. package/dist/cjs-types/server/database_api.test.d.ts +0 -2
  241. package/dist/cjs-types/server/database_api.test.d.ts.map +0 -1
  242. package/dist/cjs-types/server/filter_builder.test.d.ts +0 -2
  243. package/dist/cjs-types/server/filter_builder.test.d.ts.map +0 -1
  244. package/dist/cjs-types/server/impl/actions_impl.test.d.ts +0 -2
  245. package/dist/cjs-types/server/impl/actions_impl.test.d.ts.map +0 -1
  246. package/dist/cjs-types/server/impl/filter_builder_impl.test.d.ts +0 -2
  247. package/dist/cjs-types/server/impl/filter_builder_impl.test.d.ts.map +0 -1
  248. package/dist/cjs-types/server/impl/query_impl.test.d.ts +0 -2
  249. package/dist/cjs-types/server/impl/query_impl.test.d.ts.map +0 -1
  250. package/dist/cjs-types/server/pagination.test.d.ts +0 -2
  251. package/dist/cjs-types/server/pagination.test.d.ts.map +0 -1
  252. package/dist/cjs-types/server/query.test.d.ts +0 -2
  253. package/dist/cjs-types/server/query.test.d.ts.map +0 -1
  254. package/dist/cjs-types/server/registration.test.d.ts +0 -2
  255. package/dist/cjs-types/server/registration.test.d.ts.map +0 -1
  256. package/dist/cjs-types/server/router.test.d.ts +0 -2
  257. package/dist/cjs-types/server/router.test.d.ts.map +0 -1
  258. package/dist/cjs-types/server/scheduler.test.d.ts +0 -2
  259. package/dist/cjs-types/server/scheduler.test.d.ts.map +0 -1
  260. package/dist/cjs-types/server/schema.test.d.ts +0 -2
  261. package/dist/cjs-types/server/schema.test.d.ts.map +0 -1
  262. package/dist/cjs-types/test/fake_watch.d.ts +0 -16
  263. package/dist/cjs-types/test/fake_watch.d.ts.map +0 -1
  264. package/dist/cjs-types/test/type_testing.d.ts +0 -9
  265. package/dist/cjs-types/test/type_testing.d.ts.map +0 -1
  266. package/dist/cjs-types/type_utils.test.d.ts +0 -2
  267. package/dist/cjs-types/type_utils.test.d.ts.map +0 -1
  268. package/dist/cjs-types/values/size.test.d.ts +0 -2
  269. package/dist/cjs-types/values/size.test.d.ts.map +0 -1
  270. package/dist/cjs-types/values/validator.test.d.ts +0 -2
  271. package/dist/cjs-types/values/validator.test.d.ts.map +0 -1
  272. package/dist/cjs-types/values/value.test.d.ts +0 -2
  273. package/dist/cjs-types/values/value.test.d.ts.map +0 -1
  274. package/dist/esm-types/browser/http_client.test.d.ts +0 -2
  275. package/dist/esm-types/browser/http_client.test.d.ts.map +0 -1
  276. package/dist/esm-types/browser/query_options.test.d.ts +0 -2
  277. package/dist/esm-types/browser/query_options.test.d.ts.map +0 -1
  278. package/dist/esm-types/browser/simple_client.test.d.ts +0 -2
  279. package/dist/esm-types/browser/simple_client.test.d.ts.map +0 -1
  280. package/dist/esm-types/browser/sync/client.test.d.ts +0 -5
  281. package/dist/esm-types/browser/sync/client.test.d.ts.map +0 -1
  282. package/dist/esm-types/browser/sync/client_node.test.d.ts +0 -2
  283. package/dist/esm-types/browser/sync/client_node.test.d.ts.map +0 -1
  284. package/dist/esm-types/browser/sync/client_node_test_helpers.d.ts +0 -44
  285. package/dist/esm-types/browser/sync/client_node_test_helpers.d.ts.map +0 -1
  286. package/dist/esm-types/browser/sync/local_state.test.d.ts +0 -2
  287. package/dist/esm-types/browser/sync/local_state.test.d.ts.map +0 -1
  288. package/dist/esm-types/browser/sync/optimistic_query_set.test.d.ts +0 -2
  289. package/dist/esm-types/browser/sync/optimistic_query_set.test.d.ts.map +0 -1
  290. package/dist/esm-types/browser/sync/paginated_query_client.test.d.ts +0 -2
  291. package/dist/esm-types/browser/sync/paginated_query_client.test.d.ts.map +0 -1
  292. package/dist/esm-types/browser/sync/protocol.test.d.ts +0 -5
  293. package/dist/esm-types/browser/sync/protocol.test.d.ts.map +0 -1
  294. package/dist/esm-types/browser/sync/request_manager.test.d.ts +0 -2
  295. package/dist/esm-types/browser/sync/request_manager.test.d.ts.map +0 -1
  296. package/dist/esm-types/bundler/fs.test.d.ts +0 -2
  297. package/dist/esm-types/bundler/fs.test.d.ts.map +0 -1
  298. package/dist/esm-types/bundler/index.test.d.ts +0 -2
  299. package/dist/esm-types/bundler/index.test.d.ts.map +0 -1
  300. package/dist/esm-types/cli/codegen_templates/api.test.d.ts +0 -2
  301. package/dist/esm-types/cli/codegen_templates/api.test.d.ts.map +0 -1
  302. package/dist/esm-types/cli/codegen_templates/common.test.d.ts +0 -2
  303. package/dist/esm-types/cli/codegen_templates/common.test.d.ts.map +0 -1
  304. package/dist/esm-types/cli/codegen_templates/templates.test.d.ts +0 -2
  305. package/dist/esm-types/cli/codegen_templates/templates.test.d.ts.map +0 -1
  306. package/dist/esm-types/cli/codegen_templates/validator_helpers.test.d.ts +0 -2
  307. package/dist/esm-types/cli/codegen_templates/validator_helpers.test.d.ts.map +0 -1
  308. package/dist/esm-types/cli/configure.test.d.ts +0 -2
  309. package/dist/esm-types/cli/configure.test.d.ts.map +0 -1
  310. package/dist/esm-types/cli/deploymentCreate.test.d.ts +0 -2
  311. package/dist/esm-types/cli/deploymentCreate.test.d.ts.map +0 -1
  312. package/dist/esm-types/cli/deploymentSelect.test.d.ts +0 -2
  313. package/dist/esm-types/cli/deploymentSelect.test.d.ts.map +0 -1
  314. package/dist/esm-types/cli/deploymentSelection.test.d.ts +0 -2
  315. package/dist/esm-types/cli/deploymentSelection.test.d.ts.map +0 -1
  316. package/dist/esm-types/cli/deploymentToken.test.d.ts +0 -2
  317. package/dist/esm-types/cli/deploymentToken.test.d.ts.map +0 -1
  318. package/dist/esm-types/cli/dev.test.d.ts +0 -2
  319. package/dist/esm-types/cli/dev.test.d.ts.map +0 -1
  320. package/dist/esm-types/cli/envDefault.test.d.ts +0 -2
  321. package/dist/esm-types/cli/envDefault.test.d.ts.map +0 -1
  322. package/dist/esm-types/cli/lib/aiFiles/agentsmd.test.d.ts +0 -2
  323. package/dist/esm-types/cli/lib/aiFiles/agentsmd.test.d.ts.map +0 -1
  324. package/dist/esm-types/cli/lib/aiFiles/claudemd.test.d.ts +0 -2
  325. package/dist/esm-types/cli/lib/aiFiles/claudemd.test.d.ts.map +0 -1
  326. package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.test.d.ts +0 -2
  327. package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.test.d.ts.map +0 -1
  328. package/dist/esm-types/cli/lib/aiFiles/index.test.d.ts +0 -2
  329. package/dist/esm-types/cli/lib/aiFiles/index.test.d.ts.map +0 -1
  330. package/dist/esm-types/cli/lib/aiFiles/integration.test.d.ts +0 -2
  331. package/dist/esm-types/cli/lib/aiFiles/integration.test.d.ts.map +0 -1
  332. package/dist/esm-types/cli/lib/aiFiles/prompt.test.d.ts +0 -2
  333. package/dist/esm-types/cli/lib/aiFiles/prompt.test.d.ts.map +0 -1
  334. package/dist/esm-types/cli/lib/aiFiles/state.test.d.ts +0 -2
  335. package/dist/esm-types/cli/lib/aiFiles/state.test.d.ts.map +0 -1
  336. package/dist/esm-types/cli/lib/aiFiles/utils.test.d.ts +0 -2
  337. package/dist/esm-types/cli/lib/aiFiles/utils.test.d.ts.map +0 -1
  338. package/dist/esm-types/cli/lib/codegen.test.d.ts +0 -2
  339. package/dist/esm-types/cli/lib/codegen.test.d.ts.map +0 -1
  340. package/dist/esm-types/cli/lib/components.test.d.ts +0 -2
  341. package/dist/esm-types/cli/lib/components.test.d.ts.map +0 -1
  342. package/dist/esm-types/cli/lib/config.test.d.ts +0 -2
  343. package/dist/esm-types/cli/lib/config.test.d.ts.map +0 -1
  344. package/dist/esm-types/cli/lib/deployment.test.d.ts +0 -2
  345. package/dist/esm-types/cli/lib/deployment.test.d.ts.map +0 -1
  346. package/dist/esm-types/cli/lib/deploymentSelector.test.d.ts +0 -2
  347. package/dist/esm-types/cli/lib/deploymentSelector.test.d.ts.map +0 -1
  348. package/dist/esm-types/cli/lib/env.test.d.ts +0 -2
  349. package/dist/esm-types/cli/lib/env.test.d.ts.map +0 -1
  350. package/dist/esm-types/cli/lib/expiration.test.d.ts +0 -2
  351. package/dist/esm-types/cli/lib/expiration.test.d.ts.map +0 -1
  352. package/dist/esm-types/cli/lib/extractDeploymentNameForWorkOS.test.d.ts +0 -2
  353. package/dist/esm-types/cli/lib/extractDeploymentNameForWorkOS.test.d.ts.map +0 -1
  354. package/dist/esm-types/cli/lib/formatEnvValueForDotfile.test.d.ts +0 -2
  355. package/dist/esm-types/cli/lib/formatEnvValueForDotfile.test.d.ts.map +0 -1
  356. package/dist/esm-types/cli/lib/formatTargetedDeployment.test.d.ts +0 -2
  357. package/dist/esm-types/cli/lib/formatTargetedDeployment.test.d.ts.map +0 -1
  358. package/dist/esm-types/cli/lib/fsUtils.test.d.ts +0 -2
  359. package/dist/esm-types/cli/lib/fsUtils.test.d.ts.map +0 -1
  360. package/dist/esm-types/cli/lib/generateDocs.test.d.ts +0 -2
  361. package/dist/esm-types/cli/lib/generateDocs.test.d.ts.map +0 -1
  362. package/dist/esm-types/cli/lib/indexes.test.d.ts +0 -2
  363. package/dist/esm-types/cli/lib/indexes.test.d.ts.map +0 -1
  364. package/dist/esm-types/cli/lib/localDeployment/run.test.d.ts +0 -2
  365. package/dist/esm-types/cli/lib/localDeployment/run.test.d.ts.map +0 -1
  366. package/dist/esm-types/cli/lib/localDeployment/secrets.test.d.ts +0 -2
  367. package/dist/esm-types/cli/lib/localDeployment/secrets.test.d.ts.map +0 -1
  368. package/dist/esm-types/cli/lib/run.test.d.ts +0 -2
  369. package/dist/esm-types/cli/lib/run.test.d.ts.map +0 -1
  370. package/dist/esm-types/cli/lib/runTestFunction.test.d.ts +0 -2
  371. package/dist/esm-types/cli/lib/runTestFunction.test.d.ts.map +0 -1
  372. package/dist/esm-types/cli/lib/typecheck.test.d.ts +0 -2
  373. package/dist/esm-types/cli/lib/typecheck.test.d.ts.map +0 -1
  374. package/dist/esm-types/cli/lib/updates.test.d.ts +0 -2
  375. package/dist/esm-types/cli/lib/updates.test.d.ts.map +0 -1
  376. package/dist/esm-types/cli/lib/utils/hash.test.d.ts +0 -2
  377. package/dist/esm-types/cli/lib/utils/hash.test.d.ts.map +0 -1
  378. package/dist/esm-types/cli/lib/utils/utils.test.d.ts +0 -2
  379. package/dist/esm-types/cli/lib/utils/utils.test.d.ts.map +0 -1
  380. package/dist/esm-types/cli/lib/versionApi.test.d.ts +0 -2
  381. package/dist/esm-types/cli/lib/versionApi.test.d.ts.map +0 -1
  382. package/dist/esm-types/cli/lib/workos/environmentApi.test.d.ts +0 -2
  383. package/dist/esm-types/cli/lib/workos/environmentApi.test.d.ts.map +0 -1
  384. package/dist/esm-types/cli/lib/workos/workos.test.d.ts +0 -2
  385. package/dist/esm-types/cli/lib/workos/workos.test.d.ts.map +0 -1
  386. package/dist/esm-types/cli/login.test.d.ts +0 -2
  387. package/dist/esm-types/cli/login.test.d.ts.map +0 -1
  388. package/dist/esm-types/common/index.test.d.ts +0 -2
  389. package/dist/esm-types/common/index.test.d.ts.map +0 -1
  390. package/dist/esm-types/nextjs/nextjs.test.d.ts +0 -2
  391. package/dist/esm-types/nextjs/nextjs.test.d.ts.map +0 -1
  392. package/dist/esm-types/react/ConvexAuthState.test.d.ts +0 -2
  393. package/dist/esm-types/react/ConvexAuthState.test.d.ts.map +0 -1
  394. package/dist/esm-types/react/auth_helpers.test.d.ts +0 -2
  395. package/dist/esm-types/react/auth_helpers.test.d.ts.map +0 -1
  396. package/dist/esm-types/react/auth_websocket.test.d.ts +0 -2
  397. package/dist/esm-types/react/auth_websocket.test.d.ts.map +0 -1
  398. package/dist/esm-types/react/client.test.d.ts +0 -2
  399. package/dist/esm-types/react/client.test.d.ts.map +0 -1
  400. package/dist/esm-types/react/client_provided_base_client.test.d.ts +0 -2
  401. package/dist/esm-types/react/client_provided_base_client.test.d.ts.map +0 -1
  402. package/dist/esm-types/react/queries_observer.test.d.ts +0 -2
  403. package/dist/esm-types/react/queries_observer.test.d.ts.map +0 -1
  404. package/dist/esm-types/react/react_node.test.d.ts +0 -2
  405. package/dist/esm-types/react/react_node.test.d.ts.map +0 -1
  406. package/dist/esm-types/react/use_paginated_query.test.d.ts +0 -2
  407. package/dist/esm-types/react/use_paginated_query.test.d.ts.map +0 -1
  408. package/dist/esm-types/react/use_queries.test.d.ts +0 -5
  409. package/dist/esm-types/react/use_queries.test.d.ts.map +0 -1
  410. package/dist/esm-types/react/use_query.test.d.ts +0 -5
  411. package/dist/esm-types/react/use_query.test.d.ts.map +0 -1
  412. package/dist/esm-types/react/use_query_object_options.test.d.ts +0 -5
  413. package/dist/esm-types/react/use_query_object_options.test.d.ts.map +0 -1
  414. package/dist/esm-types/react/use_query_result.test.d.ts +0 -5
  415. package/dist/esm-types/react/use_query_result.test.d.ts.map +0 -1
  416. package/dist/esm-types/react-auth0/ConvexProviderWithAuth0.test.d.ts +0 -2
  417. package/dist/esm-types/react-auth0/ConvexProviderWithAuth0.test.d.ts.map +0 -1
  418. package/dist/esm-types/react-clerk/ConvexProviderWithClerk.test.d.ts +0 -2
  419. package/dist/esm-types/react-clerk/ConvexProviderWithClerk.test.d.ts.map +0 -1
  420. package/dist/esm-types/server/api.intersect.test.d.ts +0 -2
  421. package/dist/esm-types/server/api.intersect.test.d.ts.map +0 -1
  422. package/dist/esm-types/server/api.test.d.ts +0 -2
  423. package/dist/esm-types/server/api.test.d.ts.map +0 -1
  424. package/dist/esm-types/server/audit_logging.test.d.ts +0 -2
  425. package/dist/esm-types/server/audit_logging.test.d.ts.map +0 -1
  426. package/dist/esm-types/server/components/index.test.d.ts +0 -2
  427. package/dist/esm-types/server/components/index.test.d.ts.map +0 -1
  428. package/dist/esm-types/server/cron.test.d.ts +0 -2
  429. package/dist/esm-types/server/cron.test.d.ts.map +0 -1
  430. package/dist/esm-types/server/data_model.test.d.ts +0 -2
  431. package/dist/esm-types/server/data_model.test.d.ts.map +0 -1
  432. package/dist/esm-types/server/database.test.d.ts +0 -2
  433. package/dist/esm-types/server/database.test.d.ts.map +0 -1
  434. package/dist/esm-types/server/database_api.test.d.ts +0 -2
  435. package/dist/esm-types/server/database_api.test.d.ts.map +0 -1
  436. package/dist/esm-types/server/filter_builder.test.d.ts +0 -2
  437. package/dist/esm-types/server/filter_builder.test.d.ts.map +0 -1
  438. package/dist/esm-types/server/impl/actions_impl.test.d.ts +0 -2
  439. package/dist/esm-types/server/impl/actions_impl.test.d.ts.map +0 -1
  440. package/dist/esm-types/server/impl/filter_builder_impl.test.d.ts +0 -2
  441. package/dist/esm-types/server/impl/filter_builder_impl.test.d.ts.map +0 -1
  442. package/dist/esm-types/server/impl/query_impl.test.d.ts +0 -2
  443. package/dist/esm-types/server/impl/query_impl.test.d.ts.map +0 -1
  444. package/dist/esm-types/server/pagination.test.d.ts +0 -2
  445. package/dist/esm-types/server/pagination.test.d.ts.map +0 -1
  446. package/dist/esm-types/server/query.test.d.ts +0 -2
  447. package/dist/esm-types/server/query.test.d.ts.map +0 -1
  448. package/dist/esm-types/server/registration.test.d.ts +0 -2
  449. package/dist/esm-types/server/registration.test.d.ts.map +0 -1
  450. package/dist/esm-types/server/router.test.d.ts +0 -2
  451. package/dist/esm-types/server/router.test.d.ts.map +0 -1
  452. package/dist/esm-types/server/scheduler.test.d.ts +0 -2
  453. package/dist/esm-types/server/scheduler.test.d.ts.map +0 -1
  454. package/dist/esm-types/server/schema.test.d.ts +0 -2
  455. package/dist/esm-types/server/schema.test.d.ts.map +0 -1
  456. package/dist/esm-types/test/fake_watch.d.ts +0 -16
  457. package/dist/esm-types/test/fake_watch.d.ts.map +0 -1
  458. package/dist/esm-types/test/type_testing.d.ts +0 -9
  459. package/dist/esm-types/test/type_testing.d.ts.map +0 -1
  460. package/dist/esm-types/type_utils.test.d.ts +0 -2
  461. package/dist/esm-types/type_utils.test.d.ts.map +0 -1
  462. package/dist/esm-types/values/size.test.d.ts +0 -2
  463. package/dist/esm-types/values/size.test.d.ts.map +0 -1
  464. package/dist/esm-types/values/validator.test.d.ts +0 -2
  465. package/dist/esm-types/values/validator.test.d.ts.map +0 -1
  466. package/dist/esm-types/values/value.test.d.ts +0 -2
  467. package/dist/esm-types/values/value.test.d.ts.map +0 -1
  468. package/src/browser/http_client.test.ts +0 -202
  469. package/src/browser/query_options.test.ts +0 -43
  470. package/src/browser/simple_client.test.ts +0 -104
  471. package/src/browser/sync/client.test.ts +0 -44
  472. package/src/browser/sync/client_node.test.ts +0 -1207
  473. package/src/browser/sync/client_node_test_helpers.ts +0 -200
  474. package/src/browser/sync/local_state.test.ts +0 -128
  475. package/src/browser/sync/optimistic_query_set.test.ts +0 -253
  476. package/src/browser/sync/paginated_query_client.test.ts +0 -597
  477. package/src/browser/sync/protocol.test.ts +0 -14
  478. package/src/browser/sync/request_manager.test.ts +0 -273
  479. package/src/bundler/fs.test.ts +0 -86
  480. package/src/bundler/index.test.ts +0 -210
  481. package/src/bundler/test_fixtures/js/project01/bar.js +0 -4
  482. package/src/bundler/test_fixtures/js/project01/file with spaces.js +0 -1
  483. package/src/bundler/test_fixtures/js/project01/foo.js +0 -9
  484. package/src/bundler/test_fixtures/js/project_with_https/https.js +0 -9
  485. package/src/bundler/test_fixtures/js/project_with_https_not_at_top_level/default.js +0 -3
  486. package/src/bundler/test_fixtures/js/project_with_https_not_at_top_level/more_code/https.js +0 -5
  487. package/src/bundler/test_fixtures/js/project_with_https_without_router/https.js +0 -1
  488. package/src/bundler/test_fixtures/js/project_with_node_shims/uses_node_shims.js +0 -4
  489. package/src/cli/codegen_templates/api.test.ts +0 -18
  490. package/src/cli/codegen_templates/common.test.ts +0 -52
  491. package/src/cli/codegen_templates/templates.test.ts +0 -16
  492. package/src/cli/codegen_templates/validator_helpers.test.ts +0 -31
  493. package/src/cli/configure.test.ts +0 -138
  494. package/src/cli/deploymentCreate.test.ts +0 -1376
  495. package/src/cli/deploymentSelect.test.ts +0 -1291
  496. package/src/cli/deploymentSelection.test.ts +0 -2546
  497. package/src/cli/deploymentToken.test.ts +0 -397
  498. package/src/cli/dev.test.ts +0 -157
  499. package/src/cli/envDefault.test.ts +0 -495
  500. package/src/cli/lib/__snapshots__/formatTargetedDeployment.test.ts.snap +0 -94
  501. package/src/cli/lib/aiFiles/agentsmd.test.ts +0 -133
  502. package/src/cli/lib/aiFiles/claudemd.test.ts +0 -92
  503. package/src/cli/lib/aiFiles/guidelinesmd.test.ts +0 -50
  504. package/src/cli/lib/aiFiles/index.test.ts +0 -986
  505. package/src/cli/lib/aiFiles/integration.test.ts +0 -692
  506. package/src/cli/lib/aiFiles/prompt.test.ts +0 -202
  507. package/src/cli/lib/aiFiles/state.test.ts +0 -305
  508. package/src/cli/lib/aiFiles/utils.test.ts +0 -50
  509. package/src/cli/lib/codegen.test.ts +0 -49
  510. package/src/cli/lib/components.test.ts +0 -227
  511. package/src/cli/lib/config.test.ts +0 -1026
  512. package/src/cli/lib/deployment.test.ts +0 -85
  513. package/src/cli/lib/deploymentSelector.test.ts +0 -107
  514. package/src/cli/lib/env.test.ts +0 -60
  515. package/src/cli/lib/expiration.test.ts +0 -159
  516. package/src/cli/lib/extractDeploymentNameForWorkOS.test.ts +0 -30
  517. package/src/cli/lib/formatEnvValueForDotfile.test.ts +0 -294
  518. package/src/cli/lib/formatTargetedDeployment.test.ts +0 -281
  519. package/src/cli/lib/fsUtils.test.ts +0 -67
  520. package/src/cli/lib/generateDocs.test.ts +0 -326
  521. package/src/cli/lib/indexes.test.ts +0 -77
  522. package/src/cli/lib/localDeployment/run.test.ts +0 -104
  523. package/src/cli/lib/localDeployment/secrets.test.ts +0 -53
  524. package/src/cli/lib/run.test.ts +0 -54
  525. package/src/cli/lib/runTestFunction.test.ts +0 -84
  526. package/src/cli/lib/typecheck.test.ts +0 -71
  527. package/src/cli/lib/updates.test.ts +0 -157
  528. package/src/cli/lib/utils/hash.test.ts +0 -25
  529. package/src/cli/lib/utils/utils.test.ts +0 -340
  530. package/src/cli/lib/versionApi.test.ts +0 -471
  531. package/src/cli/lib/workos/environmentApi.test.ts +0 -107
  532. package/src/cli/lib/workos/workos.test.ts +0 -242
  533. package/src/cli/login.test.ts +0 -261
  534. package/src/common/README.md +0 -2
  535. package/src/common/index.test.ts +0 -35
  536. package/src/nextjs/nextjs.test.tsx +0 -94
  537. package/src/react/ConvexAuthState.test.tsx +0 -702
  538. package/src/react/auth_helpers.test.tsx +0 -45
  539. package/src/react/auth_websocket.test.tsx +0 -1177
  540. package/src/react/client.test.tsx +0 -261
  541. package/src/react/client_provided_base_client.test.tsx +0 -174
  542. package/src/react/queries_observer.test.ts +0 -176
  543. package/src/react/react_node.test.ts +0 -78
  544. package/src/react/use_paginated_query.test.tsx +0 -1420
  545. package/src/react/use_queries.test.ts +0 -140
  546. package/src/react/use_query.test.ts +0 -71
  547. package/src/react/use_query_object_options.test.ts +0 -51
  548. package/src/react/use_query_result.test.ts +0 -75
  549. package/src/react-auth0/ConvexProviderWithAuth0.test.tsx +0 -17
  550. package/src/react-clerk/ConvexProviderWithClerk.test.tsx +0 -18
  551. package/src/server/README.md +0 -15
  552. package/src/server/api.intersect.test.ts +0 -109
  553. package/src/server/api.test.ts +0 -447
  554. package/src/server/audit_logging.test.ts +0 -131
  555. package/src/server/components/index.test.ts +0 -48
  556. package/src/server/cron.test.ts +0 -58
  557. package/src/server/data_model.test.ts +0 -221
  558. package/src/server/database.test.ts +0 -184
  559. package/src/server/database_api.test.ts +0 -439
  560. package/src/server/filter_builder.test.ts +0 -102
  561. package/src/server/impl/actions_impl.test.ts +0 -59
  562. package/src/server/impl/filter_builder_impl.test.ts +0 -13
  563. package/src/server/impl/query_impl.test.ts +0 -46
  564. package/src/server/pagination.test.ts +0 -49
  565. package/src/server/query.test.ts +0 -112
  566. package/src/server/registration.test.ts +0 -589
  567. package/src/server/router.test.ts +0 -148
  568. package/src/server/scheduler.test.ts +0 -31
  569. package/src/server/schema.test.ts +0 -1081
  570. package/src/test/fake_watch.ts +0 -54
  571. package/src/test/type_testing.ts +0 -21
  572. package/src/type_utils.test.ts +0 -62
  573. package/src/values/size.test.ts +0 -95
  574. package/src/values/validator.test.ts +0 -619
  575. package/src/values/value.test.ts +0 -232
  576. package/src/vendor/README.md +0 -18
  577. package/src/vendor/jwt-decode/README.md +0 -1
@@ -1,1207 +0,0 @@
1
- import child_process from "child_process";
2
-
3
- import { test, expect } from "vitest";
4
- import { Long } from "../../vendor/long.js";
5
- import { createHmac } from "crypto";
6
-
7
- import { BaseConvexClient } from "./client.js";
8
- import {
9
- ActionRequest,
10
- MutationRequest,
11
- parseServerMessage,
12
- RequestId,
13
- WireServerMessage,
14
- } from "./protocol.js";
15
- import {
16
- encodeServerMessage,
17
- nodeWebSocket,
18
- UpdateQueue,
19
- withInMemoryWebSocket,
20
- } from "./client_node_test_helpers.js";
21
- import { FunctionArgs, makeFunctionReference } from "../../server/index.js";
22
-
23
- test("BaseConvexClient protocol in node", async () => {
24
- await withInMemoryWebSocket(async ({ address, receive }) => {
25
- const client = new BaseConvexClient(
26
- address,
27
- () => {
28
- // ignore updates.
29
- },
30
- { webSocketConstructor: nodeWebSocket, unsavedChangesWarning: false },
31
- );
32
-
33
- expect((await receive()).type).toEqual("Connect");
34
- expect((await receive()).type).toEqual("ModifyQuerySet");
35
-
36
- await client.close();
37
- });
38
- });
39
-
40
- // Run the test above in its own Node.js subprocess to ensure that it exists
41
- // cleanly. This is the only point of this test.
42
- test("BaseConvexClient closes cleanly", () => {
43
- const p = child_process.spawnSync(
44
- "node_modules/.bin/vitest",
45
- [
46
- "-t",
47
- "BaseConvexClient protocol in node",
48
- "src/browser/sync/client_node.test.ts",
49
- ],
50
- {
51
- encoding: "utf-8",
52
- timeout: 35000,
53
- stdio: ["pipe", "pipe", "pipe"],
54
- env: {
55
- ...process.env,
56
- FORCE_COLOR: "false",
57
- },
58
- },
59
- );
60
-
61
- // If this is a timeout, the test didn't exit cleanly! Check for timers.
62
- expect(p.status).toBeFalsy();
63
- });
64
-
65
- test("Tests can encode longs in server messages", () => {
66
- const orig: WireServerMessage = {
67
- type: "Transition",
68
- startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) },
69
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(1) },
70
- modifications: [
71
- {
72
- type: "QueryUpdated",
73
- queryId: 0,
74
- value: 0.0,
75
- logLines: ["[LOG] 'Got stuff'"],
76
- journal: null,
77
- },
78
- ],
79
- };
80
- const encoded = encodeServerMessage(orig);
81
- const decoded = parseServerMessage(JSON.parse(encoded));
82
- expect(orig).toEqual(decoded);
83
- });
84
-
85
- // Detects an issue where actions sent before the WebSocket has connected
86
- // are failed upon first connecting.
87
- test("Actions can be called immediately", async () => {
88
- await withInMemoryWebSocket(async ({ address, receive, send }) => {
89
- const client = new BaseConvexClient(address, () => null, {
90
- webSocketConstructor: nodeWebSocket,
91
- unsavedChangesWarning: false,
92
- });
93
- const actionP = client.action("myAction", {});
94
-
95
- expect((await receive()).type).toEqual("Connect");
96
- expect((await receive()).type).toEqual("ModifyQuerySet");
97
- const actionRequest = await receive();
98
- expect(actionRequest.type).toEqual("Action");
99
- const requestId = (actionRequest as ActionRequest).requestId;
100
-
101
- send(actionSuccess(requestId));
102
- expect(await actionP).toBe(42);
103
- await client.close();
104
- });
105
- });
106
-
107
- function actionSuccess(requestId: RequestId): WireServerMessage {
108
- return {
109
- type: "ActionResponse",
110
- requestId: requestId,
111
- success: true,
112
- result: 42,
113
- logLines: [],
114
- };
115
- }
116
-
117
- test("maxObservedTimestamp is updated on mutation and transition", async () => {
118
- await withInMemoryWebSocket(async ({ address, receive, send }) => {
119
- const client = new BaseConvexClient(address, () => null, {
120
- webSocketConstructor: nodeWebSocket,
121
- unsavedChangesWarning: false,
122
- });
123
-
124
- expect(client.getMaxObservedTimestamp()).toBeUndefined();
125
-
126
- const mutationP = client.mutation("myMutation", {});
127
-
128
- expect((await receive()).type).toEqual("Connect");
129
- expect((await receive()).type).toEqual("ModifyQuerySet");
130
- const mutationRequest = await receive();
131
- expect(mutationRequest.type).toEqual("Mutation");
132
- const requestId = (mutationRequest as MutationRequest).requestId;
133
-
134
- // Send a mutation, should update the max observed timestamp.
135
- send({
136
- type: "MutationResponse",
137
- requestId: requestId,
138
- success: true,
139
- result: 42,
140
- ts: Long.fromNumber(1000),
141
- logLines: [],
142
- });
143
- // Wait until getMaxObservedTimestamp() gets updated
144
- for (let i = 0; i < 10; i++) {
145
- if (client.getMaxObservedTimestamp()) {
146
- break;
147
- }
148
- await new Promise((resolve) => setTimeout(resolve, 100));
149
- }
150
- expect(client.getMaxObservedTimestamp()).toEqual(Long.fromNumber(1000));
151
-
152
- // Send a transition from before the mutation. Should not update the max
153
- // observed timestamp nor resolve the mutation.
154
- send({
155
- type: "Transition",
156
- startVersion: {
157
- querySet: 0,
158
- ts: Long.fromNumber(0),
159
- identity: 0,
160
- },
161
- endVersion: {
162
- querySet: 0,
163
- ts: Long.fromNumber(500),
164
- identity: 0,
165
- },
166
- modifications: [],
167
- });
168
-
169
- // Wait a bit and confirm the max timestamp has not been updated.
170
- await new Promise((resolve) => setTimeout(resolve, 200));
171
- expect(client.getMaxObservedTimestamp()).toEqual(Long.fromNumber(1000));
172
-
173
- // Send another transition with higher timestamp. This should resolve the
174
- // transition and advanced the max observable timestamp.
175
- send({
176
- type: "Transition",
177
- startVersion: {
178
- querySet: 0,
179
- ts: Long.fromNumber(500),
180
- identity: 0,
181
- },
182
- endVersion: {
183
- querySet: 0,
184
- ts: Long.fromNumber(2000),
185
- identity: 0,
186
- },
187
- modifications: [],
188
- });
189
- // Wait until the mutation is resolved.
190
- expect(await mutationP).toBe(42);
191
- expect(client.getMaxObservedTimestamp()).toEqual(Long.fromNumber(2000));
192
-
193
- await client.close();
194
- });
195
- });
196
-
197
- const apiQueriesA = makeFunctionReference<"query", {}, string>("queries:a");
198
- const apiQueriesB = makeFunctionReference<"query", {}, string>("queries:b");
199
-
200
- const _apiMutationsZ = makeFunctionReference<"mutation", {}>("mutations:z");
201
-
202
- /**
203
- * Regression test for
204
- * - subscribing to query a
205
- * - running a mutation that sets an optimistic update for queries a and b
206
- * - receiving an update for a
207
- */
208
- test("Setting optimistic updates for queries that have not yet been subscribed to", async () => {
209
- await withInMemoryWebSocket(async ({ address, receive, send }) => {
210
- const q = new UpdateQueue(10);
211
-
212
- const client = new BaseConvexClient(
213
- address,
214
- (queryTokens) => {
215
- q.onTransition(client)(queryTokens);
216
- },
217
- {
218
- webSocketConstructor: nodeWebSocket,
219
- unsavedChangesWarning: false,
220
- verbose: true,
221
- },
222
- );
223
-
224
- client.subscribe("queries:a", {});
225
-
226
- expect((await receive()).type).toEqual("Connect");
227
- const modify = await receive();
228
-
229
- expect(modify.type).toEqual("ModifyQuerySet");
230
- if (modify.type !== "ModifyQuerySet") {
231
- return;
232
- }
233
- expect(modify.modifications.length).toBe(1);
234
- expect(modify.modifications).toEqual([
235
- {
236
- type: "Add",
237
- queryId: 0,
238
- udfPath: "queries:a",
239
- args: [{}],
240
- },
241
- ]);
242
-
243
- // Now that we're subscribed to queries:a,
244
- // run a mutation that, optimistically and on the server,
245
- // - modifies q1
246
- // - modifies q2
247
-
248
- const mutP = client.mutation(
249
- "mutations:z",
250
- {},
251
- {
252
- optimisticUpdate: (
253
- localStore,
254
- _args: FunctionArgs<typeof _apiMutationsZ>,
255
- ) => {
256
- const curA = localStore.getQuery(apiQueriesA, {});
257
- localStore.setQuery(
258
- apiQueriesA,
259
- {},
260
- curA === undefined ? "a local" : `${curA} with a local applied`,
261
- );
262
- const curB = localStore.getQuery(apiQueriesB, {});
263
- localStore.setQuery(
264
- apiQueriesB,
265
- {},
266
- curB === undefined ? "b local" : `${curB} with b local applied`,
267
- );
268
- },
269
- },
270
- );
271
-
272
- // Synchronously, the local store should update and the changes should be broadcast.
273
- expect(client.localQueryResult("queries:a", {})).toEqual("a local");
274
- // We haven't actually subscribed to this query but it had a value set in an optimistic update.
275
- expect(client.localQueryResult("queries:b", {})).toEqual("b local");
276
- const update1 = await q.updatePromises[0];
277
- expect(q.updates).toHaveLength(1);
278
- expect(update1).toEqual({
279
- '{"udfPath":"queries:a","args":{}}': "a local",
280
- '{"udfPath":"queries:b","args":{}}': "b local",
281
- });
282
-
283
- // Now a transition arrives containing only an update to query a.
284
- // This previously crashed this execution context.
285
- send({
286
- type: "Transition",
287
- startVersion: {
288
- querySet: 0,
289
- identity: 0,
290
- ts: Long.fromNumber(0),
291
- },
292
- endVersion: {
293
- querySet: 1,
294
- identity: 0,
295
- ts: Long.fromNumber(100),
296
- },
297
- modifications: [
298
- {
299
- type: "QueryUpdated",
300
- queryId: 0,
301
- value: "a server",
302
- logLines: [],
303
- journal: null,
304
- },
305
- ],
306
- });
307
-
308
- const update2 = await q.updatePromises[1];
309
- expect(update2).toEqual({
310
- '{"udfPath":"queries:a","args":{}}': "a server with a local applied",
311
- '{"udfPath":"queries:b","args":{}}': "b local",
312
- });
313
- expect(q.allResults).toEqual({
314
- '{"udfPath":"queries:a","args":{}}': "a server with a local applied",
315
- '{"udfPath":"queries:b","args":{}}': "b local",
316
- });
317
- expect(q.updates).toHaveLength(2);
318
-
319
- const mutationRequest = await receive();
320
- expect(mutationRequest.type).toEqual("Mutation");
321
- expect(mutationRequest).toEqual({
322
- type: "Mutation",
323
- requestId: 0,
324
- udfPath: "mutations:z",
325
- args: [{}],
326
- });
327
-
328
- // Now the server sends:
329
-
330
- // 1. MutationResponse saying the mutation has run
331
- send({
332
- type: "MutationResponse",
333
- requestId: 0,
334
- success: true,
335
- result: null,
336
- ts: Long.fromNumber(200), // "ZDhuVB3CRxg=", in example
337
- logLines: [],
338
- });
339
-
340
- // 2. Transition bringing us up to date with the mutation
341
- send({
342
- type: "Transition",
343
- startVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(100) },
344
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(200) },
345
- modifications: [
346
- {
347
- type: "QueryUpdated",
348
- queryId: 0,
349
- value: "a server",
350
- logLines: [],
351
- journal: null,
352
- },
353
- ],
354
- });
355
-
356
- expect(await q.updatePromises[2]).toEqual({
357
- '{"udfPath":"queries:a","args":{}}': "a server",
358
- // Now there's no more optimistic value for b!
359
- '{"udfPath":"queries:b","args":{}}': undefined,
360
- });
361
-
362
- // After all that the mutation should resolve.
363
- await mutP;
364
-
365
- await client.close();
366
- }, true);
367
- });
368
-
369
- /**
370
- * Regression test for
371
- * - subscribing to slow query a
372
- * - subscribing to fast query b
373
- * - receiving an update for b, without a
374
- */
375
- test("Query results coming back out of order (fast query first, slower query later)", async () => {
376
- await withInMemoryWebSocket(async ({ address, receive, send }) => {
377
- const q = new UpdateQueue(10);
378
-
379
- const client = new BaseConvexClient(
380
- address,
381
- (queryTokens) => {
382
- q.onTransition(client)(queryTokens);
383
- },
384
- {
385
- webSocketConstructor: nodeWebSocket,
386
- unsavedChangesWarning: false,
387
- verbose: true,
388
- },
389
- );
390
-
391
- client.subscribe("queries:slow", {});
392
-
393
- expect((await receive()).type).toEqual("Connect");
394
- const modify = await receive();
395
-
396
- expect(modify.type).toEqual("ModifyQuerySet");
397
- if (modify.type !== "ModifyQuerySet") {
398
- return;
399
- }
400
- expect(modify.modifications.length).toBe(1);
401
- expect(modify.modifications).toEqual([
402
- {
403
- type: "Add",
404
- queryId: 0,
405
- udfPath: "queries:slow",
406
- args: [{}],
407
- },
408
- ]);
409
-
410
- // Later we subscribe to a fast query
411
- client.subscribe("queries:fast", {});
412
-
413
- const modify2 = await receive();
414
-
415
- expect(modify2.type).toEqual("ModifyQuerySet");
416
- if (modify2.type !== "ModifyQuerySet") {
417
- return;
418
- }
419
- expect(modify2.modifications.length).toBe(1);
420
- expect(modify2.modifications).toEqual([
421
- {
422
- type: "Add",
423
- queryId: 1,
424
- udfPath: "queries:fast",
425
- args: [{}],
426
- },
427
- ]);
428
-
429
- // Once the client has subscribed to queries:slow and queries:fast but has no results for either,
430
- // the server is allowed to respond with a Transition that contains no mutations, "acknowledging"
431
- // the slow query subscription but not responding with a value for it.
432
- send({
433
- type: "Transition",
434
- startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) },
435
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(100) },
436
- modifications: [
437
- // This is unusual, but allowed.
438
- ],
439
- });
440
-
441
- // TODO test what happens when this first Transition contains an update for a query that does not exist in this query set.
442
-
443
- // apparently this triggers an update???
444
- const update1 = await q.awaitPromiseAtIndexWithTimeout(0);
445
- expect(update1).toEqual({});
446
-
447
- // Later the server sends a fast result
448
- send({
449
- type: "Transition",
450
- startVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(100) },
451
- endVersion: { querySet: 2, identity: 0, ts: Long.fromNumber(200) },
452
- modifications: [
453
- {
454
- type: "QueryUpdated",
455
- queryId: 1,
456
- value: "fast result",
457
- logLines: [],
458
- journal: null,
459
- },
460
- ],
461
- });
462
- const update2 = await q.awaitPromiseAtIndexWithTimeout(1);
463
-
464
- expect(update2).toStrictEqual({
465
- '{"udfPath":"queries:fast","args":{}}': "fast result",
466
- });
467
- expect(q.allResults).toStrictEqual({
468
- '{"udfPath":"queries:fast","args":{}}': "fast result",
469
- });
470
- expect(q.updates).toHaveLength(2);
471
-
472
- expect(client.localQueryResult("queries:fast", {})).toEqual("fast result");
473
- expect(client.localQueryResult("queries:slow", {})).toEqual(undefined);
474
-
475
- // Later the server sends a slow result
476
- send({
477
- type: "Transition",
478
- startVersion: { querySet: 2, identity: 0, ts: Long.fromNumber(200) },
479
- endVersion: { querySet: 2, identity: 0, ts: Long.fromNumber(300) },
480
- modifications: [
481
- {
482
- type: "QueryUpdated",
483
- queryId: 0,
484
- value: "slow result",
485
- logLines: [],
486
- journal: null,
487
- },
488
- ],
489
- });
490
- const update3 = await q.awaitPromiseAtIndexWithTimeout(2);
491
-
492
- expect(update3).toStrictEqual({
493
- '{"udfPath":"queries:slow","args":{}}': "slow result",
494
- });
495
- expect(q.allResults).toStrictEqual({
496
- '{"udfPath":"queries:fast","args":{}}': "fast result",
497
- '{"udfPath":"queries:slow","args":{}}': "slow result",
498
- });
499
- expect(q.updates).toHaveLength(3);
500
-
501
- expect(client.localQueryResult("queries:fast", {})).toEqual("fast result");
502
- expect(client.localQueryResult("queries:slow", {})).toEqual("slow result");
503
-
504
- await client.close();
505
- }, true);
506
- });
507
-
508
- /**
509
- * Test to characterize behavior so we know if it changes. This behavior is not relied upon,
510
- * we consider it a protocol error, but it does happen to work.
511
- *
512
- * - subscribe to slow query (query 0) (querySet 1)
513
- * - subscribe to fast query (query 1) (querySet 2)
514
- * - server sends message transitioning to querySet 1 that includes result for only the fast query (!)
515
- * This works! The fast query result is not dropped on the floor.
516
- * - server send message transitioning to querySet 2, plus it includes slow query.
517
- */
518
- test("Transition contains result for query not in purported query set version", async () => {
519
- await withInMemoryWebSocket(async ({ address, receive, send }) => {
520
- const q = new UpdateQueue(10);
521
-
522
- const client = new BaseConvexClient(
523
- address,
524
- (queryTokens) => {
525
- q.onTransition(client)(queryTokens);
526
- },
527
- {
528
- webSocketConstructor: nodeWebSocket,
529
- unsavedChangesWarning: false,
530
- verbose: true,
531
- },
532
- );
533
-
534
- // Subscribe to slow query first
535
- client.subscribe("queries:slow", {});
536
-
537
- expect((await receive()).type).toEqual("Connect");
538
- const modify1 = await receive();
539
-
540
- expect(modify1.type).toEqual("ModifyQuerySet");
541
- if (modify1.type !== "ModifyQuerySet") {
542
- return;
543
- }
544
- expect(modify1.modifications).toEqual([
545
- {
546
- type: "Add",
547
- queryId: 0,
548
- udfPath: "queries:slow",
549
- args: [{}],
550
- },
551
- ]);
552
-
553
- // Then subscribe to fast query
554
- client.subscribe("queries:fast", {});
555
-
556
- const modify2 = await receive();
557
- expect(modify2.type).toEqual("ModifyQuerySet");
558
- if (modify2.type !== "ModifyQuerySet") {
559
- return;
560
- }
561
- expect(modify2.modifications).toEqual([
562
- {
563
- type: "Add",
564
- queryId: 1,
565
- udfPath: "queries:fast",
566
- args: [{}],
567
- },
568
- ]);
569
-
570
- // Server sends malformed Transition: claims querySet version 1 (only slow query)
571
- // but includes result for queryId 1 (fast query) which should be in querySet version 2
572
- send({
573
- type: "Transition",
574
- startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) },
575
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(100) },
576
- modifications: [
577
- {
578
- type: "QueryUpdated",
579
- queryId: 1, // But provides result for fast query!
580
- value: "fast result from malformed transition",
581
- logLines: [],
582
- journal: null,
583
- },
584
- ],
585
- });
586
-
587
- // Client should still process the result (the client is forgiving)
588
- const update1 = await q.awaitPromiseAtIndexWithTimeout(0);
589
- expect(update1).toEqual({
590
- '{"udfPath":"queries:fast","args":{}}':
591
- "fast result from malformed transition",
592
- });
593
-
594
- // The fast query result should be available
595
- expect(client.localQueryResult("queries:fast", {})).toEqual(
596
- "fast result from malformed transition",
597
- );
598
- expect(client.localQueryResult("queries:slow", {})).toEqual(undefined);
599
-
600
- // Next transition should work normally
601
- send({
602
- type: "Transition",
603
- startVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(100) },
604
- endVersion: { querySet: 2, identity: 0, ts: Long.fromNumber(200) },
605
- modifications: [
606
- {
607
- type: "QueryUpdated",
608
- queryId: 0,
609
- value: "slow result",
610
- logLines: [],
611
- journal: null,
612
- },
613
- ],
614
- });
615
-
616
- const update2 = await q.awaitPromiseAtIndexWithTimeout(1);
617
- expect(update2).toEqual({
618
- '{"udfPath":"queries:slow","args":{}}': "slow result",
619
- });
620
-
621
- // Both results should be available and the fast query result should persist
622
- expect(client.localQueryResult("queries:fast", {})).toEqual(
623
- "fast result from malformed transition",
624
- );
625
- expect(client.localQueryResult("queries:slow", {})).toEqual("slow result");
626
-
627
- await client.close();
628
- }, true);
629
- });
630
-
631
- /**
632
- * Test to characterize existing behavior that we may want to change.
633
- *
634
- * - subscribe to a query
635
- * - get a result
636
- * - get a new "result" (Transition with QueryRemoved modification) that, if you didn't know better,
637
- * you might send from the server to indicate this result is now loading
638
- * - get a new real result (Transition with QueryUpdated modification)
639
- *
640
- * One might expect the client to publish updates "result, loading, result,"
641
- * but the client only publishes "result."
642
- *
643
- * Currently the client stops tracking a query when it receives QueryRemoved
644
- * from the server (it stops tracking it in the RemoteQuerySet).
645
- */
646
- test("Query unsubscription triggers empty transition for listeners", async () => {
647
- await withInMemoryWebSocket(async ({ address, receive, send }) => {
648
- const q = new UpdateQueue(10);
649
-
650
- const client = new BaseConvexClient(
651
- address,
652
- (queryTokens) => {
653
- q.onTransition(client)(queryTokens);
654
- },
655
- {
656
- webSocketConstructor: nodeWebSocket,
657
- unsavedChangesWarning: false,
658
- verbose: true,
659
- },
660
- );
661
-
662
- client.subscribe("queries:test", {});
663
-
664
- expect((await receive()).type).toEqual("Connect");
665
- const modify1 = await receive();
666
-
667
- expect(modify1.type).toEqual("ModifyQuerySet");
668
- if (modify1.type !== "ModifyQuerySet") {
669
- return;
670
- }
671
- expect(modify1.modifications).toEqual([
672
- {
673
- type: "Add",
674
- queryId: 0,
675
- udfPath: "queries:test",
676
- args: [{}],
677
- },
678
- ]);
679
-
680
- // Server sends result for the query
681
- send({
682
- type: "Transition",
683
- startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) },
684
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(100) },
685
- modifications: [
686
- {
687
- type: "QueryUpdated",
688
- queryId: 0,
689
- value: "test result",
690
- logLines: [],
691
- journal: null,
692
- },
693
- ],
694
- });
695
-
696
- const update1 = await q.awaitPromiseAtIndexWithTimeout(0);
697
- expect(update1).toEqual({
698
- '{"udfPath":"queries:test","args":{}}': "test result",
699
- });
700
- expect(q.allResults).toStrictEqual({
701
- '{"udfPath":"queries:test","args":{}}': "test result",
702
- });
703
- expect(client.localQueryResult("queries:test", {})).toEqual("test result");
704
-
705
- // "QueryRemoved" from the server communicates that this query is now in an loading state.
706
- send({
707
- type: "Transition",
708
- startVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(100) },
709
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(200) },
710
- modifications: [
711
- {
712
- type: "QueryRemoved",
713
- queryId: 0,
714
- },
715
- ],
716
- });
717
-
718
- // The update received contains nothing so there's no notification
719
- // that this has gone back to undefined!
720
- const update2 = await q.awaitPromiseAtIndexWithTimeout(1);
721
-
722
- // What we wish happened, if removing a query is supposed to be
723
- // the same as setting it to undefined.
724
- /*
725
- expect(update2).toStrictEqual({
726
- '{"udfPath":"queries:test","args":{}}': undefined,
727
- });
728
- */
729
- // what actually happens
730
- expect(update2).toStrictEqual({});
731
-
732
- expect(q.updates).toHaveLength(2);
733
-
734
- // The query result is no longer available locally after removal...
735
- expect(client.localQueryResult("queries:test", {})).toEqual(undefined);
736
-
737
- // ...but anyone listening won't have been updated.
738
- expect(q.allResults).toEqual({
739
- '{"udfPath":"queries:test","args":{}}': "test result",
740
- });
741
- // So e.g. a useQuery() React hook would return the correct value (undefined),
742
- // but that component would not be triggered to rerender. The displayed result
743
- // will be stale until the component is rerendered for some other reason.
744
-
745
- // What if we set a result again?
746
- send({
747
- type: "Transition",
748
- startVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(200) },
749
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(300) },
750
- modifications: [
751
- {
752
- type: "QueryUpdated",
753
- queryId: 0,
754
- value: "new test result",
755
- logLines: [],
756
- journal: null,
757
- },
758
- ],
759
- });
760
-
761
- // What we might expect to happen if removing a query were equivalent to
762
- // "updating the query to loading" and setting a value after worked:
763
- /*
764
- const update3 = await q.awaitPromiseAtIndexWithTimeout(2);
765
- expect(update3).toEqual({
766
- '{"udfPath":"queries:test","args":{}}': "new test result",
767
- });
768
- expect(q.allResults).toStrictEqual({
769
- '{"udfPath":"queries:test","args":{}}': "new test result",
770
- });
771
- */
772
- // what actually happens
773
- // wait a macrotask just in case
774
- //await new Promise((r) => setTimeout(r, 0));
775
- expect(q.updates).toHaveLength(2);
776
-
777
- // This result is no longer tracked!
778
- expect(client.localQueryResult("queries:test", {})).toEqual(undefined);
779
-
780
- await client.close();
781
- }, true);
782
- });
783
-
784
- test("TransitionChunk messages are assembled into a Transition", async () => {
785
- await withInMemoryWebSocket(async ({ address, receive, send }) => {
786
- const client = new BaseConvexClient(address, () => null, {
787
- webSocketConstructor: nodeWebSocket,
788
- unsavedChangesWarning: false,
789
- });
790
- expect((await receive()).type).toEqual("Connect");
791
- expect((await receive()).type).toEqual("ModifyQuerySet");
792
-
793
- const fullTransition: WireServerMessage = {
794
- type: "Transition",
795
- startVersion: {
796
- querySet: 0,
797
- ts: Long.fromNumber(0),
798
- identity: 0,
799
- },
800
- endVersion: {
801
- querySet: 1,
802
- ts: Long.fromNumber(1000),
803
- identity: 0,
804
- },
805
- modifications: [
806
- {
807
- type: "QueryUpdated",
808
- queryId: 0,
809
- value: { result: "chunk test data" },
810
- logLines: [],
811
- journal: null,
812
- },
813
- ],
814
- };
815
-
816
- const fullJson = encodeServerMessage(fullTransition);
817
- const midpoint = Math.floor(fullJson.length / 2);
818
- const chunk1 = fullJson.substring(0, midpoint);
819
- const chunk2 = fullJson.substring(midpoint);
820
-
821
- const transitionId = "12345";
822
-
823
- send({
824
- type: "TransitionChunk",
825
- chunk: chunk1,
826
- partNumber: 0,
827
- totalParts: 2,
828
- transitionId,
829
- });
830
-
831
- expect(client.getMaxObservedTimestamp()).toBeUndefined();
832
-
833
- send({
834
- type: "TransitionChunk",
835
- chunk: chunk2,
836
- partNumber: 1,
837
- totalParts: 2,
838
- transitionId,
839
- });
840
-
841
- // synchronously, it's still undefined
842
- expect(client.getMaxObservedTimestamp()).toEqual(undefined);
843
-
844
- for (let i = 0; i < 10; i++) {
845
- if (client.getMaxObservedTimestamp()) {
846
- break;
847
- }
848
- await new Promise((resolve) => setTimeout(resolve, 100));
849
- }
850
-
851
- expect(client.getMaxObservedTimestamp()).toEqual(Long.fromNumber(1000));
852
-
853
- await client.close();
854
- });
855
- });
856
-
857
- test("Backoff does not reset when queries synced but mutation is still inflight", async () => {
858
- await withInMemoryWebSocket(async ({ address, receive, send, close }) => {
859
- const client = new BaseConvexClient(address, () => null, {
860
- webSocketConstructor: nodeWebSocket,
861
- unsavedChangesWarning: false,
862
- });
863
-
864
- client.subscribe("queries:myQuery", {});
865
-
866
- expect((await receive()).type).toEqual("Connect");
867
- expect((await receive()).type).toEqual("ModifyQuerySet");
868
-
869
- send({
870
- type: "Transition",
871
- startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) },
872
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(100) },
873
- modifications: [
874
- {
875
- type: "QueryUpdated",
876
- queryId: 0,
877
- value: "result",
878
- logLines: [],
879
- journal: null,
880
- },
881
- ],
882
- });
883
-
884
- for (let i = 0; i < 20; i++) {
885
- if (client.localQueryResult("queries:myQuery", {}) === "result") break;
886
- await new Promise((r) => setTimeout(r, 50));
887
- }
888
- expect(client.connectionState().connectionRetries).toBe(0);
889
-
890
- // Start a mutation, then server closes while it's inflight
891
- const mutP = client.mutation("myMutation", {});
892
- const mutReq = await receive();
893
- expect(mutReq.type).toEqual("Mutation");
894
- const requestId = (mutReq as MutationRequest).requestId;
895
-
896
- close();
897
-
898
- expect((await receive()).type).toEqual("Connect");
899
- expect(client.connectionState().connectionRetries).toBeGreaterThan(0);
900
- expect((await receive()).type).toEqual("ModifyQuerySet");
901
- expect((await receive()).type).toEqual("Mutation");
902
-
903
- // Server sends query results but NOT mutation response
904
- send({
905
- type: "Transition",
906
- startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) },
907
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(200) },
908
- modifications: [
909
- {
910
- type: "QueryUpdated",
911
- queryId: 0,
912
- value: "result 2",
913
- logLines: [],
914
- journal: null,
915
- },
916
- ],
917
- });
918
-
919
- for (let i = 0; i < 20; i++) {
920
- if (client.localQueryResult("queries:myQuery", {}) === "result 2") break;
921
- await new Promise((r) => setTimeout(r, 50));
922
- }
923
-
924
- // Retries should NOT reset — mutation is still inflight
925
- expect(client.connectionState().connectionRetries).toBeGreaterThan(0);
926
-
927
- // Now complete the mutation
928
- send({
929
- type: "MutationResponse",
930
- requestId: requestId,
931
- success: true,
932
- result: null,
933
- ts: Long.fromNumber(300),
934
- logLines: [],
935
- });
936
- send({
937
- type: "Transition",
938
- startVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(200) },
939
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(400) },
940
- modifications: [],
941
- });
942
-
943
- await mutP;
944
-
945
- // Both queries and mutations synced — retries should reset
946
- expect(client.connectionState().connectionRetries).toBe(0);
947
-
948
- await client.close();
949
- });
950
- });
951
-
952
- test("Backoff does not reset for idle client until server re-confirms queries", async () => {
953
- await withInMemoryWebSocket(async ({ address, receive, send, close }) => {
954
- const client = new BaseConvexClient(address, () => null, {
955
- webSocketConstructor: nodeWebSocket,
956
- unsavedChangesWarning: false,
957
- });
958
-
959
- client.subscribe("queries:myQuery", {});
960
-
961
- expect((await receive()).type).toEqual("Connect");
962
- expect((await receive()).type).toEqual("ModifyQuerySet");
963
-
964
- send({
965
- type: "Transition",
966
- startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) },
967
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(100) },
968
- modifications: [
969
- {
970
- type: "QueryUpdated",
971
- queryId: 0,
972
- value: "result",
973
- logLines: [],
974
- journal: null,
975
- },
976
- ],
977
- });
978
-
979
- for (let i = 0; i < 20; i++) {
980
- if (client.localQueryResult("queries:myQuery", {}) === "result") break;
981
- await new Promise((r) => setTimeout(r, 50));
982
- }
983
- expect(client.connectionState().connectionRetries).toBe(0);
984
-
985
- // Server closes (idle client, no mutations in flight)
986
- close();
987
-
988
- expect((await receive()).type).toEqual("Connect");
989
- expect(client.connectionState().connectionRetries).toBeGreaterThan(0);
990
- expect((await receive()).type).toEqual("ModifyQuerySet");
991
-
992
- // Empty transition — query not re-confirmed yet, retries should hold
993
- send({
994
- type: "Transition",
995
- startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) },
996
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(150) },
997
- modifications: [],
998
- });
999
- await new Promise((r) => setTimeout(r, 100));
1000
- expect(client.connectionState().connectionRetries).toBeGreaterThan(0);
1001
-
1002
- // Server re-confirms the query
1003
- send({
1004
- type: "Transition",
1005
- startVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(150) },
1006
- endVersion: { querySet: 1, identity: 0, ts: Long.fromNumber(200) },
1007
- modifications: [
1008
- {
1009
- type: "QueryUpdated",
1010
- queryId: 0,
1011
- value: "result refreshed",
1012
- logLines: [],
1013
- journal: null,
1014
- },
1015
- ],
1016
- });
1017
-
1018
- for (let i = 0; i < 20; i++) {
1019
- if (client.localQueryResult("queries:myQuery", {}) === "result refreshed")
1020
- break;
1021
- await new Promise((r) => setTimeout(r, 50));
1022
- }
1023
-
1024
- // Query re-confirmed — retries should reset
1025
- expect(client.connectionState().connectionRetries).toBe(0);
1026
-
1027
- await client.close();
1028
- });
1029
- });
1030
-
1031
- // We had an issue where fixing a bug related to having the client do proper exponential backoff
1032
- // resulted in revealing that if a client was authenticated and had a WebSocket disconnect, the
1033
- // count of retries would never get reset upon reconnect. This test covers that scenario.
1034
- test("Retries do not increase across connections for auth'd clients", async () => {
1035
- await withInMemoryWebSocket(async ({ address, receive, send, close }) => {
1036
- const client = new BaseConvexClient(address, () => null, {
1037
- webSocketConstructor: nodeWebSocket,
1038
- unsavedChangesWarning: false,
1039
- logger: true,
1040
- verbose: true,
1041
- });
1042
-
1043
- // Setup auth
1044
- const iat = Math.floor(Date.now() / 1000);
1045
- const exp = iat + 3600;
1046
- const token = encodeJwt({ sub: "user_123", exp, iat }, "test-secret");
1047
- client.setAuth(
1048
- async () => token,
1049
- (_) => {},
1050
- );
1051
-
1052
- // Verify client handshake on "server" side.
1053
- expect((await receive()).type).toEqual("Connect");
1054
- expect((await receive()).type).toEqual("Authenticate");
1055
- expect((await receive()).type).toEqual("ModifyQuerySet");
1056
-
1057
- // Respond to the handshake noting that the identity was accepted (increased version).
1058
- send({
1059
- type: "Transition",
1060
- startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) },
1061
- endVersion: { querySet: 0, identity: 1, ts: Long.fromNumber(100) },
1062
- modifications: [],
1063
- });
1064
-
1065
- // Subscribe to a query and verify the "server" receives it.
1066
- client.subscribe("queries:myQuery", {});
1067
- expect((await receive()).type).toEqual("ModifyQuerySet");
1068
-
1069
- // Respond to the subscription with a result.
1070
- send({
1071
- type: "Transition",
1072
- startVersion: { querySet: 0, identity: 1, ts: Long.fromNumber(100) },
1073
- endVersion: { querySet: 1, identity: 1, ts: Long.fromNumber(200) },
1074
- modifications: [
1075
- {
1076
- type: "QueryUpdated",
1077
- queryId: 0,
1078
- value: "result",
1079
- logLines: [],
1080
- journal: null,
1081
- },
1082
- ],
1083
- });
1084
-
1085
- // Verify the client gets the subscription result.
1086
- for (let i = 0; i < 20; i++) {
1087
- if (client.localQueryResult("queries:myQuery", {}) === "result") break;
1088
- await new Promise((r) => setTimeout(r, 50));
1089
- }
1090
- expect(client.localQueryResult("queries:myQuery", {})).toEqual("result");
1091
-
1092
- // Unceremoniously drop the connection.
1093
- close();
1094
-
1095
- // The "server" should see the client handshake for a reconnect.
1096
- expect((await receive()).type).toEqual("Connect");
1097
- expect((await receive()).type).toEqual("Authenticate");
1098
- expect((await receive()).type).toEqual("ModifyQuerySet");
1099
-
1100
- // The client should record that it has begun a retry.
1101
- expect(client.connectionState().connectionRetries).toBe(1);
1102
-
1103
- // Respond to the handshake noting that the identity was accepted (increased version).
1104
- send({
1105
- type: "Transition",
1106
- startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) },
1107
- endVersion: { querySet: 0, identity: 1, ts: Long.fromNumber(100) },
1108
- modifications: [],
1109
- });
1110
- // Let client handle the transition.
1111
- await new Promise((r) => setTimeout(r, 100));
1112
-
1113
- // Respond to the re-subscription with a result.
1114
- send({
1115
- type: "Transition",
1116
- startVersion: { querySet: 0, identity: 1, ts: Long.fromNumber(100) },
1117
- endVersion: { querySet: 1, identity: 1, ts: Long.fromNumber(200) },
1118
- modifications: [
1119
- {
1120
- type: "QueryUpdated",
1121
- queryId: 0,
1122
- value: "updated result",
1123
- logLines: [],
1124
- journal: null,
1125
- },
1126
- ],
1127
- });
1128
-
1129
- for (let i = 0; i < 20; i++) {
1130
- if (client.localQueryResult("queries:myQuery", {}) === "updated result")
1131
- break;
1132
- await new Promise((r) => setTimeout(r, 50));
1133
- }
1134
- // Verify the client gets the subscription result.
1135
- expect(client.localQueryResult("queries:myQuery", {})).toEqual(
1136
- "updated result",
1137
- );
1138
-
1139
- // Client has resynced - should be at 0 retries
1140
- expect(client.connectionState().connectionRetries).toBe(0);
1141
- });
1142
- });
1143
-
1144
- // https://github.com/get-convex/convex-js/issues/148
1145
- // When using expectAuth, the socket starts paused. Once the WebSocket connects
1146
- // (while still paused), the paused state becomes "uninitialized". When auth
1147
- // completes and resume() is called, hasEverConnected should become true.
1148
- test("hasEverConnected is true after expectAuth resume", async () => {
1149
- await withInMemoryWebSocket(async ({ address, receive, send }) => {
1150
- // expectAuth causes the socket to start in paused state.
1151
- const client = new BaseConvexClient(address, () => null, {
1152
- webSocketConstructor: nodeWebSocket,
1153
- unsavedChangesWarning: false,
1154
- expectAuth: true,
1155
- });
1156
-
1157
- // Before auth, socket is paused so hasEverConnected should be false.
1158
- expect(client.connectionState().hasEverConnected).toBe(false);
1159
-
1160
- // Set auth with a delayed token fetch. The delay ensures the WebSocket
1161
- // connects while the token is being fetched, causing the socket to enter
1162
- // the ready+uninitialized state (the buggy path).
1163
- const iat = Math.floor(Date.now() / 1000);
1164
- const exp = iat + 3600;
1165
- const token = encodeJwt({ sub: "user_123", exp, iat }, "test-secret");
1166
- client.setAuth(
1167
- async () => {
1168
- await new Promise((r) => setTimeout(r, 100));
1169
- return token;
1170
- },
1171
- (_) => {},
1172
- );
1173
-
1174
- // After resume, the deferred onOpen fires and sends Connect + auth messages.
1175
- expect((await receive()).type).toEqual("Connect");
1176
- expect((await receive()).type).toEqual("Authenticate");
1177
- expect((await receive()).type).toEqual("ModifyQuerySet");
1178
-
1179
- // Respond to the handshake noting that the identity was accepted.
1180
- send({
1181
- type: "Transition",
1182
- startVersion: { querySet: 0, identity: 0, ts: Long.fromNumber(0) },
1183
- endVersion: { querySet: 0, identity: 1, ts: Long.fromNumber(100) },
1184
- modifications: [],
1185
- });
1186
-
1187
- // Let the client process the transition.
1188
- await new Promise((r) => setTimeout(r, 100));
1189
-
1190
- // After auth completes and socket is resumed, hasEverConnected should be true.
1191
- expect(client.connectionState().isWebSocketConnected).toBe(true);
1192
- expect(client.connectionState().hasEverConnected).toBe(true);
1193
-
1194
- await client.close();
1195
- });
1196
- });
1197
-
1198
- function encodeJwt(payload: object, secret: string): string {
1199
- const header = Buffer.from(
1200
- JSON.stringify({ alg: "HS256", typ: "JWT" }),
1201
- ).toString("base64url");
1202
- const body = Buffer.from(JSON.stringify(payload)).toString("base64url");
1203
- const sig = createHmac("sha256", secret)
1204
- .update(`${header}.${body}`)
1205
- .digest("base64url");
1206
- return `${header}.${body}.${sig}`;
1207
- }