convex 1.17.3 → 1.17.5-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 (89) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/dist/browser.bundle.js +105 -23
  3. package/dist/browser.bundle.js.map +2 -2
  4. package/dist/cjs/browser/sync/client.js +93 -15
  5. package/dist/cjs/browser/sync/client.js.map +2 -2
  6. package/dist/cjs/browser/sync/request_manager.js +11 -7
  7. package/dist/cjs/browser/sync/request_manager.js.map +2 -2
  8. package/dist/cjs/cli/deploy.js +1 -1
  9. package/dist/cjs/cli/deploy.js.map +2 -2
  10. package/dist/cjs/cli/dev.js +4 -1
  11. package/dist/cjs/cli/dev.js.map +2 -2
  12. package/dist/cjs/cli/lib/utils/utils.js.map +1 -1
  13. package/dist/cjs/index.js +1 -1
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/cjs/react/use_paginated_query.js +1 -1
  16. package/dist/cjs/react/use_paginated_query.js.map +2 -2
  17. package/dist/cjs/react-clerk/ConvexProviderWithClerk.js +2 -1
  18. package/dist/cjs/react-clerk/ConvexProviderWithClerk.js.map +2 -2
  19. package/dist/cjs/server/data_model.js.map +1 -1
  20. package/dist/cjs/server/impl/registration_impl.js +25 -14
  21. package/dist/cjs/server/impl/registration_impl.js.map +2 -2
  22. package/dist/cjs/server/registration.js.map +1 -1
  23. package/dist/cjs-types/browser/sync/client.d.ts +47 -3
  24. package/dist/cjs-types/browser/sync/client.d.ts.map +1 -1
  25. package/dist/cjs-types/browser/sync/request_manager.d.ts +5 -2
  26. package/dist/cjs-types/browser/sync/request_manager.d.ts.map +1 -1
  27. package/dist/cjs-types/cli/dev.d.ts +1 -0
  28. package/dist/cjs-types/cli/dev.d.ts.map +1 -1
  29. package/dist/cjs-types/cli/lib/utils/utils.d.ts +1 -1
  30. package/dist/cjs-types/cli/lib/utils/utils.d.ts.map +1 -1
  31. package/dist/cjs-types/index.d.ts +1 -1
  32. package/dist/cjs-types/index.d.ts.map +1 -1
  33. package/dist/cjs-types/react/use_paginated_query.d.ts.map +1 -1
  34. package/dist/cjs-types/server/data_model.d.ts +1 -1
  35. package/dist/cjs-types/server/data_model.d.ts.map +1 -1
  36. package/dist/cjs-types/server/impl/registration_impl.d.ts.map +1 -1
  37. package/dist/cjs-types/server/registration.d.ts +1 -1
  38. package/dist/cjs-types/server/registration.d.ts.map +1 -1
  39. package/dist/cli.bundle.cjs +13601 -14245
  40. package/dist/cli.bundle.cjs.map +4 -4
  41. package/dist/esm/browser/sync/client.js +93 -15
  42. package/dist/esm/browser/sync/client.js.map +2 -2
  43. package/dist/esm/browser/sync/request_manager.js +11 -7
  44. package/dist/esm/browser/sync/request_manager.js.map +2 -2
  45. package/dist/esm/cli/deploy.js +1 -1
  46. package/dist/esm/cli/deploy.js.map +2 -2
  47. package/dist/esm/cli/dev.js +4 -1
  48. package/dist/esm/cli/dev.js.map +2 -2
  49. package/dist/esm/cli/lib/utils/utils.js.map +1 -1
  50. package/dist/esm/index.js +1 -1
  51. package/dist/esm/index.js.map +1 -1
  52. package/dist/esm/react/use_paginated_query.js +2 -2
  53. package/dist/esm/react/use_paginated_query.js.map +2 -2
  54. package/dist/esm/react-clerk/ConvexProviderWithClerk.js +2 -1
  55. package/dist/esm/react-clerk/ConvexProviderWithClerk.js.map +2 -2
  56. package/dist/esm/server/impl/registration_impl.js +25 -14
  57. package/dist/esm/server/impl/registration_impl.js.map +2 -2
  58. package/dist/esm-types/browser/sync/client.d.ts +47 -3
  59. package/dist/esm-types/browser/sync/client.d.ts.map +1 -1
  60. package/dist/esm-types/browser/sync/request_manager.d.ts +5 -2
  61. package/dist/esm-types/browser/sync/request_manager.d.ts.map +1 -1
  62. package/dist/esm-types/cli/dev.d.ts +1 -0
  63. package/dist/esm-types/cli/dev.d.ts.map +1 -1
  64. package/dist/esm-types/cli/lib/utils/utils.d.ts +1 -1
  65. package/dist/esm-types/cli/lib/utils/utils.d.ts.map +1 -1
  66. package/dist/esm-types/index.d.ts +1 -1
  67. package/dist/esm-types/index.d.ts.map +1 -1
  68. package/dist/esm-types/react/use_paginated_query.d.ts.map +1 -1
  69. package/dist/esm-types/server/data_model.d.ts +1 -1
  70. package/dist/esm-types/server/data_model.d.ts.map +1 -1
  71. package/dist/esm-types/server/impl/registration_impl.d.ts.map +1 -1
  72. package/dist/esm-types/server/registration.d.ts +1 -1
  73. package/dist/esm-types/server/registration.d.ts.map +1 -1
  74. package/dist/react.bundle.js +106 -24
  75. package/dist/react.bundle.js.map +2 -2
  76. package/package.json +34 -34
  77. package/src/browser/sync/client.ts +131 -14
  78. package/src/browser/sync/request_manager.ts +24 -19
  79. package/src/cli/deploy.ts +3 -1
  80. package/src/cli/dev.ts +5 -0
  81. package/src/cli/lib/utils/utils.ts +1 -1
  82. package/src/index.ts +1 -1
  83. package/src/react/use_paginated_query.ts +8 -2
  84. package/src/react-clerk/ConvexProviderWithClerk.tsx +3 -2
  85. package/src/server/data_model.test.ts +9 -0
  86. package/src/server/data_model.ts +10 -1
  87. package/src/server/impl/registration_impl.ts +43 -19
  88. package/src/server/registration.test.ts +30 -0
  89. package/src/server/registration.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,76 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ - Warn on direct Convex function call. This adds a console.warn whenever a
