kitcn 0.13.5 → 0.13.6

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 (2) hide show
  1. package/dist/react/index.js +119 -71
  2. package/package.json +1 -1
@@ -5,9 +5,9 @@ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, use
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { getFunctionName } from "convex/server";
7
7
  import { notifyManager, skipToken, useQueries, useQueryClient } from "@tanstack/react-query";
8
- import { ConvexHttpClient } from "convex/browser";
9
8
  import { hashKey } from "@tanstack/query-core";
10
9
  import { convexToJson } from "convex/values";
10
+ import { ConvexHttpClient } from "convex/browser";
11
11
 
12
12
  //#region src/shared/meta-utils.ts
13
13
  const metaCache = /* @__PURE__ */ new WeakMap();
@@ -723,6 +723,57 @@ function useAuthSkip(funcRef, opts) {
723
723
  };
724
724
  }
725
725
 
726
+ //#endregion
727
+ //#region src/internal/query-key.ts
728
+ /**
729
+ * Shared query key utilities for Convex + TanStack Query.
730
+ * This file has NO React dependencies so it can be imported in both
731
+ * server (RSC) and client contexts.
732
+ */
733
+ /**
734
+ * Check if query key is for a Convex query function.
735
+ * Format: ['convexQuery', 'namespace:functionName', { args }]
736
+ */
737
+ function isConvexQuery(queryKey) {
738
+ return queryKey.length >= 2 && queryKey[0] === "convexQuery";
739
+ }
740
+ /**
741
+ * Check if query key is for a Convex action function.
742
+ * Format: ['convexAction', 'namespace:functionName', { args }]
743
+ */
744
+ function isConvexAction$1(queryKey) {
745
+ return queryKey.length >= 2 && queryKey[0] === "convexAction";
746
+ }
747
+ /**
748
+ * Create stable hash for Convex query keys.
749
+ * Uses Convex's JSON serialization for consistent argument hashing.
750
+ */
751
+ function hashConvexQuery(queryKey) {
752
+ const [, funcName, args] = queryKey;
753
+ return `convexQuery|${funcName}|${JSON.stringify(convexToJson(args))}`;
754
+ }
755
+ /**
756
+ * Create stable hash for Convex action keys.
757
+ * Uses Convex's JSON serialization for consistent argument hashing.
758
+ */
759
+ function hashConvexAction(queryKey) {
760
+ const [, funcName, args] = queryKey;
761
+ return `convexAction|${funcName}|${JSON.stringify(convexToJson(args))}`;
762
+ }
763
+
764
+ //#endregion
765
+ //#region src/internal/hash.ts
766
+ /**
767
+ * Create a hash function for TanStack Query that handles Convex keys.
768
+ */
769
+ function createHashFn(fallback = hashKey) {
770
+ return (queryKey) => {
771
+ if (isConvexQuery(queryKey)) return hashConvexQuery(queryKey);
772
+ if (isConvexAction$1(queryKey)) return hashConvexAction(queryKey);
773
+ return fallback(queryKey);
774
+ };
775
+ }
776
+
726
777
  //#endregion
727
778
  //#region src/react/use-query-options.ts
728
779
  /** biome-ignore-all lint/suspicious/noExplicitAny: Convex type compatibility */
