better-convex 0.7.3 → 0.8.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 (46) hide show
  1. package/dist/aggregate/index.d.ts +1 -1
  2. package/dist/aggregate/index.js +1 -1
  3. package/dist/auth/http/index.d.ts +1 -1
  4. package/dist/auth/index.d.ts +10 -10
  5. package/dist/auth/index.js +5 -5
  6. package/dist/auth/nextjs/index.d.ts +2 -2
  7. package/dist/auth/nextjs/index.js +2 -2
  8. package/dist/{caller-factory-4uND4vnj.js → caller-factory-CCsm4Dut.js} +2 -2
  9. package/dist/cli.mjs +1 -0
  10. package/dist/{create-schema-orm-DtuyK2RB.js → create-schema-orm-OcyA0apQ.js} +10 -13
  11. package/dist/crpc/index.d.ts +2 -2
  12. package/dist/crpc/index.js +3 -3
  13. package/dist/{customFunctions-C_i_0joT.js → customFunctions-RnzME_cJ.js} +1 -1
  14. package/dist/{http-types-BsnDV7Je.d.ts → http-types-BK7FuIcR.d.ts} +1 -1
  15. package/dist/id-BcBb900m.js +121 -0
  16. package/dist/orm/index.d.ts +4 -4
  17. package/dist/orm/index.js +60 -222
  18. package/dist/plugins/index.d.ts +9 -0
  19. package/dist/plugins/index.js +3 -0
  20. package/dist/plugins/ratelimit/index.d.ts +222 -0
  21. package/dist/plugins/ratelimit/index.js +846 -0
  22. package/dist/plugins/ratelimit/react/index.d.ts +76 -0
  23. package/dist/plugins/ratelimit/react/index.js +294 -0
  24. package/dist/{procedure-caller-Cj_lgUev.d.ts → procedure-caller-DYjpq7rG.d.ts} +2 -2
  25. package/dist/rsc/index.d.ts +3 -3
  26. package/dist/rsc/index.js +4 -4
  27. package/dist/runtime-C0WcYGY0.js +1028 -0
  28. package/dist/schema-Bx6j2doh.js +204 -0
  29. package/dist/server/index.d.ts +2 -2
  30. package/dist/server/index.js +4 -4
  31. package/dist/{runtime-B9xQFY8W.js → table-B7yzBihE.js} +3 -1088
  32. package/dist/text-enum-CFdcLUuw.js +30 -0
  33. package/dist/{types-DZFvhoPJ.d.ts → types-f53SgpBL.d.ts} +1 -1
  34. package/dist/{where-clause-compiler-HUa2223D.d.ts → where-clause-compiler-BIjTkVVJ.d.ts} +34 -2
  35. package/package.json +4 -1
  36. /package/dist/{create-schema-DE9ZtH8n.js → create-schema-BsN0jL5S.js} +0 -0
  37. /package/dist/{error-C7AOPlv2.js → error-CAGGSN5H.js} +0 -0
  38. /package/dist/{meta-utils-C9_6WIzj.js → meta-utils-NRyocOSc.js} +0 -0
  39. /package/dist/{query-context-yQVARct0.js → query-context-DEUFBhXS.js} +0 -0
  40. /package/dist/{query-context-BMXt2TKe.d.ts → query-context-ji7By8u0.d.ts} +0 -0
  41. /package/dist/{query-options-Bjo6j5cC.js → query-options-CSCmKYdJ.js} +0 -0
  42. /package/dist/{transformer-BsX4RWes.js → transformer-ogg-4d78.js} +0 -0
  43. /package/dist/{types-kgwiK-xe.d.ts → types-BTb_4BaU.d.ts} +0 -0
  44. /package/dist/{types-DarApWtO.d.ts → types-CM67ko7K.d.ts} +0 -0
  45. /package/dist/{validators-BDrWGp4M.d.ts → validators-BcQFm1oY.d.ts} +0 -0
  46. /package/dist/{validators-B7oIJCAp.js → validators-D_i3BK7v.js} +0 -0