6
+ Convex Function (mutation, query, action, internalMutation, etc.) is called
7
+ directly
8
+
9
+ ```ts
10
+ export const foo = mutation(...);
11
+
12
+ export const bar = mutation({
13
+ args: v.any(),
14
+ returns: v.any(),
15
+ handler: (ctx, args) => {
16
+ const result = await foo();
17
+ })
18
+ }
19
+ ```
20
+
21
+ because this pattern causes problems and there are straightforward
22
+ workarounds. The problems here:
23
+
24
+ 1. Arguments and return values aren't validated despite the presence of
25
+ validators at the function definition site.
26
+ 2. Functions called this way unexpectedly lack isolation and atomicity. Convex
27
+ functions may be writting assuming they will run as independent
28
+ transactions, but running these function directly breaks that assumption.
29
+ 3. Running Convex functions defined by customFunctions like triggers can cause
30
+ deadlocks and other bad behavior.
31
+
32
+ There are two options for how to modify your code to address the warning:
33
+
34
+ 1. Refactor it out as a helper function, then call that helper function
35
+ directly.
36
+ 2. Use `ctx.runMutation`, `ctx.runQuery`, or `ctx.runAction()` instead of
37
+ calling the function directly. This has more overhead (it's slower) but you
38
+ gain isolation and atomicity because it runs as a subtransaction.
39
+
40
+ See
41
+ https://docs.convex.dev/production/best-practices/#use-helper-functions-to-write-shared-code
42
+ for more.
43
+
44
+ Filter to warnings in the convex dashboard logs to see if you're using this
45
+ pattern.
46
+
47
+ For now running functions this way only logs a warning, but this pattern is
48
+ now deprecated and may be deleted in a future version.
49
+
50
+ - Support for Next.js 15 and
51
+ [Clerk core 2](https://clerk.com/docs/upgrade-guides/core-2/overview):
52
+ `@clerk/nextjs@5` and `@clerk/nextjs@6` are now known to work to Convex. Docs,
53
+ quickstarts and templates have not yet been updated. If you're upgrading
54
+ `@clerk/nextjs` be sure to follow the Clerk upgrade guides as there are many
55
+ breaking changes.
56
+
57
+ - Fix type for FieldTypeFromFieldPath with optional objects.
58
+
59
+ - Fix types when a handler returns a promise when using return value validators
60
+ with object syntax.
61
+
62
+ ## 1.17.4
63
+
64
+ - Revert use of the identity of useAuth from Clerk to determine whether
65
+ refreshing auth is necessary. This was causing an auth loop in Expo.
66
+
67
+ ## 1.17.3
68
+
69
+ - Fetch a new JWT from Clerk when using Clerk components to change the active
70
+ orgId or orgRole in React on the client. Any auth provider can implement this
71
+ by returning a new `getToken` function from the `useAuth` hook passed into
72
+ `ConvexProviderWithAuth`.
73
+
3
74
  ## 1.17.3
4
75
 
5
76
  - Fetch a new JWT from Clerk when using CLerk components to change the active
@@ -28,7 +28,7 @@ var convex = (() => {
28
28
  });
29
29
 
30
30
  // src/index.ts
31
- var version = "1.17.3";
31
+ var version = "1.17.5-alpha.0";
32
32
 
33
33
  // src/values/base64.ts
34
34
  var base64_exports = {};
@@ -931,32 +931,36 @@ var convex = (() => {
931
931
  logForFunction(this.logger, "info", udfType, udfPath, line);
932
932
  }
933
933
  const status = requestInfo.status;
934
+ let result;
934
935
  let onResolve;
935
936
  if (response.success) {
936
- onResolve = () => status.onResult({
937
+ result = {
937
938
  success: true,
938
939
  logLines: response.logLines,
939
940
  value: jsonToConvex(response.result)
940
- });
941
+ };
942
+ onResolve = () => status.onResult(result);
941
943
  } else {
942
944
  const errorMessage = response.result;
943
945
  const { errorData } = response;
944
946
  logForFunction(this.logger, "error", udfType, udfPath, errorMessage);
945
- onResolve = () => status.onResult({
947
+ result = {
946
948
  success: false,
947
949
  errorMessage,
948
950
  errorData: errorData !== void 0 ? jsonToConvex(errorData) : void 0,
949
951
  logLines: response.logLines
950
- });
952
+ };
953
+ onResolve = () => status.onResult(result);
951
954
  }
952
955
  if (response.type === "ActionResponse" || !response.success) {
953
956
  onResolve();
954
957
  this.inflightRequests.delete(response.requestId);
955
958
  this.requestsOlderThanRestart.delete(response.requestId);
956
- return response.requestId;
959
+ return { requestId: response.requestId, result };
957
960
  }
958
961
  requestInfo.status = {
959
962
  status: "Completed",
963
+ result,
960
964
  ts: response.ts,
961
965
  onResolve
962
966
  };
@@ -964,12 +968,12 @@ var convex = (() => {
964
968
  }
965
969
  // Remove and returns completed requests.
966
970
  removeCompleted(ts) {
967
- const completeRequests = /* @__PURE__ */ new Set();
971
+ const completeRequests = /* @__PURE__ */ new Map();
968
972
  for (const [requestId, requestInfo] of this.inflightRequests.entries()) {
969
973
  const status = requestInfo.status;
970
974
  if (status.status === "Completed" && status.ts.lessThanOrEqual(ts)) {
971
975
  status.onResolve();
972
- completeRequests.add(requestId);
976
+ completeRequests.set(requestId, status.result);
973
977
  this.inflightRequests.delete(requestId);
974
978
  this.requestsOlderThanRestart.delete(requestId);
975
979
  }
@@ -2218,8 +2222,9 @@ var convex = (() => {
2218
2222
  authenticationManager;
2219
2223
  remoteQuerySet;
2220
2224
  optimisticQueryResults;
2221
- onTransition;
2225
+ _transitionHandlerCounter = 0;
2222
2226
  _nextRequestId;
2227
+ _onTransitionFns = /* @__PURE__ */ new Map();
2223
2228
  _sessionId;
2224
2229
  firstMessageReceived = false;
2225
2230
  debug;
@@ -2229,7 +2234,8 @@ var convex = (() => {
2229
2234
  * @param address - The url of your Convex deployment, often provided
2230
2235
  * by an environment variable. E.g. `https://small-mouse-123.convex.cloud`.
2231
2236
  * @param onTransition - A callback receiving an array of query tokens
2232
- * corresponding to query results that have changed.
2237
+ * corresponding to query results that have changed -- additional handlers
2238
+ * can be added via `addOnTransitionHandler`.
2233
2239
  * @param options - See {@link BaseConvexClientOptions} for a full description.
2234
2240
  */
2235
2241
  constructor(address, onTransition, options) {
@@ -2298,7 +2304,9 @@ var convex = (() => {
2298
2304
  }
2299
2305
  );
2300
2306
  this.optimisticQueryResults = new OptimisticQueryResults();
2301
- this.onTransition = onTransition;
2307
+ this.addOnTransitionHandler((transition) => {
2308
+ onTransition(transition.queries.map((q) => q.token));
2309
+ });
2302
2310
  this._nextRequestId = 0;
2303
2311
  this._sessionId = newSessionId();
2304
2312
  const { unsavedChangesWarning } = options;
@@ -2381,9 +2389,16 @@ var convex = (() => {
2381
2389
  if (serverMessage.success) {
2382
2390
  this.observedTimestamp(serverMessage.ts);
2383
2391
  }
2384
- const completedMutationId = this.requestManager.onResponse(serverMessage);
2385
- if (completedMutationId !== null) {
2386
- this.notifyOnQueryResultChanges(/* @__PURE__ */ new Set([completedMutationId]));
2392
+ const completedMutationInfo = this.requestManager.onResponse(serverMessage);
2393
+ if (completedMutationInfo !== null) {
2394
+ this.notifyOnQueryResultChanges(
2395
+ /* @__PURE__ */ new Map([
2396
+ [
2397
+ completedMutationInfo.requestId,
2398
+ completedMutationInfo.result
2399
+ ]
2400
+ ])
2401
+ );
2387
2402
  }
2388
2403
  break;
2389
2404
  }
@@ -2441,7 +2456,7 @@ var convex = (() => {
2441
2456
  * @param completedMutations - A set of mutation IDs whose optimistic updates
2442
2457
  * are no longer needed.
2443
2458
  */
2444
- notifyOnQueryResultChanges(completedRequest) {
2459
+ notifyOnQueryResultChanges(completedRequests) {
2445
2460
  const remoteQueryResults = this.remoteQuerySet.remoteQueryResults();
2446
2461
  const queryTokenToValue = /* @__PURE__ */ new Map();
2447
2462
  for (const [queryId, result] of remoteQueryResults) {
@@ -2455,12 +2470,45 @@ var convex = (() => {
2455
2470
  queryTokenToValue.set(queryToken, query);
2456
2471
  }
2457
2472
  }
2458
- this.onTransition(
2459
- this.optimisticQueryResults.ingestQueryResultsFromServer(
2460
- queryTokenToValue,
2461
- completedRequest
2462
- )
2473
+ const changedQueryTokens = this.optimisticQueryResults.ingestQueryResultsFromServer(
2474
+ queryTokenToValue,
2475
+ new Set(completedRequests.keys())
2463
2476
  );
2477
+ this.handleTransition({
2478
+ queries: changedQueryTokens.map((token) => ({
2479
+ token,
2480
+ modification: {
2481
+ kind: "Updated",
2482
+ result: queryTokenToValue.get(token).result
2483
+ }
2484
+ })),
2485
+ reflectedMutations: Array.from(completedRequests).map(
2486
+ ([requestId, result]) => ({
2487
+ requestId,
2488
+ result
2489
+ })
2490
+ ),
2491
+ timestamp: this.remoteQuerySet.timestamp()
2492
+ });
2493
+ }
2494
+ handleTransition(transition) {
2495
+ for (const fn of this._onTransitionFns.values()) {
2496
+ fn(transition);
2497
+ }
2498
+ }
2499
+ /**
2500
+ * Add a handler that will be called on a transition.
2501
+ *
2502
+ * Any external side effects (e.g. setting React state) should be handled here.
2503
+ *
2504
+ * @param fn
2505
+ *
2506
+ * @returns
2507
+ */
2508
+ addOnTransitionHandler(fn) {
2509
+ const id = this._transitionHandlerCounter++;
2510
+ this._onTransitionFns.set(id, fn);
2511
+ return () => this._onTransitionFns.delete(id);
2464
2512
  }
2465
2513
  /**
2466
2514
  * Set the authentication token to be used for subsequent queries and mutations.
@@ -2616,6 +2664,18 @@ var convex = (() => {
2616
2664
  * @internal
2617
2665
  */
2618
2666
  async mutationInternal(udfPath, args, options, componentPath) {
2667
+ const { mutationPromise } = this.enqueueMutation(
2668
+ udfPath,
2669
+ args,
2670
+ options,
2671
+ componentPath
2672
+ );
2673
+ return mutationPromise;
2674
+ }
2675
+ /**
2676
+ * @internal
2677
+ */
2678
+ enqueueMutation(udfPath, args, options, componentPath) {
2619
2679
  const mutationArgs = parseArgs(args);
2620
2680
  this.tryReportLongDisconnect();
2621
2681
  const requestId = this.nextRequestId;
@@ -2626,11 +2686,29 @@ var convex = (() => {
2626
2686
  const wrappedUpdate = (localQueryStore) => {
2627
2687
  optimisticUpdate(localQueryStore, mutationArgs);
2628
2688
  };
2629
- const changedQueries = this.optimisticQueryResults.applyOptimisticUpdate(
2689
+ const changedQueryTokens = this.optimisticQueryResults.applyOptimisticUpdate(
2630
2690
  wrappedUpdate,
2631
2691
  requestId
2632
2692
  );
2633
- this.onTransition(changedQueries);
2693
+ const changedQueries = changedQueryTokens.map((token) => {
2694
+ const localResult = this.localQueryResultByToken(token);
2695
+ return {
2696
+ token,
2697
+ modification: {
2698
+ kind: "Updated",
2699
+ result: localResult === void 0 ? void 0 : {
2700
+ success: true,
2701
+ value: localResult,
2702
+ logLines: []
2703
+ }
2704
+ }
2705
+ };
2706
+ });
2707
+ this.handleTransition({
2708
+ queries: changedQueries,
2709
+ reflectedMutations: [],
2710
+ timestamp: this.remoteQuerySet.timestamp()
2711
+ });
2634
2712
  }
2635
2713
  }
2636
2714
  const message = {
@@ -2641,7 +2719,11 @@ var convex = (() => {
2641
2719
  args: [convexToJson(mutationArgs)]
2642
2720
  };
2643
2721
  const mightBeSent = this.webSocketManager.sendMessage(message);
2644
- return this.requestManager.request(message, mightBeSent);
2722
+ const mutationPromise = this.requestManager.request(message, mightBeSent);
2723
+ return {
2724
+ requestId,
2725
+ mutationPromise
2726
+ };
2645
2727
  }
2646
2728
  /**
2647
2729
  * Execute an action function.