convex-helpers 0.1.47 → 0.1.48

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "convex-helpers",
3
- "version": "0.1.47",
3
+ "version": "0.1.48",
4
4
  "description": "A collection of useful code to complement the official convex package.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -105,7 +105,7 @@
105
105
  "test:debug": "vitest --inspect-brk --no-file-parallelism",
106
106
  "test:coverage": "vitest run --coverage --coverage.reporter=text",
107
107
  "clean": "rm -rf dist",
108
- "dev": "chokidar '*.ts' 'server/*.ts' 'react/*.ts' 'react/cache/*.ts' 'tsconfig*.json' 'package.json' -c 'npm run build' --initial",
108
+ "dev": "chokidar '*.ts' 'server/**/*.ts' 'react/**/*.ts*' 'tsconfig*.json' 'package.json' -c 'npm run build' --initial",
109
109
  "arethetypeswrong": "attw $(npm pack)"
110
110
  },
111
111
  "repository": {
@@ -146,10 +146,10 @@
146
146
  "@edge-runtime/vm": "3.2.0",
147
147
  "@types/node": "20.14.9",
148
148
  "@types/react": "18.3.3",
149
- "@vitest/coverage-v8": "2.0.2",
149
+ "@vitest/coverage-v8": "2.0.3",
150
150
  "chokidar-cli": "3.0.0",
151
151
  "convex-test": "0.0.23",
152
152
  "typescript": "5.5.3",
153
- "vitest": "2.0.2"
153
+ "vitest": "2.0.3"
154
154
  }
155
155
  }
@@ -52,7 +52,6 @@ type SubEntry<Query extends FunctionReference<"query">> = {
52
52
  setter: (v?: FunctionReturnType<Query>) => void;
53
53
  };
