kitcn 0.16.0 → 0.17.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 (38) hide show
  1. package/dist/aggregate/index.d.ts +1 -1
  2. package/dist/auth/client/index.js +1 -1
  3. package/dist/auth/index.js +19 -21
  4. package/dist/auth/nextjs/index.d.ts +1 -1
  5. package/dist/auth/nextjs/index.js +4 -4
  6. package/dist/{auth-store-ssZDPa37.js → auth-store-BnGZxmnY.js} +4 -1
  7. package/dist/{backend-core-DqPydYyx.mjs → backend-core-BsKP1LVg.mjs} +204 -164
  8. package/dist/{builder-DBgto1yn.js → builder-f4F_NRvK.js} +245 -153
  9. package/dist/{caller-factory-NEfgD5E0.js → caller-factory-DHywSoGZ.js} +7 -5
  10. package/dist/cli.mjs +14 -7
  11. package/dist/crpc/index.js +1 -127
  12. package/dist/{middleware-Bg-PdtrI.js → middleware-Cgrv2jIu.js} +1 -1
  13. package/dist/orm/index.d.ts +1 -1
  14. package/dist/orm/index.js +486 -121
  15. package/dist/plugins/index.js +1 -1
  16. package/dist/{procedure-caller-9m6NBxQu.js → procedure-caller-Rj6z3ai7.js} +1 -1
  17. package/dist/{procedure-name-Cy1AxayA.d.ts → procedure-name-Bo5KMcqc.d.ts} +15 -3
  18. package/dist/{query-context-ydn9kb6P.js → query-context-C90vNlc9.js} +131 -30
  19. package/dist/query-options-C_eBSIXG.js +247 -0
  20. package/dist/ratelimit/index.d.ts +26 -6
  21. package/dist/ratelimit/index.js +427 -100
  22. package/dist/ratelimit/react/index.d.ts +14 -0
  23. package/dist/ratelimit/react/index.js +149 -16
  24. package/dist/react/index.d.ts +3 -1
  25. package/dist/react/index.js +48 -15
  26. package/dist/rsc/index.js +22 -33
  27. package/dist/server/index.d.ts +1 -1
  28. package/dist/server/index.js +3 -3
  29. package/dist/solid/index.js +19 -5
  30. package/dist/watcher.mjs +2 -2
  31. package/dist/{where-clause-compiler-WF9UcrAB.d.ts → where-clause-compiler-BRhLW1dp.d.ts} +51 -0
  32. package/package.json +1 -1
  33. package/skills/kitcn/SKILL.md +1 -0
  34. package/skills/kitcn/references/features/create-plugins.md +1 -1
  35. package/skills/kitcn/references/features/orm.md +11 -1
  36. package/skills/kitcn/references/features/ratelimit.md +105 -0
  37. package/skills/kitcn/references/setup/server.md +1 -1
  38. package/dist/query-options-C96zLANM.js +0 -121
@@ -1,4 +1,4 @@
1
- import { C as ConvexNumberBuilderInitial, E as ConvexIdBuilderInitial, N as ConvexCustomBuilderInitial, dn as ConvexTableWithColumns, tr as ConvexTextBuilderInitial } from "../where-clause-compiler-WF9UcrAB.js";
1
+ import { C as ConvexNumberBuilderInitial, E as ConvexIdBuilderInitial, N as ConvexCustomBuilderInitial, dn as ConvexTableWithColumns, tr as ConvexTextBuilderInitial } from "../where-clause-compiler-BRhLW1dp.js";
2
2
  import * as convex_values0 from "convex/values";
3
3
  import { GenericId, Infer, Value } from "convex/values";
4
4
  import { DocumentByName, GenericDataModel, GenericDatabaseReader, GenericDatabaseWriter, TableNamesInDataModel } from "convex/server";
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { A as defaultIsUnauthorized, D as writeAuthSessionFallbackData, E as readAuthSessionFallbackToken, T as readAuthSessionFallbackData, _ as useAuthValue, d as decodeJwtExp, f as isSessionSyncGraceActive, g as useAuthStore, k as CRPCClientError, n as AuthProvider, o as ConvexProviderWithAuth$1, s as FetchAccessTokenContext, t as AUTH_SESSION_SYNC_GRACE_MS, w as clearAuthSessionFallback } from "../../auth-store-ssZDPa37.js";
2
+ import { A as defaultIsUnauthorized, D as writeAuthSessionFallbackData, E as readAuthSessionFallbackToken, T as readAuthSessionFallbackData, _ as useAuthValue, d as decodeJwtExp, f as isSessionSyncGraceActive, g as useAuthStore, k as CRPCClientError, n as AuthProvider, o as ConvexProviderWithAuth$1, s as FetchAccessTokenContext, t as AUTH_SESSION_SYNC_GRACE_MS, w as clearAuthSessionFallback } from "../../auth-store-BnGZxmnY.js";
3
3
  import { useConvexAuth } from "convex/react";