@@ -0,0 +1,76 @@
1
+ 'use client';
2
+ import { FunctionReference } from "convex/server";
3
+
4
+ //#region src/plugins/ratelimit/types.d.ts
5
+ type RateLimitSnapshot = {
6
+ value: number;
7
+ ts: number;
8
+ shard: number;
9
+ config: ResolvedAlgorithm;
10
+ };
11
+ type FixedWindowAlgorithm = {
12
+ kind: 'fixedWindow';
13
+ limit: number;
14
+ window: number;
15
+ capacity: number;
16
+ start?: number;
17
+ maxReserved?: number;
18
+ shards: number;
19
+ };
20
+ type SlidingWindowAlgorithm = {
21
+ kind: 'slidingWindow';
22
+ limit: number;
23
+ window: number;
24
+ maxReserved?: number;
25
+ shards: number;
26
+ };
27
+ type TokenBucketAlgorithm = {
28
+ kind: 'tokenBucket';
29
+ refillRate: number;
30
+ interval: number;
31
+ maxTokens: number;
32
+ maxReserved?: number;
33
+ shards: number;
34
+ };
35
+ type ResolvedAlgorithm = FixedWindowAlgorithm | SlidingWindowAlgorithm | TokenBucketAlgorithm;
36
+ type HookCheckValue = {
37
+ value: number;
38
+ ts: number;
39
+ config: ResolvedAlgorithm;
40
+ shard: number;
41
+ ok: boolean;
42
+ retryAt?: number;
43
+ };
44
+ //#endregion
45
+ //#region src/plugins/ratelimit/react/use-rate-limit.d.ts
46
+ type GetRateLimitValueQueryRef = FunctionReference<'query', 'public', {
47
+ identifier?: string;
48
+ sampleShards?: number;
49
+ }, RateLimitSnapshot>;
50
+ type GetServerTimeMutationRef = FunctionReference<'mutation', 'public', Record<string, never>, number>;
51
+ type GetRateLimitValueQuery = GetRateLimitValueQueryRef | string;
52
+ type GetServerTimeMutation = GetServerTimeMutationRef | string;
53
+ type UseRateLimitOptions = {
54
+ identifier?: string;
55
+ count?: number;
56
+ sampleShards?: number;
57
+ getServerTimeMutation?: GetServerTimeMutation;
58
+ };
59
+ declare function useRateLimit(getRateLimitValueQuery: GetRateLimitValueQuery, options?: UseRateLimitOptions): {
60
+ status: undefined;
61
+ check: (ts?: number, requestedCount?: number) => HookCheckValue | undefined;
62
+ } | {
63
+ status: {
64
+ ok: false;
65
+ retryAt: number;
66
+ };
67
+ check: (ts?: number, requestedCount?: number) => HookCheckValue | undefined;
68
+ } | {
69
+ status: {
70
+ ok: true;
71
+ retryAt: undefined;
72
+ };
73
+ check: (ts?: number, requestedCount?: number) => HookCheckValue | undefined;
74
+ };
75
+ //#endregion
76
+ export { GetRateLimitValueQuery, GetRateLimitValueQueryRef, GetServerTimeMutation, GetServerTimeMutationRef, UseRateLimitOptions, useRateLimit };
@@ -0,0 +1,294 @@
1
+ 'use client';
2
+ import { c } from "react/compiler-runtime";
3
+ import { useConvex, useQuery } from "convex/react";
4
+ import { useEffect, useState } from "react";
5
+ import { makeFunctionReference } from "convex/server";
6
+
7
+ //#region src/plugins/ratelimit/core/calculate-rate-limit.ts
8
+ function calculateRateLimit(state, algorithm, now, count) {
9
+ if (algorithm.kind === "fixedWindow") return calculateFixedWindow(state, algorithm, now, count);
10
+ if (algorithm.kind === "tokenBucket") return calculateTokenBucket(state, algorithm, now, count);
11
+ return calculateSlidingWindow(state, algorithm, now, count);
12
+ }
13
+ function calculateTokenBucket(state, config, now, count) {
14
+ const ratePerMs = config.refillRate / config.interval;
15
+ const initial = state ?? {
16
+ value: config.maxTokens,
17
+ ts: now
18
+ };
19
+ const elapsed = Math.max(0, now - initial.ts);
20
+ const nextValue = Math.min(initial.value + elapsed * ratePerMs, config.maxTokens) - count;
21
+ const retryAfter = nextValue < 0 ? Math.ceil(-nextValue / ratePerMs) : void 0;
22
+ return {
23
+ state: {
24
+ value: nextValue,
25
+ ts: now
26
+ },
27
+ retryAfter,
28
+ remaining: Math.max(0, Math.floor(nextValue)),
29
+ reset: retryAfter ? now + retryAfter : now,
30
+ limit: config.maxTokens
31
+ };
32
+ }
33
+ function calculateFixedWindow(state, config, now, count) {
34
+ const windowStart = alignWindowStart(now, config.window, config.start);
35
+ const initial = state ?? {
36
+ value: config.capacity,
37
+ ts: windowStart
38
+ };
39
+ const elapsedWindows = Math.max(0, Math.floor((now - initial.ts) / config.window));
40
+ const replenished = Math.min(initial.value + config.limit * elapsedWindows, config.capacity);
41
+ const ts = initial.ts + elapsedWindows * config.window;
42
+ const nextValue = replenished - count;
43
+ const retryAfter = nextValue < 0 ? ts + config.window * Math.ceil(-nextValue / config.limit) - now : void 0;
44
+ return {
45
+ state: {
46
+ value: nextValue,
47
+ ts
48
+ },
49
+ retryAfter,
50
+ remaining: Math.max(0, Math.floor(nextValue)),
51
+ reset: ts + config.window,
52
+ limit: config.limit
53
+ };
54
+ }
55
+ function calculateSlidingWindow(state, config, now, count) {
56
+ const windowStart = alignWindowStart(now, config.window);
57
+ const previousWindowStart = windowStart - config.window;
58
+ const elapsedInWindow = now - windowStart;
59
+ const previousWeight = Math.max(0, (config.window - elapsedInWindow) / config.window);
60
+ let currentCount = 0;
61
+ let previousCount = 0;
62
+ if (state) {
63
+ if (state.ts === windowStart) {
64
+ currentCount = Math.max(0, state.value);
65
+ if (state.auxTs === previousWindowStart) previousCount = Math.max(0, state.auxValue ?? 0);
66
+ } else if (state.ts === previousWindowStart) previousCount = Math.max(0, state.value);
67
+ }
68
+ const projectedCurrent = currentCount + count;
69
+ const projectedUsed = projectedCurrent + previousCount * previousWeight;
70
+ const remaining = config.limit - projectedUsed;
71
+ const retryAfter = remaining < 0 ? Math.max(1, config.window - elapsedInWindow) : void 0;
72
+ return {
73
+ state: {
74
+ value: projectedCurrent,
75
+ ts: windowStart,
76
+ auxValue: previousCount,
77
+ auxTs: previousWindowStart
78
+ },
79
+ retryAfter,
80
+ remaining: Math.max(0, Math.floor(remaining)),
81
+ reset: windowStart + config.window,
82
+ limit: config.limit
83
+ };
84
+ }
85
+ function alignWindowStart(now, window, start = 0) {
86
+ const offsetNow = now - start;
87
+ return start + Math.floor(offsetNow / window) * window;
88
+ }
89
+
90
+ //#endregion
91
+ //#region src/plugins/ratelimit/react/use-rate-limit.ts
92
+ function useRateLimit(getRateLimitValueQuery, options) {
93
+ const $ = c(38);
94
+ const [timeOffset, setTimeOffset] = useState(0);
95
+ const [now, setNow] = useState(_temp);
96
+ const convex = useConvex();
97
+ let t0;
98
+ if ($[0] !== getRateLimitValueQuery) {
99
+ t0 = resolveGetRateLimitValueQuery(getRateLimitValueQuery);
100
+ $[0] = getRateLimitValueQuery;
101
+ $[1] = t0;
102
+ } else t0 = $[1];
103
+ const getRateLimitValueQueryRef = t0;
104
+ let t1;
105
+ if ($[2] !== options) {
106
+ t1 = options ?? {};
107
+ $[2] = options;
108
+ $[3] = t1;
109
+ } else t1 = $[3];
110
+ const { getServerTimeMutation, count, identifier, sampleShards } = t1;
111
+ let t2;
112
+ if ($[4] !== getServerTimeMutation) {
113
+ t2 = getServerTimeMutation ? resolveGetServerTimeMutation(getServerTimeMutation) : void 0;
114
+ $[4] = getServerTimeMutation;
115
+ $[5] = t2;
116
+ } else t2 = $[5];
117
+ const getServerTimeMutationRef = t2;
118
+ let t3;
119
+ let t4;
120
+ if ($[6] !== convex || $[7] !== getServerTimeMutationRef) {
121
+ t3 = () => {
122
+ if (!getServerTimeMutationRef) return;
123
+ const clientTime = Date.now();
124
+ convex.mutation(getServerTimeMutationRef, {}).then((serverTime) => {
125
+ const latency = Date.now() - clientTime;
126
+ setTimeOffset(serverTime - clientTime - latency / 2);
127
+ });
128
+ };
129
+ t4 = [convex, getServerTimeMutationRef];
130
+ $[6] = convex;
131
+ $[7] = getServerTimeMutationRef;
132
+ $[8] = t3;
133
+ $[9] = t4;
134
+ } else {
135
+ t3 = $[8];
136
+ t4 = $[9];
137
+ }
138
+ useEffect(t3, t4);
139
+ let t5;
140
+ if ($[10] !== identifier || $[11] !== sampleShards) {
141
+ t5 = {
142
+ identifier,
143
+ sampleShards
144
+ };
145
+ $[10] = identifier;
146
+ $[11] = sampleShards;
147
+ $[12] = t5;
148
+ } else t5 = $[12];
149
+ const rateLimitData = useQuery(getRateLimitValueQueryRef, t5);
150
+ let t6;
151
+ if ($[13] !== count || $[14] !== rateLimitData || $[15] !== timeOffset) {
152
+ t6 = (ts, requestedCount) => {
153
+ if (!rateLimitData) return;
154
+ const serverTs = (ts ?? Date.now()) + timeOffset;
155
+ const evaluation = evaluateSnapshot(rateLimitData, serverTs, requestedCount ?? count ?? 1);
156
+ return {
157
+ value: evaluation.value,
158
+ ts: evaluation.ts - timeOffset,
159
+ config: rateLimitData.config,
160
+ shard: rateLimitData.shard,
161
+ ok: evaluation.value >= 0,
162
+ retryAt: evaluation.retryAfter ? serverTs + evaluation.retryAfter - timeOffset : void 0
163
+ };
164
+ };
165
+ $[13] = count;
166
+ $[14] = rateLimitData;
167
+ $[15] = timeOffset;
168
+ $[16] = t6;
169
+ } else t6 = $[16];
170
+ const check = t6;
171
+ const t7 = count ?? 1;
172
+ let t8;
173
+ if ($[17] !== check || $[18] !== now || $[19] !== t7) {
174
+ t8 = check(now, t7);
175
+ $[17] = check;
176
+ $[18] = now;
177
+ $[19] = t7;
178
+ $[20] = t8;
179
+ } else t8 = $[20];
180
+ const current = t8;
181
+ let t9;
182
+ bb0: {
183
+ if (!current) {
184
+ let t10;
185
+ if ($[21] !== check) {
186
+ t10 = {
187
+ status: void 0,
188
+ check
189
+ };
190
+ $[21] = check;
191
+ $[22] = t10;
192
+ } else t10 = $[22];
193
+ t9 = t10;
194
+ break bb0;
195
+ }
196
+ if (current.value < 0) {
197
+ let t10;
198
+ if ($[23] !== current.retryAt) {
199
+ t10 = {
200
+ ok: false,
201
+ retryAt: current.retryAt
202
+ };
203
+ $[23] = current.retryAt;
204
+ $[24] = t10;
205
+ } else t10 = $[24];
206
+ let t11;
207
+ if ($[25] !== check || $[26] !== t10) {
208
+ t11 = {
209
+ status: t10,
210
+ check
211
+ };
212
+ $[25] = check;
213
+ $[26] = t10;
214
+ $[27] = t11;
215
+ } else t11 = $[27];
216
+ t9 = t11;
217
+ break bb0;
218
+ }
219
+ let t10;
220
+ if ($[28] === Symbol.for("react.memo_cache_sentinel")) {
221
+ t10 = {
222
+ ok: true,
223
+ retryAt: void 0
224
+ };
225
+ $[28] = t10;
226
+ } else t10 = $[28];
227
+ let t11;
228
+ if ($[29] !== check) {
229
+ t11 = {
230
+ status: t10,
231
+ check
232
+ };
233
+ $[29] = check;
234
+ $[30] = t11;
235
+ } else t11 = $[30];
236
+ t9 = t11;
237
+ }
238
+ const response = t9;
239
+ let t10;
240
+ if ($[31] !== now || $[32] !== response.status) {
241
+ t10 = () => {
242
+ if (response.status?.ok !== false || !response.status.retryAt) return;
243
+ const timeout = setTimeout(() => setNow(Date.now()), Math.max(0, response.status.retryAt - now));
244
+ return () => clearTimeout(timeout);
245
+ };
246
+ $[31] = now;
247
+ $[32] = response.status;
248
+ $[33] = t10;
249
+ } else t10 = $[33];
250
+ const t11 = response.status?.ok;
251
+ const t12 = response.status?.retryAt;
252
+ let t13;
253
+ if ($[34] !== now || $[35] !== t11 || $[36] !== t12) {
254
+ t13 = [
255
+ now,
256
+ t11,
257
+ t12
258
+ ];
259
+ $[34] = now;
260
+ $[35] = t11;
261
+ $[36] = t12;
262
+ $[37] = t13;
263
+ } else t13 = $[37];
264
+ useEffect(t10, t13);
265
+ return response;
266
+ }
267
+ function _temp() {
268
+ return Date.now();
269
+ }
270
+ function resolveGetRateLimitValueQuery(ref) {
271
+ if (typeof ref === "string") return makeFunctionReference(ref);
272
+ return ref;
273
+ }
274
+ function resolveGetServerTimeMutation(ref) {
275
+ if (typeof ref === "string") return makeFunctionReference(ref);
276
+ return ref;
277
+ }
278
+ function evaluateSnapshot(snapshot, now, count) {
279
+ const evaluated = calculateRateLimit(snapshot.config.kind === "slidingWindow" ? {
280
+ value: Math.max(0, snapshot.config.limit - snapshot.value),
281
+ ts: snapshot.ts
282
+ } : {
283
+ value: snapshot.value,
284
+ ts: snapshot.ts
285
+ }, snapshot.config, now, count);
286
+ return {
287
+ value: snapshot.config.kind === "slidingWindow" ? evaluated.retryAfter !== void 0 ? -1 : evaluated.remaining : evaluated.state.value,
288
+ ts: evaluated.state.ts,
289
+ retryAfter: evaluated.retryAfter
290
+ };
291
+ }
292
+
293
+ //#endregion
294
+ export { useRateLimit };
@@ -1,5 +1,5 @@
1
- import { t as VRequired } from "./validators-BDrWGp4M.js";
2
- import { C as HttpProcedure, D as ProcedureMeta, G as DataTransformerOptions, N as MiddlewareBuilder, O as AnyMiddleware, P as MiddlewareFunction, Q as getTransformer, R as Overwrite$1, S as HttpMethod, V as UnsetMarker, c as InferHttpInput, d as CRPCHttpRouter, j as IntersectIfDefined, l as InferHttpOutput, p as HttpRouterRecord, w as HttpProcedureBuilderDef, x as HttpHandlerOpts } from "./http-types-BsnDV7Je.js";
1
+ import { t as VRequired } from "./validators-BcQFm1oY.js";
2
+ import { C as HttpProcedure, D as ProcedureMeta, G as DataTransformerOptions, N as MiddlewareBuilder, O as AnyMiddleware, P as MiddlewareFunction, Q as getTransformer, R as Overwrite$1, S as HttpMethod, V as UnsetMarker, c as InferHttpInput, d as CRPCHttpRouter, j as IntersectIfDefined, l as InferHttpOutput, p as HttpRouterRecord, w as HttpProcedureBuilderDef, x as HttpHandlerOpts } from "./http-types-BK7FuIcR.js";
3
3
  import { ConvexError, GenericId, GenericValidator, ObjectType, OptionalProperty, PropertyValidators, VAny, VArray, VBoolean, VBytes, VFloat64, VId, VInt64, VLiteral, VNull, VObject, VOptional, VRecord, VString, VUnion, Validator } from "convex/values";