@@ -730,6 +781,37 @@ function useAuthSkip(funcRef, opts) {
730
781
  * Query options factories for Convex functions.
731
782
  * Forked from @convex-dev/react-query to support auth-aware error handling.
732
783
  */
784
+ const EMPTY_ARGS = {};
785
+ const hashConvexOptionsKey = createHashFn();
786
+ const MAX_STABLE_ARGS = 500;
787
+ const stableArgsByHash = /* @__PURE__ */ new Map();
788
+ function getStableArgsByHash(hash, args) {
789
+ if (stableArgsByHash.has(hash)) {
790
+ const stableArgs = stableArgsByHash.get(hash);
791
+ stableArgsByHash.delete(hash);
792
+ stableArgsByHash.set(hash, stableArgs);
793
+ return stableArgs;
794
+ }
795
+ stableArgsByHash.set(hash, args);
796
+ if (stableArgsByHash.size > MAX_STABLE_ARGS) {
797
+ const oldestHash = stableArgsByHash.keys().next().value;
798
+ if (oldestHash !== void 0) stableArgsByHash.delete(oldestHash);
799
+ }
800
+ return args;
801
+ }
802
+ function useStableQueryArgs(prefix, funcRef, args) {
803
+ const resolvedArgs = args === skipToken || args == null ? EMPTY_ARGS : args;
804
+ const argsHash = hashConvexOptionsKey([
805
+ prefix,
806
+ getFunctionName(funcRef),
807
+ resolvedArgs
808
+ ]);
809
+ const value = useMemo(() => getStableArgsByHash(argsHash, resolvedArgs), [argsHash, resolvedArgs]);
810
+ return useMemo(() => ({
811
+ hash: argsHash,
812
+ value
813
+ }), [argsHash, value]);
814
+ }
733
815
  /**
734
816
  * Hook that returns query options for use with useQuery.
735
817
  * Handles skipUnauth by setting enabled: false when unauthorized.
@@ -761,18 +843,27 @@ function useConvexQueryOptions(funcRef, args, options) {
761
843
  enabled: isSkipped ? false : enabled,
762
844
  skipUnauth: options?.skipUnauth
763
845
  });
764
- const baseOptions = convexQuery(funcRef, isSkipped ? {} : args);
765
- const { skipUnauth: _, subscribe, ...queryOptions } = options ?? {};
766
- return {
767
- ...baseOptions,
768
- ...queryOptions,
769
- enabled: isSkipped ? false : !shouldSkip,
770
- meta: {
771
- ...baseOptions.meta,
772
- authType,
773
- subscribe: subscribe !== false
774
- }
775
- };
846
+ const stableArgs = useStableQueryArgs("convexQuery", funcRef, isSkipped ? EMPTY_ARGS : args);
847
+ const baseOptions = useMemo(() => convexQuery(funcRef, stableArgs.value), [funcRef, stableArgs]);
848
+ return useMemo(() => {
849
+ const { skipUnauth: _, subscribe, ...queryOptions } = options ?? {};
850
+ return {
851
+ ...baseOptions,
852
+ ...queryOptions,
853
+ enabled: isSkipped ? false : !shouldSkip,
854
+ meta: {
855
+ ...baseOptions.meta,
856
+ authType,
857
+ subscribe: subscribe !== false
858
+ }
859
+ };
860
+ }, [
861
+ authType,
862
+ baseOptions,
863
+ isSkipped,
864
+ options,
865
+ shouldSkip
866
+ ]);
776
867
  }
777
868
  /**
778
869
  * Hook that returns infinite query options for use with useInfiniteQuery.
@@ -846,13 +937,21 @@ function useConvexActionQueryOptions(action, args, options) {
846
937
  enabled: isSkipped ? false : enabled,
847
938
  skipUnauth: options?.skipUnauth
848
939
  });
849
- const baseOptions = convexAction(action, isSkipped ? {} : args);
850
- const { skipUnauth: _, ...queryOptions } = options ?? {};
851
- return {
852
- ...baseOptions,
853
- ...queryOptions,
854
- enabled: isSkipped ? false : !shouldSkip
855
- };
940
+ const stableArgs = useStableQueryArgs("convexAction", action, isSkipped ? EMPTY_ARGS : args);
941
+ const baseOptions = useMemo(() => convexAction(action, stableArgs.value), [action, stableArgs]);
942
+ return useMemo(() => {
943
+ const { skipUnauth: _, ...queryOptions } = options ?? {};
944
+ return {
945
+ ...baseOptions,
946
+ ...queryOptions,
947
+ enabled: isSkipped ? false : !shouldSkip
948
+ };
949
+ }, [
950
+ baseOptions,
951
+ isSkipped,
952
+ options,
953
+ shouldSkip
954
+ ]);
856
955
  }
857
956
  /**
858
957
  * Hook that returns mutation options for use with useMutation.
@@ -1511,57 +1610,6 @@ function createAuthMutations(authClient) {
1511
1610
  };
1512
1611
  }
1513
1612
 
1514
- //#endregion
1515
- //#region src/internal/query-key.ts
1516
- /**
1517
- * Shared query key utilities for Convex + TanStack Query.
1518
- * This file has NO React dependencies so it can be imported in both
1519
- * server (RSC) and client contexts.
1520
- */
1521
- /**
1522
- * Check if query key is for a Convex query function.
1523
- * Format: ['convexQuery', 'namespace:functionName', { args }]
1524
- */
1525
- function isConvexQuery(queryKey) {
1526
- return queryKey.length >= 2 && queryKey[0] === "convexQuery";
1527
- }
1528
- /**
1529
- * Check if query key is for a Convex action function.
1530
- * Format: ['convexAction', 'namespace:functionName', { args }]
1531
- */
1532
- function isConvexAction$1(queryKey) {
1533
- return queryKey.length >= 2 && queryKey[0] === "convexAction";
1534
- }
1535
- /**
1536
- * Create stable hash for Convex query keys.
1537
- * Uses Convex's JSON serialization for consistent argument hashing.
1538
- */
1539
- function hashConvexQuery(queryKey) {
1540
- const [, funcName, args] = queryKey;
1541
- return `convexQuery|${funcName}|${JSON.stringify(convexToJson(args))}`;
1542
- }
1543
- /**
1544
- * Create stable hash for Convex action keys.
1545
- * Uses Convex's JSON serialization for consistent argument hashing.
1546
- */
1547
- function hashConvexAction(queryKey) {
1548
- const [, funcName, args] = queryKey;
1549
- return `convexAction|${funcName}|${JSON.stringify(convexToJson(args))}`;
1550
- }
1551
-
1552
- //#endregion
1553
- //#region src/internal/hash.ts
1554
- /**
1555
- * Create a hash function for TanStack Query that handles Convex keys.
1556
- */
1557
- function createHashFn(fallback = hashKey) {
1558
- return (queryKey) => {
1559
- if (isConvexQuery(queryKey)) return hashConvexQuery(queryKey);
1560
- if (isConvexAction$1(queryKey)) return hashConvexAction(queryKey);
1561
- return fallback(queryKey);
1562
- };
1563
- }
1564
-
1565
1613
  //#endregion
1566
1614
  //#region src/react/client.ts
1567
1615
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitcn",
3
- "version": "0.13.5",
3
+ "version": "0.13.6",
4
4
  "description": "kitcn - React Query integration and CLI tools for Convex",
5
5
  "keywords": [
6
6
  "convex",