4
4
  import { useCallback, useEffect, useMemo, useRef } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
@@ -3,7 +3,7 @@ import { r as partial } from "../validators-C7LelqTN.js";
3
3
  import { i as defineAuth, n as createDisabledAuthRuntime, r as getGeneratedAuthDisabledReason, t as DEFAULT_AUTH_DEFINITION_PATH } from "../generated-contract-disabled-BXaz7JCE.js";
4
4
  import { n as createGeneratedFunctionReference, o as isQueryCtx, s as isRunMutationCtx } from "../api-entry-N3nBOlI2.js";
5
5
  import { n as customCtx, r as customMutation } from "../customFunctions-DxEEO4Dq.js";
6
- import { a as mergedStream, l as unsetToken, o as stream, t as getByIdWithOrmQueryFallback, v as eq } from "../query-context-ydn9kb6P.js";
6
+ import { o as mergedStream, s as stream, t as getByIdWithOrmQueryFallback, u as unsetToken, y as eq } from "../query-context-C90vNlc9.js";
7
7
  import { n as convex } from "../convex-plugin-BHVCqWTH.js";
8
8
  import { v } from "convex/values";
9
9
  import { internalActionGeneric, internalMutationGeneric, internalQueryGeneric, paginationOptsValidator } from "convex/server";
@@ -160,6 +160,11 @@ const filterByWhere = (doc, where, filterWhere) => {
160
160
  }
161
161
  return true;
162
162
  };
163
+ const getByIdInTable = async (ctx, model, value) => {
164
+ if (typeof value !== "string") return null;
165
+ const normalizedId = ctx.db.normalizeId(model, value);
166
+ return normalizedId === null ? null : await ctx.db.get(normalizedId);
167
+ };
163
168
  const generateQuery = (ctx, schema, args) => {
164
169
  const { boundField, index, indexFields, values } = findIndex(schema, args) ?? {};
165
170
  const usableIndex = index?.indexDescriptor === "by_creation_time" ? void 0 : index;
@@ -207,7 +212,7 @@ const paginate = async (ctx, schema, betterAuthSchema, args) => {
207
212
  model: args.model,
208
213
  where: [uniqueWhere]
209
214
  }) || {};