4
4
  import * as convex_server0 from "convex/server";
5
5
  import { ActionBuilder, ArgsArrayToObject, DefaultFunctionArgs, FunctionReference, FunctionReturnType, FunctionVisibility, GenericActionCtx, GenericDataModel, GenericMutationCtx, GenericQueryCtx, MutationBuilder, QueryBuilder, RegisteredAction, RegisteredMutation, RegisteredQuery, TableNamesInDataModel } from "convex/server";
@@ -1,6 +1,6 @@
1
- import { o as Simplify, r as DistributiveOmit } from "../types-kgwiK-xe.js";
2
- import { C as HttpProcedure, G as DataTransformerOptions, V as UnsetMarker, d as CRPCHttpRouter, p as HttpRouterRecord } from "../http-types-BsnDV7Je.js";
3
- import { n as CRPCClient } from "../types-DZFvhoPJ.js";
1
+ import { o as Simplify, r as DistributiveOmit } from "../types-BTb_4BaU.js";
2
+ import { C as HttpProcedure, G as DataTransformerOptions, V as UnsetMarker, d as CRPCHttpRouter, p as HttpRouterRecord } from "../http-types-BK7FuIcR.js";
3
+ import { n as CRPCClient } from "../types-f53SgpBL.js";
4
4
  import { DefaultError, QueryFilters, UseMutationOptions, UseQueryOptions } from "@tanstack/react-query";
5
5
  import { z } from "zod";
6
6
 
package/dist/rsc/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { n as defaultIsUnauthorized } from "../error-C7AOPlv2.js";
2
- import { n as getFuncRef, r as getFunctionMeta, t as buildMetaIndex } from "../meta-utils-C9_6WIzj.js";
3
- import { i as decodeWire, s as getTransformer } from "../transformer-BsX4RWes.js";
4
- import { n as convexInfiniteQueryOptions, r as convexQuery } from "../query-options-Bjo6j5cC.js";
1
+ import { n as defaultIsUnauthorized } from "../error-CAGGSN5H.js";
2
+ import { n as getFuncRef, r as getFunctionMeta, t as buildMetaIndex } from "../meta-utils-NRyocOSc.js";
3
+ import { i as decodeWire, s as getTransformer } from "../transformer-ogg-4d78.js";
4
+ import { n as convexInfiniteQueryOptions, r as convexQuery } from "../query-options-CSCmKYdJ.js";
5
5
  import { convexToJson } from "convex/values";
6
6
  import { getFunctionName } from "convex/server";
7
7
  import { fetchAction, fetchQuery } from "convex/nextjs";