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.
- package/dist/aggregate/index.d.ts +1 -1
- package/dist/auth/nextjs/index.d.ts +1 -1
- package/dist/auth/nextjs/index.js +1 -1
- package/dist/{builder-Dwy6D2QA.js → builder-CsxVc5xC.js} +110 -57
- package/dist/{caller-factory-DHywSoGZ.js → caller-factory-CWa0ELLD.js} +1 -1
- package/dist/cli.mjs +96 -20
- package/dist/crpc/index.d.ts +3 -3
- package/dist/crpc/index.js +3 -3
- package/dist/{http-types-zsMHb_QN.d.ts → http-types-DXOgaerG.d.ts} +46 -1
- package/dist/{middleware-qzHEHaDy.js → middleware-DUd1Sj39.js} +1 -1
- package/dist/orm/index.d.ts +1 -1
- package/dist/plugins/index.js +1 -1
- package/dist/{procedure-caller-JB9kjYsy.js → procedure-caller-DQxnLBS_.js} +2 -2
- package/dist/{procedure-name-exVcmr_p.d.ts → procedure-name-C20pFZnk.d.ts} +21 -7
- package/dist/{query-options-C_eBSIXG.js → query-options-CzRV4G4N.js} +33 -1
- package/dist/ratelimit/index.d.ts +45 -9
- package/dist/ratelimit/index.js +255 -101
- package/dist/react/index.d.ts +9 -6
- package/dist/react/index.js +81 -18
- package/dist/rsc/index.d.ts +4 -7
- package/dist/rsc/index.js +5 -9
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +3 -3
- package/dist/solid/index.d.ts +9 -6
- package/dist/solid/index.js +81 -18
- package/dist/{transformer-C6pGVHqx.js → transformer-yZuBWo8v.js} +45 -1
- package/dist/{types-jNTcza_a.d.ts → types-BHR7ZKKD.d.ts} +1 -1
- package/dist/{where-clause-compiler-B_H3oio5.d.ts → where-clause-compiler-DW6jy2er.d.ts} +59 -59
- package/package.json +1 -1
- package/skills/kitcn/references/features/http.md +26 -1
- package/skills/kitcn/references/features/ratelimit.md +11 -0
- package/skills/kitcn/references/features/react.md +1 -1
- 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-
|
|
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-
|
|
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-
|
|
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-
|
|
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,
|
|
521
|
-
const rawArgs =
|
|
522
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
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,
|
|
1013
|
+
function parseQueryParams(url, coercion) {
|
|
984
1014
|
const params = {};
|
|
985
|
-
const
|
|
986
|
-
const
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
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
|
-
|
|
996
|
-
|
|
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,
|
|
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(
|
|
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 = (
|
|
1828
|
+
const parseInput = (plan, value) => {
|
|
1772
1829
|
try {
|
|
1773
|
-
if (
|
|
1774
|
-
const
|
|
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 =
|
|
1781
|
-
const
|
|
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
|
|
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
|
|
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 ? {
|
|
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(
|
|
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 =
|
|
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-
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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 {
|
|
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 = [
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
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:
|
|
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.",
|
package/dist/crpc/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
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-
|
|
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 };
|
package/dist/crpc/index.js
CHANGED
|
@@ -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-
|
|
3
|
-
import { a as buildSearchParams, c as
|
|
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 {
|
|
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 };
|