210
- const doc = uniqueWhere.field === "_id" ? await ctx.db.get(uniqueWhere.value) : await ctx.db.query(args.model).withIndex(index?.indexDescriptor, (q) => q.eq(index?.fields[0], uniqueWhere.value)).unique();
215
+ const doc = uniqueWhere.field === "_id" ? await getByIdInTable(ctx, args.model, uniqueWhere.value) : await ctx.db.query(args.model).withIndex(index?.indexDescriptor, (q) => q.eq(index?.fields[0], uniqueWhere.value)).unique();
211
216
  if (filterByWhere(doc, args.where, (w) => w !== uniqueWhere)) return {
212
217
  continueCursor: "",
213
218
  isDone: true,
@@ -233,7 +238,7 @@ const paginate = async (ctx, schema, betterAuthSchema, args) => {
233
238
  if (inWhere.field === "_id") return {
234
239
  continueCursor: "",
235
240
  isDone: true,
236
- page: (await asyncMap(inWhere.value, async (value) => ctx.db.get(value))).flatMap((doc) => doc ? [doc] : []).filter((doc) => filterByWhere(doc, args.where, (w) => w !== inWhere)).sort((a, b) => {
241
+ page: (await asyncMap(inWhere.value, async (value) => getByIdInTable(ctx, args.model, value))).flatMap((doc) => doc ? [doc] : []).filter((doc) => filterByWhere(doc, args.where, (w) => w !== inWhere)).sort((a, b) => {
237
242
  if (args.sortBy?.field === "createdAt") return args.sortBy.direction === "asc" ? a._creationTime - b._creationTime : b._creationTime - a._creationTime;
238
243
  if (args.sortBy) {
239
244
  const aValue = a[args.sortBy.field];
@@ -261,18 +266,7 @@ const paginate = async (ctx, schema, betterAuthSchema, args) => {
261
266
  };
262
267
  }
263
268
  const notInWhere = args.where?.find((w) => w.operator === "not_in");
264
- if (notInWhere) {
265
- if (!Array.isArray(notInWhere.value)) throw new TypeError("not_in clause value must be an array");
266
- const result = await generateQuery(ctx, schema, {
267
- ...args,
268
- where: args.where?.filter((w) => w !== notInWhere)
269
- }).paginate(paginationOpts);
270
- const filteredPage = result.page.filter((doc) => filterByWhere(doc, [notInWhere]));
271
- return {
272
- ...result,
273
- page: filteredPage.map((doc) => selectFields(doc, args.select))
274
- };
275
- }
269
+ if (notInWhere && !Array.isArray(notInWhere.value)) throw new TypeError("not_in clause value must be an array");
276
270
  const result = await generateQuery(ctx, schema, args).paginate(paginationOpts);
277
271
  return {
278
272
  ...result,
@@ -763,7 +757,7 @@ const handlePagination = async (next, { limit, numItems } = {}) => {
763
757
  isDone: false
764
758
  };
765
759
  const onResult = (result) => {
766
- state.cursor = result.pageStatus === "SplitRecommended" || result.pageStatus === "SplitRequired" ? result.splitCursor ?? result.continueCursor : result.continueCursor;
760
+ state.cursor = result.continueCursor;
767
761
  if (result.page) {
768
762
  state.docs.push(...result.page);
769
763
  state.isDone = limit && state.docs.length >= limit || result.isDone;
@@ -790,7 +784,7 @@ const handlePagination = async (next, { limit, numItems } = {}) => {
790
784
  return state;
791
785
  };
792
786
  const hasOrWhere = (where) => where?.some((clause) => clause.connector === "OR") ?? false;
793
- const assertSupportedBulkOrWhere = (where, operation) => {
787
+ const assertSupportedOrWhere = (where, operation) => {
794
788
  if (hasOrWhere(where) && !where?.every((clause) => clause.connector === "OR")) throw new Error(`Mixed OR/AND where clauses are not supported for ${operation}`);
795
789
  };
796
790
  const parseWhere = (where) => {
@@ -897,6 +891,7 @@ const httpAdapter = (ctx, { authFunctions, debugLogs, schema }) => {
897
891
  id: "convex",
898
892
  options: { isRunMutationCtx: isRunMutationCtx(ctx) },
899
893
  count: async (data) => {
894
+ assertSupportedOrWhere(data.where, "count");
900
895
  if (hasOrWhere(data.where)) return dedupeDocsById((await asyncMap(data.where, async (w) => handlePagination(async ({ paginationOpts }) => await ctx.runQuery(authFunctions.findMany, {
901
896
  ...data,
902
897
  paginationOpts,
@@ -932,7 +927,7 @@ const httpAdapter = (ctx, { authFunctions, debugLogs, schema }) => {
932
927
  },
933
928
  deleteMany: async (data) => {
934
929
  if (!("runMutation" in ctx)) throw new Error("ctx is not a mutation ctx");
935
- assertSupportedBulkOrWhere(data.where, "deleteMany");
930
+ assertSupportedOrWhere(data.where, "deleteMany");
936
931
  if (hasOrWhere(data.where)) {
937
932
  const ids = await collectIdsForOrWhere({
938
933
  model: data.model,
@@ -960,6 +955,7 @@ const httpAdapter = (ctx, { authFunctions, debugLogs, schema }) => {
960
955
  },
961
956
  findMany: async (data) => {
962
957
  if (data.offset) throw new Error("offset not supported");
958
+ assertSupportedOrWhere(data.where, "findMany");
963
959
  if (hasOrWhere(data.where)) {
964
960
  const { select: _ignoredSelect, ...queryData } = data;
965
961
  let docs = dedupeDocsById((await asyncMap(data.where, async (w) => handlePagination(async ({ paginationOpts }) => await ctx.runQuery(authFunctions.findMany, {
@@ -1012,7 +1008,7 @@ const httpAdapter = (ctx, { authFunctions, debugLogs, schema }) => {
1012
1008
  },
1013
1009
  updateMany: async (data) => {
1014
1010
  if (!("runMutation" in ctx)) throw new Error("ctx is not a mutation ctx");
1015
- assertSupportedBulkOrWhere(data.where, "updateMany");
1011
+ assertSupportedOrWhere(data.where, "updateMany");
1016
1012
  if (hasOrWhere(data.where)) {
1017
1013
  const ids = await collectIdsForOrWhere({
1018
1014
  model: data.model,
@@ -1073,6 +1069,7 @@ const dbAdapter = (ctx, getAuthOptions, { authFunctions, debugLogs, schema }) =>
1073
1069
  id: "convex",
1074
1070
  options: { isRunMutationCtx: isRunMutationCtx(ctx) },
1075
1071
  count: async (data) => {
1072
+ assertSupportedOrWhere(data.where, "count");
1076
1073
  if (hasOrWhere(data.where)) return dedupeDocsById((await asyncMap(data.where, async (w) => handlePagination(async ({ paginationOpts }) => await findManyHandler(ctx, {
1077
1074
  ...data,
1078
1075
  paginationOpts,
@@ -1108,7 +1105,7 @@ const dbAdapter = (ctx, getAuthOptions, { authFunctions, debugLogs, schema }) =>
1108
1105
  },
1109
1106
  deleteMany: async (data) => {
1110
1107
  if (!("runMutation" in ctx)) throw new Error("ctx is not a mutation ctx");
1111
- assertSupportedBulkOrWhere(data.where, "deleteMany");
1108
+ assertSupportedOrWhere(data.where, "deleteMany");
1112
1109
  if (hasOrWhere(data.where)) {
1113
1110
  const ids = await collectIdsForOrWhere({
1114
1111
  model: data.model,
@@ -1136,6 +1133,7 @@ const dbAdapter = (ctx, getAuthOptions, { authFunctions, debugLogs, schema }) =>
1136
1133
  },
1137
1134
  findMany: async (data) => {
1138
1135
  if (data.offset) throw new Error("offset not supported");
1136
+ assertSupportedOrWhere(data.where, "findMany");
1139
1137
  if (hasOrWhere(data.where)) {
1140
1138
  const { select: _ignoredSelect, ...queryData } = data;
1141
1139
  let docs = dedupeDocsById((await asyncMap(data.where, async (w) => handlePagination(async ({ paginationOpts }) => await findManyHandler(ctx, {
@@ -1187,7 +1185,7 @@ const dbAdapter = (ctx, getAuthOptions, { authFunctions, debugLogs, schema }) =>
1187
1185
  },
1188
1186
  updateMany: async (data) => {
1189
1187
  if (!("runMutation" in ctx)) throw new Error("ctx is not a mutation ctx");
1190
- assertSupportedBulkOrWhere(data.where, "updateMany");
1188
+ assertSupportedOrWhere(data.where, "updateMany");
1191
1189
  if (hasOrWhere(data.where)) {
1192
1190
  const ids = await collectIdsForOrWhere({
1193
1191
  model: data.model,
@@ -1,4 +1,4 @@
1
- import { H as ConvexContext, W as LazyCaller } from "../../procedure-name-Cy1AxayA.js";
1
+ import { H as ConvexContext, W as LazyCaller } from "../../procedure-name-Bo5KMcqc.js";
2
2
  import { t as GetTokenOptions } from "../../token-B9Bjcqug.js";
3
3
 
4
4
  //#region src/auth-nextjs/index.d.ts
@@ -1,6 +1,6 @@
1
1
  import { t as getToken } from "../../token-oA2EMtPA.js";
2
2
  import { n as defaultIsUnauthorized } from "../../error-Bvo7YEhk.js";
3
- import { t as createCallerFactory } from "../../caller-factory-NEfgD5E0.js";
3
+ import { t as createCallerFactory } from "../../caller-factory-DHywSoGZ.js";
4
4
 
5
5
  //#region src/auth-nextjs/index.ts
6
6
  /** biome-ignore-all lint/suspicious/noExplicitAny: lib */
@@ -69,7 +69,7 @@ function convexBetterAuth(opts) {
69
69
  const jwtCacheEnabled = auth.jwtCache !== false;
70
70
  const { createContext, createCaller } = createCallerFactory({
71
71
  api: opts.api,
72
- auth: jwtCacheEnabled ? {
72
+ auth: {
73
73
  getToken: (siteUrl, headers, getTokenOpts) => {
74
74
  const mutableHeaders = new Headers(headers);
75
75
  stripHopByHopHeaders(mutableHeaders);
@@ -78,14 +78,14 @@ function convexBetterAuth(opts) {
78
78
  basePath: auth.basePath,
79
79
  ...getTokenOpts,
80
80
  jwtCache: {
81
- enabled: true,
81
+ enabled: jwtCacheEnabled,
82
82
  expirationToleranceSeconds: auth.expirationToleranceSeconds,
83
83
  isAuthError: auth.isUnauthorized ?? defaultIsUnauthorized
84
84
  }
85
85
  });
86
86
  },
87
87
  isUnauthorized: auth.isUnauthorized ?? defaultIsUnauthorized
88
- } : void 0,
88
+ },
89
89
  convexSiteUrl: opts.convexSiteUrl,
90
90
  convexUrl: opts.convexUrl
91
91
  });
@@ -170,7 +170,10 @@ const isSessionSyncGraceActive = (sessionSyncGraceUntil) => typeof sessionSyncGr
170
170
  /** Decode JWT expiration (ms timestamp) from token */
171
171
  function decodeJwtExp(token) {
172
172
  try {
173
- const payload = JSON.parse(atob(token.split(".")[1]));
173
+ const segment = token.split(".")[1];
174
+ if (!segment) return null;
175
+ const binary = atob(segment.replaceAll("-", "+").replaceAll("_", "/"));
176
+ const payload = JSON.parse(new TextDecoder().decode(Uint8Array.from(binary, (char) => char.charCodeAt(0))));
174
177
  return payload.exp ? payload.exp * 1e3 : null;
175
178
  } catch {
176
179
  return null;