kitcn 0.22.1 → 0.24.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 (33) hide show
  1. package/dist/aggregate/index.d.ts +1 -1
  2. package/dist/auth/nextjs/index.d.ts +1 -1
  3. package/dist/auth/nextjs/index.js +1 -1
  4. package/dist/{builder-Dwy6D2QA.js → builder-CsxVc5xC.js} +110 -57
  5. package/dist/{caller-factory-DHywSoGZ.js → caller-factory-CWa0ELLD.js} +1 -1
  6. package/dist/cli.mjs +96 -20
  7. package/dist/crpc/index.d.ts +3 -3
  8. package/dist/crpc/index.js +3 -3
  9. package/dist/{http-types-zsMHb_QN.d.ts → http-types-DXOgaerG.d.ts} +46 -1
  10. package/dist/{middleware-qzHEHaDy.js → middleware-DUd1Sj39.js} +1 -1
  11. package/dist/orm/index.d.ts +1 -1
  12. package/dist/plugins/index.js +1 -1
  13. package/dist/{procedure-caller-JB9kjYsy.js → procedure-caller-DQxnLBS_.js} +2 -2
  14. package/dist/{procedure-name-exVcmr_p.d.ts → procedure-name-C20pFZnk.d.ts} +21 -7
  15. package/dist/{query-options-C_eBSIXG.js → query-options-CzRV4G4N.js} +33 -1
  16. package/dist/ratelimit/index.d.ts +45 -9
  17. package/dist/ratelimit/index.js +255 -101
  18. package/dist/react/index.d.ts +9 -6
  19. package/dist/react/index.js +81 -18
  20. package/dist/rsc/index.d.ts +4 -7
  21. package/dist/rsc/index.js +5 -9
  22. package/dist/server/index.d.ts +2 -2
  23. package/dist/server/index.js +3 -3
  24. package/dist/solid/index.d.ts +9 -6
  25. package/dist/solid/index.js +81 -18
  26. package/dist/{transformer-C6pGVHqx.js → transformer-yZuBWo8v.js} +45 -1
  27. package/dist/{types-jNTcza_a.d.ts → types-BHR7ZKKD.d.ts} +1 -1
  28. package/dist/{where-clause-compiler-B_H3oio5.d.ts → where-clause-compiler-DW6jy2er.d.ts} +59 -59
  29. package/package.json +1 -1
  30. package/skills/kitcn/references/features/http.md +26 -1
  31. package/skills/kitcn/references/features/ratelimit.md +11 -0
  32. package/skills/kitcn/references/features/react.md +1 -1
  33. package/skills/kitcn/references/setup/server.md +35 -5
@@ -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-B_H3oio5.js";
1
+ import { C as ConvexNumberBuilderInitial, E as ConvexIdBuilderInitial, N as ConvexCustomBuilderInitial, dn as ConvexTableWithColumns, tr as ConvexTextBuilderInitial } from "../where-clause-compiler-DW6jy2er.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,4 +1,4 @@
1
- import { H as ConvexContext, W as LazyCaller } from "../../procedure-name-exVcmr_p.js";
1
+ import { H as ConvexContext, W as LazyCaller } from "../../procedure-name-C20pFZnk.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-xlpENMVn.js";
2
2
  import { n as defaultIsUnauthorized } from "../../error-Bvo7YEhk.js";
3
- import { t as createCallerFactory } from "../../caller-factory-DHywSoGZ.js";
3
+ import { t as createCallerFactory } from "../../caller-factory-CWa0ELLD.js";
4
4
 
5
5
  //#region src/auth-nextjs/index.ts
6
6
  /** biome-ignore-all lint/suspicious/noExplicitAny: lib */
@@ -1,7 +1,6 @@
1
- import { i as pick } from "./upstream-BR6sBLg3.js";
2
1
  import { o as vRequired, t as addFieldsToValidator } from "./validators-C7LelqTN.js";
3
2
  import { n as customCtx, t as NoOp } from "./customFunctions-DxEEO4Dq.js";
4
- import { s as getTransformer } from "./transformer-C6pGVHqx.js";
3
+ import { s as getTransformer } from "./transformer-yZuBWo8v.js";
5
4
  import { ConvexError, v } from "convex/values";
6
5
  import { HttpRouter, actionGeneric, httpActionGeneric, internalActionGeneric, internalMutationGeneric, internalQueryGeneric, mutationGeneric, queryGeneric } from "convex/server";
7
6
  import { z } from "zod";
@@ -501,25 +500,43 @@ function withSystemFields(tableName, zObject) {
501
500
  _creationTime: z$1.number()
502
501
  };
503
502
  }