54
54
  declare class CacheRegistry {
55
- #private;
56
55
  queries: Map<QueryKey, CachedQuery<FunctionReference<"query">>>;
57
56
  subs: Map<SubKey, SubEntry<FunctionReference<"query">>>;
58
57
  convex: ConvexReactClient;
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["provider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAa,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAiB,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE7D,eAAO,MAAM,uBAAuB;cAChB,aAAa,GAAG,IAAI;EACtC,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,EAAE,EAAE,CACvC,iBAAiB,CAAC,uBAAuB,CAAC,CAgB3C,CAAC;AAKF,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;GAEG;AAEH,KAAK,MAAM,GAAG,MAAM,CAAC;AACrB,KAAK,QAAQ,GAAG,MAAM,CAAC;AACvB,KAAK,WAAW,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,IAAI;IAC3D,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,CAAC,EAAE,kBAAkB,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;CAC3C,CAAC;AACF,KAAK,QAAQ,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,IAAI;IACxD,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;CACjD,CAAC;AAGF,cAAM,aAAa;;IACjB,OAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAChE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACxD,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;gBAED,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,uBAAuB;IA0BvE,KAAK,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAC5C,QAAQ,EAAE,QAAQ,GACjB,kBAAkB,CAAC,KAAK,CAAC,GAAG,SAAS;IAMxC,KAAK,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAC5C,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC,EACzB,MAAM,EAAE,CAAC,CAAC,EAAE,kBAAkB,CAAC,KAAK,CAAC,KAAK,IAAI,GAC7C,IAAI;IAoCP,GAAG,CAAC,EAAE,EAAE,MAAM;IA0Bd,KAAK;CAeN"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["provider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAa,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAiB,EAAE,EAAE,iBAAiB,EAAW,MAAM,OAAO,CAAC;AAEtE,eAAO,MAAM,uBAAuB;cAChB,aAAa,GAAG,IAAI;EACtC,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,EAAE,EAAE,CACvC,iBAAiB,CAAC,uBAAuB,CAAC,CAmB3C,CAAC;AAKF,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;GAEG;AAEH,KAAK,MAAM,GAAG,MAAM,CAAC;AACrB,KAAK,QAAQ,GAAG,MAAM,CAAC;AACvB,KAAK,WAAW,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,IAAI;IAC3D,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,CAAC,EAAE,kBAAkB,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;CAC3C,CAAC;AACF,KAAK,QAAQ,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,IAAI;IACxD,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;CACjD,CAAC;AAGF,cAAM,aAAa;IACjB,OAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAChE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACxD,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;gBAED,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,uBAAuB;IAoBvE,KAAK,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAC5C,QAAQ,EAAE,QAAQ,GACjB,kBAAkB,CAAC,KAAK,CAAC,GAAG,SAAS;IAMxC,KAAK,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAC5C,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC,EACzB,MAAM,EAAE,CAAC,CAAC,EAAE,kBAAkB,CAAC,KAAK,CAAC,KAAK,IAAI,GAC7C,IAAI;IAwCP,GAAG,CAAC,EAAE,EAAE,MAAM;IA0Bd,KAAK;CAeN"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useConvex } from "convex/react";
4
- import { createContext } from "react";
4
+ import { createContext, useMemo } from "react";
5
5
  export const ConvexQueryCacheContext = createContext({
6
6
  registry: null,
7
7
  });
@@ -13,14 +13,14 @@ export const ConvexQueryCacheContext = createContext({
13
13
  * @param {ConvexQueryCacheOptions} props.options - Options for the query cache
14
14
  * @returns {Element}
15
15
  */
16
- export const ConvexQueryCacheProvider = ({ children, ...options }) => {
16
+ export const ConvexQueryCacheProvider = ({ children, debug, expiration, maxIdleEntries }) => {
17
17
  const convex = useConvex();
18
18
  if (convex === undefined) {
19
19
  throw new Error("Could not find Convex client! `ConvexQueryCacheProvider` must be used in the React component " +
20
20
  "tree under `ConvexProvider`. Did you forget it? " +
21
21
  "See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app");
22
22
  }
23
- const registry = new CacheRegistry(convex, options);
23
+ const registry = useMemo(() => new CacheRegistry(convex, { debug, expiration, maxIdleEntries }), [convex, debug, expiration, maxIdleEntries]);
24
24
  return (_jsx(ConvexQueryCacheContext.Provider, { value: { registry }, children: children }));
25
25
  };
26
26
  const DEFAULT_EXPIRATION_MS = 300_000; // 5 minutes
@@ -53,27 +53,27 @@ class CacheRegistry {
53
53
  }, 3000);
54
54
  }
55
55
  }
56
- #getQueryEntry(queryKey) {
57
- const entry = this.queries.get(queryKey);
58
- return entry;
59
- }
60
56
  probe(queryKey) {
61
- const entry = this.#getQueryEntry(queryKey);
57
+ const entry = this.queries.get(queryKey);
62
58
  return entry === undefined ? undefined : entry.value;
63
59
  }
64
60
  // Enable a new subscription.
65
61
  start(id, queryKey, query, args, setter) {
66
- let entry = this.#getQueryEntry(queryKey);
62
+ let entry = this.queries.get(queryKey);
67
63
  this.subs.set(id, {
68
64
  queryKey,
69
65
  setter,
70
66
  });
71
67
  if (entry === undefined) {
68
+ const w = this.convex.watchQuery(query, args);
72
69
  entry = {
73
70
  refs: new Set(),
74
71
  evictTimer: null,
72
+ // On the first pass, it might already have a result,
73
+ // either if there are queries not managed by the cache previously,
74
+ // or if the registry is hot-reloaded.
75
+ value: w.localQueryResult(),
75
76
  };
76
- const w = this.convex.watchQuery(query, args);
77
77
  const unsub = w.onUpdate(() => {
78
78
  const e = entry;
79
79
  try {
@@ -5,7 +5,7 @@ import {
5
5
  FunctionReference,
6
6
  FunctionReturnType,
7
7
  } from "convex/server";
8
- import { createContext, FC, PropsWithChildren } from "react";
8
+ import { createContext, FC, PropsWithChildren, useMemo } from "react";
9
9
 
10
10
  export const ConvexQueryCacheContext = createContext({
11
11
  registry: null as CacheRegistry | null,
@@ -21,7 +21,7 @@ export const ConvexQueryCacheContext = createContext({
21
21
  */
22
22
  export const ConvexQueryCacheProvider: FC<
23
23
  PropsWithChildren<ConvexQueryCacheOptions>
24
- > = ({ children, ...options }) => {
24
+ > = ({ children, debug, expiration, maxIdleEntries }) => {
25
25
  const convex = useConvex();
26
26
  if (convex === undefined) {
27
27
  throw new Error(
@@ -30,7 +30,10 @@ export const ConvexQueryCacheProvider: FC<
30
30
  "See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app",
31
31
  );
32
32
  }
33
- const registry = new CacheRegistry(convex, options);
33
+ const registry = useMemo(
34
+ () => new CacheRegistry(convex, { debug, expiration, maxIdleEntries }),
35
+ [convex, debug, expiration, maxIdleEntries],
36
+ );
34
37
  return (
35
38
  <ConvexQueryCacheContext.Provider value={{ registry }}>
36
39
  {children}
@@ -112,17 +115,11 @@ class CacheRegistry {
112
115
  }, 3000);
113
116
  }
114
117
  }
115
- #getQueryEntry(
116
- queryKey: QueryKey,
117
- ): CachedQuery<FunctionReference<"query">> | undefined {
118
- const entry = this.queries.get(queryKey);
119
- return entry;
120
- }
121
118
 
122
119
  probe<Query extends FunctionReference<"query">>(
123
120
  queryKey: QueryKey,
124
121
  ): FunctionReturnType<Query> | undefined {
125
- const entry = this.#getQueryEntry(queryKey);
122
+ const entry = this.queries.get(queryKey);
126
123
  return entry === undefined ? undefined : entry.value;
127
124
  }
128
125
 
@@ -134,17 +131,21 @@ class CacheRegistry {
134
131
  args: FunctionArgs<Query>,
135
132
  setter: (v: FunctionReturnType<Query>) => void,
136
133
  ): void {
137
- let entry = this.#getQueryEntry(queryKey);
134
+ let entry = this.queries.get(queryKey);
138
135
  this.subs.set(id, {
139
136
  queryKey,
140
137
  setter,
141
138
  });
142
139
  if (entry === undefined) {
140
+ const w = this.convex.watchQuery(query, args);
143
141
  entry = {
144
142
  refs: new Set(),
145
143
  evictTimer: null,
144
+ // On the first pass, it might already have a result,
145
+ // either if there are queries not managed by the cache previously,
146
+ // or if the registry is hot-reloaded.
147
+ value: w.localQueryResult(),
146
148
  };
147
- const w = this.convex.watchQuery(query, args);
148
149
  const unsub = w.onUpdate(() => {
149
150
  const e = entry!;
150
151
  try {