503
+ /**
504
+ * Single-pass `pick` over own keys, preserving `obj`'s insertion order.
505
+ *
506
+ * The shared `pick` helper is `Object.fromEntries(Object.entries(obj).filter(
507
+ * ([k]) => keys.includes(k)))`, i.e. O(fields^2) with three intermediate
508
+ * allocations. This runs on every request, so it gets a Set instead.
509
+ */
510
+ function pickKeys(obj, keys) {
511
+ const result = {};
512
+ for (const key of Object.keys(obj)) if (keys.has(key)) result[key] = obj[key];
513
+ return result;
514
+ }
504
515
  function customFnBuilder(builder, customization) {
505
516
  const customInput = customization.input ?? NoOp.input;
506
517
  const inputArgs = customization.args ?? NoOp.args;
507
518
  return function customBuilder(fn) {
508
- const { args, handler = fn, skipConvexValidation = false, returns: maybeObject, ...extra } = fn;
519
+ const { args, handler = fn, skipConvexValidation = false, skipZodReturnsValidation = false, returns: maybeObject, ...extra } = fn;
509
520
  const returns = maybeObject && !(maybeObject instanceof zCore.$ZodType) ? z$1.object(maybeObject) : maybeObject;
510
521
  const returnValidator = returns && !skipConvexValidation ? { returns: zodOutputToConvex(returns) } : null;
522
+ const parseReturns = returns && !skipZodReturnsValidation ? (value) => returns.parseAsync(value === void 0 ? null : value) : null;
511
523
  if (args) {
512
524
  let argsValidator = args;
513
525
  if (argsValidator instanceof zCore.$ZodType) if (argsValidator instanceof zCore.$ZodObject) argsValidator = argsValidator._zod.def.shape;
514
526
  else throw new Error("Unsupported zod type as args validator: " + argsValidator.constructor.name);
515
527
  const convexValidator = zodToConvexFields(argsValidator);
528
+ const inputArgKeys = Object.keys(inputArgs);
529
+ const inputArgKeySet = new Set(inputArgKeys);
530
+ const argKeySet = new Set(Object.keys(argsValidator));
531
+ let argsSchema;
516
532
  return builder({
517
533
  args: skipConvexValidation ? void 0 : addFieldsToValidator(convexValidator, inputArgs),
518
534
  ...returnValidator,
519
535
  handler: async (ctx, allArgs) => {
520
- const added = await customInput(ctx, pick(allArgs, Object.keys(inputArgs)), extra);
521
- const rawArgs = pick(allArgs, Object.keys(argsValidator));
522
- const parsed = await z$1.object(argsValidator).safeParseAsync(rawArgs);
536
+ const added = await customInput(ctx, inputArgKeys.length === 0 ? {} : pickKeys(allArgs, inputArgKeySet), extra);
537
+ const rawArgs = pickKeys(allArgs, argKeySet);
538
+ argsSchema ??= z$1.object(argsValidator);
539
+ const parsed = await argsSchema.safeParseAsync(rawArgs);
523
540
  if (!parsed.success) throw new ConvexError({ ZodError: JSON.parse(JSON.stringify(parsed.error.issues, null, 2)) });
524
541
  const args = parsed.data;
525
542
  const ret = await handler({
@@ -529,7 +546,7 @@ function customFnBuilder(builder, customization) {
529
546
  ...args,
530
547
  ...added.args
531
548
  });
532
- const result = returns ? await returns.parseAsync(ret === void 0 ? null : ret) : ret;
549
+ const result = parseReturns ? await parseReturns(ret) : ret;
533
550
  if (added.onSuccess) await added.onSuccess({
534
551
  ctx,
535
552
  args,
@@ -551,7 +568,7 @@ function customFnBuilder(builder, customization) {
551
568
  ...args,
552
569
  ...added.args
553
570
  });
554
- const result = returns ? await returns.parseAsync(ret === void 0 ? null : ret) : ret;
571
+ const result = parseReturns ? await parseReturns(ret) : ret;
555
572
  if (added.onSuccess) await added.onSuccess({
556
573
  ctx,
557
574
  args,
@@ -971,29 +988,51 @@ function getBaseSchema(schema) {
971
988
  if (schema instanceof z.ZodDefault) return getBaseSchema(schema._def.innerType);
972
989
  return schema;
973
990
  }
974
- function isArraySchema(schema) {
975
- return getBaseSchema(schema) instanceof z.ZodArray;
976
- }
977
- function isNumberSchema(schema) {
978
- return getBaseSchema(schema) instanceof z.ZodNumber;
979
- }
980
- function isBooleanSchema(schema) {
981
- return getBaseSchema(schema) instanceof z.ZodBoolean;
991
+ /**
992
+ * Resolve each field's coercion kind from the query schema, once.
993
+ *
994
+ * The kind is a static property of the schema, but zod 4 overrides
995
+ * `Symbol.hasInstance`, so leaving it in the request path pays a `Set.has`
996
+ * per unwrap step per field per request.
997
+ *
998
+ * Fields absent from the map fall through to the raw string(s) branch, which
999
+ * is also where a non-`ZodObject` query schema lands (it has no readable
1000
+ * shape, so it gets no coercion at all).
1001
+ */
1002
+ function buildQueryCoercion(schema) {
1003
+ const coercion = /* @__PURE__ */ new Map();
1004
+ if (!(schema instanceof z.ZodObject)) return coercion;
1005
+ for (const [key, fieldSchema] of Object.entries(schema.shape)) {
1006
+ const base = getBaseSchema(fieldSchema);
1007
+ if (base instanceof z.ZodArray) coercion.set(key, "array");
1008
+ else if (base instanceof z.ZodNumber) coercion.set(key, "number");
1009
+ else if (base instanceof z.ZodBoolean) coercion.set(key, "boolean");
1010
+ }
1011
+ return coercion;
982
1012
  }
983
- function parseQueryParams(url, schema) {
1013
+ function parseQueryParams(url, coercion) {
984
1014
  const params = {};
985
- const keys = new Set(url.searchParams.keys());
986
- const shape = schema instanceof z.ZodObject ? schema.shape : {};
987
- for (const key of keys) {
988
- const values = url.searchParams.getAll(key);
989
- const fieldSchema = shape[key];
990
- if (fieldSchema) if (isArraySchema(fieldSchema)) params[key] = values;
991
- else if (isNumberSchema(fieldSchema)) params[key] = Number(values[0]);
992
- else if (isBooleanSchema(fieldSchema)) {
1015
+ const collected = /* @__PURE__ */ new Map();
1016
+ for (const [key, value] of url.searchParams) {
1017
+ const existing = collected.get(key);
1018
+ if (existing) existing.push(value);
1019
+ else collected.set(key, [value]);
1020
+ }
1021
+ for (const [key, values] of collected) switch (coercion.get(key)) {
1022
+ case "array":
1023
+ params[key] = values;
1024
+ break;
1025
+ case "number":
1026
+ params[key] = Number(values[0]);
1027
+ break;
1028
+ case "boolean": {
993
1029
  const val = values[0].toLowerCase();
994
1030
  params[key] = val === "true" || val === "1";
995
- } else params[key] = values.length === 1 ? values[0] : values;
996
- else params[key] = values.length === 1 ? values[0] : values;
1031
+ break;
1032
+ }
1033
+ default:
1034
+ params[key] = values.length === 1 ? values[0] : values;
1035
+ break;
997
1036
  }
998
1037
  return params;
999
1038
  }
@@ -1017,6 +1056,7 @@ function resolveHttpProcedureInfo(def) {
1017
1056
  function createProcedure(def, handler, _type) {
1018
1057
  if (!def.route) throw new Error("Route must be defined before action. Use .route(path, method) first.");
1019
1058
  const middlewareProcedure = resolveHttpProcedureInfo(def);
1059
+ const queryCoercion = buildQueryCoercion(def.querySchema);
1020
1060
  /**
1021
1061
  * Hono-compatible handler function.
1022
1062
  * When used with HttpRouterWithHono, Convex ctx is passed via c.env.
@@ -1046,7 +1086,7 @@ function createProcedure(def, handler, _type) {
1046
1086
  }
1047
1087
  let parsedQuery;
1048
1088
  if (def.querySchema) {
1049
- const queryParams = parseQueryParams(url, def.querySchema);
1089
+ const queryParams = parseQueryParams(url, queryCoercion);
1050
1090
  try {
1051
1091
  parsedQuery = def.querySchema.parse(queryParams);
1052
1092
  } catch (error) {
@@ -1720,24 +1760,18 @@ const replaceUnencodableInputTypes = (schema) => {
1720
1760
  * unchanged) but carries no checks, transforms, or defaults. cRPC's own
1721
1761
  * `.input()` parse stays the single authoritative one, so refinements and
1722
1762
  * transforms never run twice.
1763
+ *
1764
+ * Throws when the shape has no Convex equivalent, which is also the
1765
+ * feasibility test `resolveConvexArgsShape` steps down its fallback ladder on.
1723
1766
  */
1724
- const toWireShape = (shape) => {
1725
- try {
1726
- return convexToZodFields(zodToConvexFields(shape));
1727
- } catch {
1728
- return shape;
1729
- }
1730
- };
1767
+ const toWireShape = (shape) => convexToZodFields(zodToConvexFields(shape));
1731
1768
  const resolveConvexArgsShape = (inputShape) => {
1732
1769
  if (!inputShape) return;
1733
- const rawSchema = z.object(inputShape);
1734
1770
  try {
1735
- zodToConvex(rawSchema);
1736
1771
  return toWireShape(inputShape);
1737
1772
  } catch {
1738
- const compatibleSchema = replaceUnencodableInputTypes(rawSchema);
1773
+ const compatibleSchema = replaceUnencodableInputTypes(z.object(inputShape));
1739
1774
  try {
1740
- zodToConvex(compatibleSchema);
1741
1775
  return toWireShape(compatibleSchema.shape);
1742
1776
  } catch {
1743
1777
  return Object.fromEntries(Object.keys(inputShape).map((key) => [key, z.any()]));
@@ -1760,6 +1794,29 @@ const relaxSupersededKeys = (schema, superseded) => {
1760
1794
  return schema;
1761
1795
  }
1762
1796
  };
1797
+ const buildInputPlan = (inputSchemas) => {
1798
+ if (inputSchemas.length === 1) return {
1799
+ entries: [],
1800
+ single: inputSchemas[0]
1801
+ };
1802
+ const ownerOf = /* @__PURE__ */ new Map();
1803
+ inputSchemas.forEach((schema, index) => {
1804
+ for (const key of Object.keys(schema.shape)) ownerOf.set(key, index);
1805
+ });
1806
+ return { entries: inputSchemas.map((schema, index) => {
1807
+ const keys = Object.keys(schema.shape);
1808
+ const owned = [];
1809
+ const superseded = /* @__PURE__ */ new Set();
1810
+ for (const key of keys) if (ownerOf.get(key) === index) owned.push(key);
1811
+ else superseded.add(key);
1812
+ return {
1813
+ keys,
1814
+ owned,
1815
+ scoped: relaxSupersededKeys(schema, [...superseded]),
1816
+ superseded
1817
+ };
1818
+ }) };
1819
+ };
1763
1820
  /**
1764
1821
  * Parse the wire payload through every `.input()` schema.
1765
1822
  *
@@ -1768,20 +1825,14 @@ const relaxSupersededKeys = (schema, superseded) => {
1768
1825
  * so object-level checks run against the shape they were written for without an
1769
1826
  * earlier, superseded declaration vetoing the payload.
1770
1827
  */
1771
- const parseInput = (inputSchemas, value) => {
1828
+ const parseInput = (plan, value) => {
1772
1829
  try {
1773
- if (inputSchemas.length === 1) return inputSchemas[0].parse(value);
1774
- const ownerOf = /* @__PURE__ */ new Map();
1775
- inputSchemas.forEach((schema, index) => {
1776
- for (const key of Object.keys(schema.shape)) ownerOf.set(key, index);
1777
- });
1830
+ if (plan.single) return plan.single.parse(value);
1831
+ const { entries } = plan;
1778
1832
  const source = isPlainObject(value) ? value : {};
1779
1833
  const parsed = {};
1780
- for (let index = inputSchemas.length - 1; index >= 0; index -= 1) {
1781
- const schema = inputSchemas[index];
1782
- const keys = Object.keys(schema.shape);
1783
- const superseded = new Set(keys.filter((key) => ownerOf.get(key) !== index));
1784
- const scoped = relaxSupersededKeys(schema, [...superseded]);
1834
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
1835
+ const { keys, owned, scoped, superseded } = entries[index];
1785
1836
  const narrowed = {};
1786
1837
  for (const key of keys) {
1787
1838
  if (superseded.has(key)) {
@@ -1791,7 +1842,7 @@ const parseInput = (inputSchemas, value) => {
1791
1842
  if (Object.hasOwn(source, key)) narrowed[key] = source[key];
1792
1843
  }
1793
1844
  const result = scoped.parse(narrowed);
1794
- for (const key of keys) if (ownerOf.get(key) === index && key in result) parsed[key] = result[key];
1845
+ for (const key of owned) if (key in result) parsed[key] = result[key];
1795
1846
  }
1796
1847
  return parsed;
1797
1848
  } catch (cause) {
@@ -1877,19 +1928,21 @@ var ProcedureBuilder = class {
1877
1928
  _createFunction(handler, baseFunction, customFn, fnType) {
1878
1929
  const { middlewares, inputSchemas, outputSchema, meta, procedureName, functionConfig, isInternal } = this._def;
1879
1930
  const convexArgs = resolveConvexArgsShape(this._getMergedInput());
1931
+ const inputPlan = buildInputPlan(inputSchemas);
1880
1932
  const customFunction = customFn(baseFunction, customCtx(async (_ctx) => withConvexSafeRunners(await functionConfig.createContext(_ctx))));
1881
- const returnsSchema = resolveConvexReturnsSchema(outputSchema);
1882
- const typedReturnsSchema = returnsSchema;
1933
+ const typedReturnsSchema = resolveConvexReturnsSchema(outputSchema);
1883
1934
  const typedArgs = convexArgs ?? {};
1884
- const shouldValidateOutputWithZod = !!outputSchema && returnsSchema !== outputSchema;
1885
1935
  const resolvedProcedureName = procedureName ?? inferProcedureNameFromCallsite();
1886
1936
  let fn;
1887
1937
  fn = customFunction({
1888
1938
  args: typedArgs,
1889
- ...typedReturnsSchema ? { returns: typedReturnsSchema } : {},
1939
+ ...typedReturnsSchema ? {
1940
+ returns: typedReturnsSchema,
1941
+ skipZodReturnsValidation: true
1942
+ } : {},
1890
1943
  handler: async (ctx, rawInput) => {
1891
1944
  const decodedInput = functionConfig.transformer.input.deserialize(rawInput);
1892
- const parsedInput = inputSchemas.length > 0 ? parseInput(inputSchemas, decodedInput) : decodedInput;
1945
+ const parsedInput = inputSchemas.length > 0 ? parseInput(inputPlan, decodedInput) : decodedInput;
1893
1946
  const getRawInput = async () => parsedInput;
1894
1947
  try {
1895
1948
  const result = await executeMiddlewares(middlewares, ctx, meta, resolveProcedureInfo(fnType, resolvedProcedureName, fn), parsedInput, getRawInput, async ({ ctx: resolvedCtx, input: resolvedInput }) => {
@@ -1898,7 +1951,7 @@ var ProcedureBuilder = class {
1898
1951
  input: resolvedInput === parsedInput ? parsedInput : functionConfig.transformer.input.deserialize(resolvedInput ?? parsedInput)
1899
1952
  });
1900
1953
  });
1901
- const validatedOutput = shouldValidateOutputWithZod ? outputSchema.parse(result.output) : result.output;
1954
+ const validatedOutput = outputSchema ? await outputSchema.parseAsync(result.output) : result.output;
1902
1955
  return functionConfig.transformer.output.serialize(validatedOutput);
1903
1956
  } catch (cause) {
1904
1957
  const err = toCRPCError(cause);
@@ -1,6 +1,6 @@
1
1
  import { n as defaultIsUnauthorized } from "./error-Bvo7YEhk.js";
2
2
  import { i as getFunctionType, n as getFuncRef, t as buildMetaIndex } from "./meta-utils-D9K4fICl.js";
3
- import { s as getTransformer } from "./transformer-C6pGVHqx.js";
3
+ import { s as getTransformer } from "./transformer-yZuBWo8v.js";
4
4
  import { fetchAction, fetchMutation, fetchQuery } from "convex/nextjs";
5
5
 
6
6
  //#region src/server/caller.ts
package/dist/cli.mjs CHANGED
@@ -2506,7 +2506,7 @@ function QueryProvider({ children }: { children: ReactNode }) {
2506
2506
  const FUNCTIONS_DIR_IMPORT_PLACEHOLDER$5 = "__KITCN_FUNCTIONS_DIR__";
2507
2507
  const PLUGIN_CONFIG_IMPORT_PLACEHOLDER$1 = "__KITCN_PLUGIN_CONFIG_IMPORT__";
2508
2508
  const PLUGIN_SCHEMA_IMPORT_PLACEHOLDER$1 = "__KITCN_PLUGIN_SCHEMA_IMPORT__";
2509
- const PROJECT_CRPC_IMPORT_PLACEHOLDER$3 = "__KITCN_PROJECT_CRPC_IMPORT__";
2509
+ const PROJECT_CRPC_IMPORT_PLACEHOLDER$4 = "__KITCN_PROJECT_CRPC_IMPORT__";
2510
2510
  const PROJECT_SHARED_API_IMPORT_PLACEHOLDER = "__KITCN_PROJECT_SHARED_API_IMPORT__";
2511
2511
  const PROJECT_GET_ENV_IMPORT_PLACEHOLDER$2 = "__KITCN_PROJECT_GET_ENV_IMPORT__";
2512
2512
 
@@ -2536,7 +2536,7 @@ const INIT_HTTP_IMPORT_MARKER = "// __KITCN_HTTP_IMPORTS__";
2536
2536
  const INIT_HTTP_ROUTE_MARKER = " // __KITCN_HTTP_ROUTES__";
2537
2537
  const INIT_HTTP_TEMPLATE = `import { createHttpRouter } from 'kitcn/server';
2538
2538
  import { Hono } from 'hono';
2539
- import { router } from '${PROJECT_CRPC_IMPORT_PLACEHOLDER$3}';
2539
+ import { router } from '${PROJECT_CRPC_IMPORT_PLACEHOLDER$4}';
2540
2540
  ${INIT_HTTP_IMPORT_MARKER}
2541
2541
 
2542
2542
  const app = new Hono();
@@ -2849,7 +2849,7 @@ function resolveRelativeImportPath(filePath, targetFilePath) {
2849
2849
  return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
2850
2850
  }
2851
2851
  function renderInitTemplateContent(params) {
2852
- return params.template.replaceAll(FUNCTIONS_DIR_IMPORT_PLACEHOLDER$5, resolveRelativeImportPath(params.filePath, params.functionsDir)).replaceAll(PROJECT_CRPC_IMPORT_PLACEHOLDER$3, resolveRelativeImportPath(params.filePath, params.crpcFilePath));
2852
+ return params.template.replaceAll(FUNCTIONS_DIR_IMPORT_PLACEHOLDER$5, resolveRelativeImportPath(params.filePath, params.functionsDir)).replaceAll(PROJECT_CRPC_IMPORT_PLACEHOLDER$4, resolveRelativeImportPath(params.filePath, params.crpcFilePath));
2853
2853
  }
2854
2854
 
2855
2855
  //#endregion
@@ -3424,7 +3424,7 @@ const resolvePluginScaffoldFiles = (templates, roots, functionsDir, existingTemp
3424
3424
  const lockfilePath = normalizeLockfileScaffoldPath(mappedLockfilePath) ?? normalizePath$2(relative(process.cwd(), join(rootDir, template.path)));
3425
3425
  const filePath = resolve(process.cwd(), lockfilePath);
3426
3426
  const getEnvImportPath = resolveProjectGetEnvImportPrefix(filePath, roots.envFilePath);
3427
- const content = template.content.replaceAll(FUNCTIONS_DIR_IMPORT_PLACEHOLDER$5, resolveFunctionsDirImportPrefix(filePath, functionsDir)).replaceAll(PROJECT_CRPC_IMPORT_PLACEHOLDER$3, resolveProjectCrpcImportPrefix(filePath, roots.crpcFilePath)).replaceAll(PROJECT_SHARED_API_IMPORT_PLACEHOLDER, resolveProjectSharedApiImportPrefix(filePath, roots.sharedApiFilePath)).replaceAll(PROJECT_GET_ENV_IMPORT_PLACEHOLDER$2, `import { getEnv } from '${getEnvImportPath}';`).replaceAll(PLUGIN_CONFIG_IMPORT_PLACEHOLDER$1, resolvePluginConfigImportPrefix(filePath, roots.libRootDir)).replaceAll(PLUGIN_SCHEMA_IMPORT_PLACEHOLDER$1, resolvePluginSchemaImportPrefix(filePath, roots.libRootDir));
3427
+ const content = template.content.replaceAll(FUNCTIONS_DIR_IMPORT_PLACEHOLDER$5, resolveFunctionsDirImportPrefix(filePath, functionsDir)).replaceAll(PROJECT_CRPC_IMPORT_PLACEHOLDER$4, resolveProjectCrpcImportPrefix(filePath, roots.crpcFilePath)).replaceAll(PROJECT_SHARED_API_IMPORT_PLACEHOLDER, resolveProjectSharedApiImportPrefix(filePath, roots.sharedApiFilePath)).replaceAll(PROJECT_GET_ENV_IMPORT_PLACEHOLDER$2, `import { getEnv } from '${getEnvImportPath}';`).replaceAll(PLUGIN_CONFIG_IMPORT_PLACEHOLDER$1, resolvePluginConfigImportPrefix(filePath, roots.libRootDir)).replaceAll(PLUGIN_SCHEMA_IMPORT_PLACEHOLDER$1, resolvePluginSchemaImportPrefix(filePath, roots.libRootDir));
3428
3428
  if (!(descriptor.key === "auth" && preset === "convex") && (template.target === "functions" || template.target === "lib") && content.includes("process.env")) throw new Error(`Scaffold template "${descriptor.key}/${template.id}" contains process.env. Use getEnv() instead.`);
3429
3429
  return {
3430
3430
  templateId: template.id,
@@ -6776,10 +6776,46 @@ const authRegistryItem = defineInternalRegistryItem({
6776
6776
  }
6777
6777
  });
6778
6778
 
6779
+ //#endregion
6780
+ //#region src/cli/registry/items/ratelimit/ratelimit-functions.template.ts
6781
+ const PROJECT_CRPC_IMPORT_PLACEHOLDER$3 = "__KITCN_PROJECT_CRPC_IMPORT__";
6782
+ const RATELIMIT_FUNCTIONS_TEMPLATE = `import { cleanupRatelimitState } from "kitcn/ratelimit";
6783
+ import { z } from "zod";
6784
+ import { privateMutation } from "${PROJECT_CRPC_IMPORT_PLACEHOLDER$3}";
6785
+
6786
+ const DEFAULT_BATCH_SIZE = 500;
6787
+
6788
+ export const cleanup = privateMutation
6789
+ .input(
6790
+ z.object({
6791
+ olderThanMs: z.number().positive(),
6792
+ limit: z.number().int().min(1).max(1000).optional(),
6793
+ })
6794
+ )
6795
+ .output(
6796
+ z.object({
6797
+ deleted: z.number(),
6798
+ hasMore: z.boolean(),
6799
+ })
6800
+ )
6801
+ .mutation(async ({ ctx, input }) =>
6802
+ cleanupRatelimitState(ctx.db, {
6803
+ before: Date.now() - input.olderThanMs,
6804
+ limit: input.limit ?? DEFAULT_BATCH_SIZE,
6805
+ })
6806
+ );
6807
+ `;
6808
+
6779
6809
  //#endregion
6780
6810
  //#region src/cli/registry/items/ratelimit/ratelimit-plugin.template.ts
6781
6811
  const FUNCTIONS_DIR_IMPORT_PLACEHOLDER$4 = "__KITCN_FUNCTIONS_DIR__";
6782
- const RATELIMIT_PLUGIN_TEMPLATE = `import { MINUTE, Ratelimit, RatelimitPlugin } from "kitcn/ratelimit";
6812
+ const RATELIMIT_PLUGIN_TEMPLATE = `import {
6813
+ type LimitRequest,
6814
+ MINUTE,
6815
+ Ratelimit,
6816
+ RatelimitPlugin,
6817
+ SECOND,
6818
+ } from "kitcn/ratelimit";
6783
6819
  import type { MutationCtx } from "${FUNCTIONS_DIR_IMPORT_PLACEHOLDER$4}/generated/server";
6784
6820
 
6785
6821
  const fixed = (rate: number) => Ratelimit.fixedWindow(rate, MINUTE);
@@ -6790,6 +6826,11 @@ export const ratelimitBuckets = {
6790
6826
  free: fixed(60),
6791
6827
  premium: fixed(200),
6792
6828
  },
6829
+ interactive: {
6830
+ public: Ratelimit.fixedWindow(3, 30 * SECOND),
6831
+ free: Ratelimit.fixedWindow(3, 30 * SECOND),
6832
+ premium: Ratelimit.fixedWindow(3, 30 * SECOND),
6833
+ },
6793
6834
  } as const;
6794
6835
 
6795
6836
  type RatelimitTier = keyof (typeof ratelimitBuckets)["default"];
@@ -6829,14 +6870,38 @@ async function getRequestSignals(ctx: RatelimitCtx) {
6829
6870
  };
6830
6871
  }
6831
6872
 
6873
+ /**
6874
+ * The identifier is the rate-limit partition key: everything that resolves to
6875
+ * the same string shares one budget and one \`ratelimitState\` document.
6876
+ *
6877
+ * Unauthenticated traffic is keyed by request IP so one visitor cannot spend
6878
+ * every other visitor's budget. Calls without request metadata all fall back
6879
+ * to one key.
6880
+ */
6881
+ function getRequestIdentifier(
6882
+ user: RatelimitUser | null,
6883
+ signals: LimitRequest | undefined
6884
+ ) {
6885
+ if (user) {
6886
+ return user.id;
6887
+ }
6888
+
6889
+ return signals?.ip ? \`ip:\${signals.ip}\` : "ip:unknown";
6890
+ }
6891
+
6832
6892
  export const ratelimit = RatelimitPlugin.configure({
6833
6893
  buckets: ratelimitBuckets,
6834
6894
  getBucket: ({ meta }: { meta: RatelimitMeta }) => meta.ratelimit ?? "default",
6835
6895
  getUser: ({ ctx }: { ctx: RatelimitCtx }) => ctx.user ?? null,
6836
- getIdentifier: ({ user }: { user: RatelimitUser | null }) =>
6837
- user?.id ?? "anonymous",
6838
6896
  getTier: getUserTier,
6839
6897
  getSignals: ({ ctx }: { ctx: RatelimitCtx }) => getRequestSignals(ctx),
6898
+ getIdentifier: ({
6899
+ user,
6900
+ signals,
6901
+ }: {
6902
+ user: RatelimitUser | null;
6903
+ signals: LimitRequest | undefined;
6904
+ }) => getRequestIdentifier(user, signals),
6840
6905
  prefix: ({ bucket, tier }) => \`ratelimit:\${bucket}:\${tier}\`,
6841
6906
  failureMode: "closed",
6842
6907
  enableProtection: true,
@@ -6869,6 +6934,7 @@ export const ratelimitStateTable = convexTable(
6869
6934
  (t) => [
6870
6935
  index("by_name_key_shard").on(t.name, t.key, t.shard),
6871
6936
  index("by_name_key").on(t.name, t.key),
6937
+ index("by_ts").on(t.ts),
6872
6938
  ],
6873
6939
  );
6874
6940
 
@@ -6909,18 +6975,28 @@ export function ratelimitExtension() {
6909
6975
 
6910
6976
  //#endregion
6911
6977
  //#region src/cli/registry/items/ratelimit/ratelimit-item.ts
6912
- const RATELIMIT_FILES = [createRegistryFile({
6913
- id: "ratelimit-schema",
6914
- path: "schema.ts",
6915
- target: "lib",
6916
- content: RATELIMIT_SCHEMA_TEMPLATE
6917
- }), createRegistryFile({
6918
- id: "ratelimit-plugin",
6919
- path: "plugin.ts",
6920
- target: "lib",
6921
- content: RATELIMIT_PLUGIN_TEMPLATE,
6922
- requires: ["ratelimit-schema"]
6923
- })];
6978
+ const RATELIMIT_FILES = [
6979
+ createRegistryFile({
6980
+ id: "ratelimit-schema",
6981
+ path: "schema.ts",
6982
+ target: "lib",
6983
+ content: RATELIMIT_SCHEMA_TEMPLATE
6984
+ }),
6985
+ createRegistryFile({
6986
+ id: "ratelimit-functions",
6987
+ path: "ratelimit.ts",
6988
+ target: "functions",
6989
+ content: RATELIMIT_FUNCTIONS_TEMPLATE,
6990
+ requires: ["ratelimit-schema"]
6991
+ }),
6992
+ createRegistryFile({
6993
+ id: "ratelimit-plugin",
6994
+ path: "plugin.ts",
6995
+ target: "lib",
6996
+ content: RATELIMIT_PLUGIN_TEMPLATE,
6997
+ requires: ["ratelimit-schema"]
6998
+ })
6999
+ ];
6924
7000
  function buildRatelimitCrpcRegistrationPlanFile(params) {
6925
7001
  const crpcPath = getCrpcFilePath(params.config);
6926
7002
  const baselineCrpcSource = renderInitTemplateContent({
@@ -6966,7 +7042,7 @@ const ratelimitRegistryItem = defineInternalRegistryItem({
6966
7042
  presets: [{
6967
7043
  name: "server-first",
6968
7044
  description: "Scaffold a reusable ratelimit plugin and auto-register schema extension.",
6969
- registryDependencies: ["ratelimit-schema", "ratelimit-plugin"]
7045
+ registryDependencies: RATELIMIT_FILES.map((file) => file.meta.id)
6970
7046
  }, {
6971
7047
  name: "schema-only",
6972
7048
  description: "Only register ratelimit extension in schema.",
@@ -1,5 +1,5 @@
1
- import { A as DataTransformer, F as decodeWire, I as defaultCRPCTransformer, L as encodeWire, M as WireCodec, N as createTaggedTransformer, O as CombinedDataTransformer, P as dateWireCodec, R as getTransformer, a as HttpProcedureCall, c as InferHttpInput, i as HttpErrorCode, j as DataTransformerOptions, k as DATE_CODEC_TAG, l as InferHttpOutput, n as HttpClientError, o as HttpRouteInfo, r as HttpClientFromRouter, s as HttpRouteMap, t as HttpClient, u as isHttpClientError, z as identityTransformer } from "../http-types-zsMHb_QN.js";
2
- import { A as HttpInputArgs, C as ReservedMutationOptions, D as VanillaMutation, E as VanillaAction, F as replaceUrlParam, M as RESERVED_KEYS, N as buildSearchParams, O as HttpClientOptions, P as executeHttpRequest, S as ReservedInfiniteQueryOptions, T as StaticQueryOptsParam, _ as IsPaginated, a as BaseInfiniteQueryOptsParam, b as PaginatedFnMeta, c as ConvexMutationKey, d as ConvexQueryMeta, f as EmptyObject, g as InfiniteQueryInput, h as FnMeta, i as BaseConvexQueryOptions, j as HttpProxyBaseOptions, k as HttpFormValue, l as ConvexQueryHookOptions, m as FUNC_REF_SYMBOL, n as BaseConvexActionOptions, o as ConvexActionKey, p as ExtractPaginatedItem, r as BaseConvexInfiniteQueryOptions, s as ConvexInfiniteQueryMeta, t as AuthType, u as ConvexQueryKey, v as Meta, w as ReservedQueryOptions, x as PaginationOpts, y as MutationVariables } from "../types-jNTcza_a.js";
1
+ import { B as dateWireCodec, F as DATE_CODEC_TAG, G as identityTransformer, H as defaultCRPCTransformer, I as DataTransformer, L as DataTransformerOptions, P as CombinedDataTransformer, R as WireCodec, U as encodeWire, V as decodeWire, W as getTransformer, a as HttpErrorCode, c as HttpQueryKey, d as HttpRouteMap, f as InferHttpInput, g as isHttpClientError, h as buildHttpQueryPrefixKey, i as HttpClientFromRouter, l as HttpQueryPrefixKey, m as buildHttpQueryKey, n as HttpClient, o as HttpMutationKey, p as InferHttpOutput, r as HttpClientError, s as HttpProcedureCall, t as HTTP_DEFAULT_STALE_TIME, u as HttpRouteInfo, z as createTaggedTransformer } from "../http-types-DXOgaerG.js";
2
+ import { A as HttpInputArgs, C as ReservedMutationOptions, D as VanillaMutation, E as VanillaAction, F as replaceUrlParam, M as RESERVED_KEYS, N as buildSearchParams, O as HttpClientOptions, P as executeHttpRequest, S as ReservedInfiniteQueryOptions, T as StaticQueryOptsParam, _ as IsPaginated, a as BaseInfiniteQueryOptsParam, b as PaginatedFnMeta, c as ConvexMutationKey, d as ConvexQueryMeta, f as EmptyObject, g as InfiniteQueryInput, h as FnMeta, i as BaseConvexQueryOptions, j as HttpProxyBaseOptions, k as HttpFormValue, l as ConvexQueryHookOptions, m as FUNC_REF_SYMBOL, n as BaseConvexActionOptions, o as ConvexActionKey, p as ExtractPaginatedItem, r as BaseConvexInfiniteQueryOptions, s as ConvexInfiniteQueryMeta, t as AuthType, u as ConvexQueryKey, v as Meta, w as ReservedQueryOptions, x as PaginationOpts, y as MutationVariables } from "../types-BHR7ZKKD.js";
3
3
  import { FunctionArgs, FunctionReference } from "convex/server";
4
4
 
5
5
  //#region src/crpc/auth-error.d.ts
@@ -102,4 +102,4 @@ declare function convexAction<T extends FunctionReference<'action'>>(funcRef: T,
102
102
  */
103
103
  declare function convexInfiniteQueryOptions<T extends FunctionReference<'query'>>(funcRef: T, args: Record<string, unknown> | 'skip', opts?: BaseInfiniteQueryOptsParam<T> & Record<string, unknown>, meta?: Meta): BaseConvexInfiniteQueryOptions<T> & Record<string, unknown>;
104
104
  //#endregion
105
- export { AuthMutationError, AuthType, BaseConvexActionOptions, BaseConvexInfiniteQueryOptions, BaseConvexQueryOptions, BaseInfiniteQueryOptsParam, CRPCClientError, CombinedDataTransformer, ConvexActionKey, ConvexInfiniteQueryMeta, ConvexMutationKey, ConvexQueryHookOptions, ConvexQueryKey, ConvexQueryMeta, DATE_CODEC_TAG, DataTransformer, DataTransformerOptions, EmptyObject, ExtractPaginatedItem, FUNC_REF_SYMBOL, FnMeta, HttpClient, HttpClientError, HttpClientFromRouter, HttpClientOptions, HttpErrorCode, HttpFormValue, HttpInputArgs, HttpProcedureCall, HttpProxyBaseOptions, HttpRouteInfo, HttpRouteMap, InferHttpInput, InferHttpOutput, InfiniteQueryInput, IsPaginated, Meta, MutationVariables, PaginatedFnMeta, PaginationOpts, RESERVED_KEYS, ReservedInfiniteQueryOptions, ReservedMutationOptions, ReservedQueryOptions, StaticQueryOptsParam, VanillaAction, VanillaMutation, WireCodec, buildSearchParams, convexAction, convexInfiniteQueryOptions, convexQuery, createTaggedTransformer, dateWireCodec, decodeWire, defaultCRPCTransformer, defaultIsUnauthorized, encodeWire, executeHttpRequest, getTransformer, identityTransformer, isAuthMutationError, isCRPCClientError, isCRPCError, isCRPCErrorCode, isHttpClientError, replaceUrlParam };
105
+ export { AuthMutationError, AuthType, BaseConvexActionOptions, BaseConvexInfiniteQueryOptions, BaseConvexQueryOptions, BaseInfiniteQueryOptsParam, CRPCClientError, CombinedDataTransformer, ConvexActionKey, ConvexInfiniteQueryMeta, ConvexMutationKey, ConvexQueryHookOptions, ConvexQueryKey, ConvexQueryMeta, DATE_CODEC_TAG, DataTransformer, DataTransformerOptions, EmptyObject, ExtractPaginatedItem, FUNC_REF_SYMBOL, FnMeta, HTTP_DEFAULT_STALE_TIME, HttpClient, HttpClientError, HttpClientFromRouter, HttpClientOptions, HttpErrorCode, HttpFormValue, HttpInputArgs, HttpMutationKey, HttpProcedureCall, HttpProxyBaseOptions, HttpQueryKey, HttpQueryPrefixKey, HttpRouteInfo, HttpRouteMap, InferHttpInput, InferHttpOutput, InfiniteQueryInput, IsPaginated, Meta, MutationVariables, PaginatedFnMeta, PaginationOpts, RESERVED_KEYS, ReservedInfiniteQueryOptions, ReservedMutationOptions, ReservedQueryOptions, StaticQueryOptsParam, VanillaAction, VanillaMutation, WireCodec, buildHttpQueryKey, buildHttpQueryPrefixKey, buildSearchParams, convexAction, convexInfiniteQueryOptions, convexQuery, createTaggedTransformer, dateWireCodec, decodeWire, defaultCRPCTransformer, defaultIsUnauthorized, encodeWire, executeHttpRequest, getTransformer, identityTransformer, isAuthMutationError, isCRPCClientError, isCRPCError, isCRPCErrorCode, isHttpClientError, replaceUrlParam };
@@ -1,6 +1,6 @@
1
1
  import { a as isCRPCErrorCode, i as isCRPCError, n as defaultIsUnauthorized, r as isCRPCClientError, t as CRPCClientError } from "../error-Bvo7YEhk.js";
2
- import { a as defaultCRPCTransformer, c as identityTransformer, i as decodeWire, n as createTaggedTransformer, o as encodeWire, r as dateWireCodec, s as getTransformer, t as DATE_CODEC_TAG } from "../transformer-C6pGVHqx.js";
3
- import { a as buildSearchParams, c as HttpClientError, i as RESERVED_KEYS, l as isHttpClientError, n as convexInfiniteQueryOptions, o as executeHttpRequest, r as convexQuery, s as replaceUrlParam, t as convexAction } from "../query-options-C_eBSIXG.js";
2
+ import { a as defaultCRPCTransformer, c as identityTransformer, i as decodeWire, n as createTaggedTransformer, o as encodeWire, r as dateWireCodec, s as getTransformer, t as DATE_CODEC_TAG } from "../transformer-yZuBWo8v.js";
3
+ import { a as buildSearchParams, c as HTTP_DEFAULT_STALE_TIME, d as buildHttpQueryPrefixKey, f as isHttpClientError, i as RESERVED_KEYS, l as HttpClientError, n as convexInfiniteQueryOptions, o as executeHttpRequest, r as convexQuery, s as replaceUrlParam, t as convexAction, u as buildHttpQueryKey } from "../query-options-CzRV4G4N.js";
4
4
 
5
5
  //#region src/crpc/auth-error.ts
6
6
  /**
@@ -40,4 +40,4 @@ function isAuthMutationError(error) {
40
40
  const FUNC_REF_SYMBOL = Symbol.for("convex.funcRef");
41
41
 
42
42
  //#endregion
43
- export { AuthMutationError, CRPCClientError, DATE_CODEC_TAG, FUNC_REF_SYMBOL, HttpClientError, RESERVED_KEYS, buildSearchParams, convexAction, convexInfiniteQueryOptions, convexQuery, createTaggedTransformer, dateWireCodec, decodeWire, defaultCRPCTransformer, defaultIsUnauthorized, encodeWire, executeHttpRequest, getTransformer, identityTransformer, isAuthMutationError, isCRPCClientError, isCRPCError, isCRPCErrorCode, isHttpClientError, replaceUrlParam };
43
+ export { AuthMutationError, CRPCClientError, DATE_CODEC_TAG, FUNC_REF_SYMBOL, HTTP_DEFAULT_STALE_TIME, HttpClientError, RESERVED_KEYS, buildHttpQueryKey, buildHttpQueryPrefixKey, buildSearchParams, convexAction, convexInfiniteQueryOptions, convexQuery, createTaggedTransformer, dateWireCodec, decodeWire, defaultCRPCTransformer, defaultIsUnauthorized, encodeWire, executeHttpRequest, getTransformer, identityTransformer, isAuthMutationError, isCRPCClientError, isCRPCError, isCRPCErrorCode, isHttpClientError, replaceUrlParam };
@@ -30,6 +30,18 @@ interface WireCodec {
30
30
  decode(value: unknown): unknown;
31
31
  encode(value: unknown): unknown;
32
32
  isType(value: unknown): boolean;
33
+ /**
34
+ * Declares that `isType` only ever claims a value where
35
+ * `typeof value === 'object' && value !== null` - never a primitive, a
36
+ * function, `null` or `undefined`.
37
+ *
38
+ * Lets `serialize` skip codec dispatch on primitives, which are the majority
39
+ * of visited nodes. It is opt-in because an arbitrary predicate cannot be
40
+ * classified by sampling values: a codec that claims, say, one specific
41
+ * number would be misread as object-only and silently lose its encoding.
42
+ * Codecs that leave it unset keep full dispatch.
43
+ */
44
+ readonly objectsOnly?: boolean;
33
45
  readonly tag: `$${string}`;
34
46
  }
35
47
  /**
@@ -51,6 +63,9 @@ declare const defaultCRPCTransformer: DataTransformer;
51
63
  /**
52
64
  * Normalize transformer config to split input/output shape.
53
65
  * User transformers are additive and always composed with default Date handling.
66
+ *
67
+ * Idempotent: passing a transformer this function already resolved returns it
68
+ * unchanged.
54
69
  */
55
70
  declare const getTransformer: (transformer?: DataTransformerOptions) => CombinedDataTransformer;
56
71
  /**
@@ -246,6 +261,36 @@ type HttpRouteInfo = {
246
261
  };
247
262
  /** Route map type - from codegen */
248
263
  type HttpRouteMap = Record<string, HttpRouteInfo>;
264
+ /** Exact cache key for one route + args, as stored in the QueryClient */
265
+ type HttpQueryKey = readonly ['httpQuery', string, unknown];
266
+ /** Route-wide prefix key that matches every args variant of one route */
267
+ type HttpQueryPrefixKey = readonly ['httpQuery', string];
268
+ /** Mutation key for HTTP endpoints */
269
+ type HttpMutationKey = readonly ['httpMutation', string];
270
+ /**
271
+ * Build the exact cache key for an HTTP route.
272
+ *
273
+ * Missing args normalize to `{}` so the RSC prefetch, the browser observer, and
274
+ * a hand-written `getQueryData` call all hash to the same key. Every producer
275
+ * of an `httpQuery` cache key goes through here.
276
+ */
277
+ declare function buildHttpQueryKey(routeKey: string, args?: unknown): HttpQueryKey;
278
+ /**
279
+ * Build the route-wide prefix key.
280
+ *
281
+ * Filters match on prefix, so this matches every args variant of the route.
282
+ * Not a cache key: nothing is ever stored under it.
283
+ */
284
+ declare function buildHttpQueryPrefixKey(routeKey: string): HttpQueryPrefixKey;
285
+ /**
286
+ * Freshness window for `crpc.http.*` routes, in milliseconds.
287
+ *
288
+ * HTTP routes are a pull model with no push channel, so hydrated data needs a
289
+ * real freshness window or the browser refetches it on mount. The RSC
290
+ * QueryClient reads the same constant, so the server dedupe window and the
291
+ * client freshness window cannot drift apart.
292
+ */
293
+ declare const HTTP_DEFAULT_STALE_TIME = 30000;
249
294
  /** Infer schema type or return empty object if UnsetMarker */
250
295
  type InferSchemaOrEmpty<T> = T extends UnsetMarker ? object : T extends z.ZodTypeAny ? z.infer<T> : object;
251
296
  /**
@@ -290,4 +335,4 @@ declare class HttpClientError extends Error {
290
335
  /** Type guard for HttpClientError */
291
336
  declare const isHttpClientError: (error: unknown) => error is HttpClientError;
292
337
  //#endregion
293
- export { DataTransformer as A, HttpProcedure as C, ProcedureMeta as D, InferHttpInput$1 as E, decodeWire as F, defaultCRPCTransformer as I, encodeWire as L, WireCodec as M, createTaggedTransformer as N, CombinedDataTransformer as O, dateWireCodec as P, getTransformer as R, HttpMethod as S, HttpRouteDefinition as T, extractRouteMap as _, HttpProcedureCall as a, HttpActionHandler as b, InferHttpInput as c, CRPCHttpRouter as d, HttpRouterDef as f, createHttpRouterFactory as g, createHttpRouter as h, HttpErrorCode as i, DataTransformerOptions as j, DATE_CODEC_TAG as k, InferHttpOutput as l, HttpRouterWithHono as m, HttpClientError as n, HttpRouteInfo as o, HttpRouterRecord as p, HttpClientFromRouter as r, HttpRouteMap as s, HttpClient as t, isHttpClientError as u, CRPCHonoHandler as v, HttpProcedureBuilderDef as w, HttpHandlerOpts as x, HttpActionConstructor as y, identityTransformer as z };
338
+ export { HttpProcedureBuilderDef as A, dateWireCodec as B, extractRouteMap as C, HttpHandlerOpts as D, HttpActionHandler as E, DATE_CODEC_TAG as F, identityTransformer as G, defaultCRPCTransformer as H, DataTransformer as I, DataTransformerOptions as L, InferHttpInput$1 as M, ProcedureMeta as N, HttpMethod as O, CombinedDataTransformer as P, WireCodec as R, createHttpRouterFactory as S, HttpActionConstructor as T, encodeWire as U, decodeWire as V, getTransformer as W, CRPCHttpRouter as _, HttpErrorCode as a, HttpRouterWithHono as b, HttpQueryKey as c, HttpRouteMap as d, InferHttpInput as f, isHttpClientError as g, buildHttpQueryPrefixKey as h, HttpClientFromRouter as i, HttpRouteDefinition as j, HttpProcedure as k, HttpQueryPrefixKey as l, buildHttpQueryKey as m, HttpClient as n, HttpMutationKey as o, InferHttpOutput as p, HttpClientError as r, HttpProcedureCall as s, HTTP_DEFAULT_STALE_TIME as t, HttpRouteInfo as u, HttpRouterDef as v, CRPCHonoHandler as w, createHttpRouter as x, HttpRouterRecord as y, createTaggedTransformer as z };
@@ -1,4 +1,4 @@
1
- import { a as createMiddlewareFactory } from "./builder-Dwy6D2QA.js";
1
+ import { a as createMiddlewareFactory } from "./builder-CsxVc5xC.js";
2
2
 
3
3
  //#region src/plugins/middleware.ts
4
4
  const PLUGIN_CONFIG_RESOLVERS = Symbol.for("kitcn:PluginConfigResolvers");