kitcn
Version:
kitcn - React Query integration and CLI tools for Convex
169 lines (164 loc) • 6.32 kB
JavaScript
import { a as isCRPCErrorCode, i as isCRPCError, n as defaultIsUnauthorized, r as isCRPCClientError, t as CRPCClientError } from "../error-Bvo7YEhk.js";
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";
import { n as convexInfiniteQueryOptions, r as convexQuery, t as convexAction } from "../query-options-C96zLANM.js";
//#region src/crpc/auth-error.ts
/**
* Auth Mutation Error
*
* Framework-agnostic error class for Better Auth mutations.
*/
/**
* Error thrown when a Better Auth mutation fails.
* Contains the original error details from Better Auth.
*/
var AuthMutationError = class extends Error {
/** Error code from Better Auth (e.g., 'INVALID_PASSWORD', 'EMAIL_ALREADY_REGISTERED') */
code;
/** HTTP status code */
status;
/** HTTP status text */
statusText;
constructor(authError) {
super(authError.message || authError.statusText);
this.name = "AuthMutationError";
this.code = authError.code;
this.status = authError.status;
this.statusText = authError.statusText;
}
};
/**
* Type guard to check if an error is an AuthMutationError.
*/
function isAuthMutationError(error) {
return error instanceof AuthMutationError;
}
//#endregion
//#region src/crpc/http-types.ts
/** HTTP client error */
var HttpClientError = class extends Error {
name = "HttpClientError";
code;
status;
procedureName;
constructor(opts) {
super(opts.message ?? `${opts.code}: ${opts.procedureName}`);
this.code = opts.code;
this.status = opts.status;
this.procedureName = opts.procedureName;
}
};
/** Type guard for HttpClientError */
const isHttpClientError = (error) => error instanceof HttpClientError;
//#endregion
//#region src/crpc/http-client.ts
/**
* HTTP Client Helpers
*
* Framework-agnostic utilities for executing HTTP requests
* against Convex HTTP endpoints.
*/
/** Reserved keys that are not part of JSON body */
const RESERVED_KEYS = new Set([
"params",
"searchParams",
"form",
"fetch",
"init",
"headers"
]);
/**
* Replace URL path parameters with actual values.
* e.g., '/users/:id' with { id: '123' } -> '/users/123'
*/
function replaceUrlParam(url, params) {
return url.replace(/:(\w+)/g, (_, key) => {
const value = params[key];
return value !== void 0 ? encodeURIComponent(value) : `:${key}`;
});
}
/**
* Build URLSearchParams from query object.
* Handles array values as multiple params with same key (like Hono).
*/
function buildSearchParams(query) {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(query)) if (Array.isArray(value)) for (const v of value) params.append(key, v);
else if (value !== void 0 && value !== null) params.append(key, value);
return params;
}
/**
* Hono-style HTTP request executor.
* Processes args in the same way as Hono's ClientRequestImpl.fetch().
*/
async function executeHttpRequest(opts) {
const { method, path } = opts.route;
const args = opts.args ?? {};
let rBody;
let cType;
if (args.form) {
const form = new FormData();
for (const [k, v] of Object.entries(args.form)) if (Array.isArray(v)) for (const v2 of v) form.append(k, v2);
else form.append(k, v);
rBody = form;
} else {
const jsonBody = {};
for (const [key, value] of Object.entries(args)) if (!RESERVED_KEYS.has(key) && value !== void 0) jsonBody[key] = value;
if (Object.keys(jsonBody).length > 0) {
rBody = JSON.stringify(opts.transformer.input.serialize(jsonBody));
cType = "application/json";
}
}
const argsClientOpts = {};
if (args.fetch) argsClientOpts.fetch = args.fetch;
if (args.init) argsClientOpts.init = args.init;
if (args.headers) argsClientOpts.headers = args.headers;
const mergedClientOpts = {
...opts.clientOpts,
...argsClientOpts
};
const resolvedBaseHeaders = typeof opts.baseHeaders === "function" ? await opts.baseHeaders() : opts.baseHeaders;
const headerValues = { ...typeof mergedClientOpts.headers === "function" ? await mergedClientOpts.headers() : mergedClientOpts.headers };
if (cType) headerValues["Content-Type"] = cType;
const finalHeaders = {};
if (resolvedBaseHeaders) {
for (const [key, value] of Object.entries(resolvedBaseHeaders)) if (value !== void 0) finalHeaders[key] = value;
}
Object.assign(finalHeaders, headerValues);
let url = opts.convexSiteUrl + path;
if (args.params) url = opts.convexSiteUrl + replaceUrlParam(path, args.params);
if (args.searchParams) {
const queryString = buildSearchParams(args.searchParams).toString();
if (queryString) url = `${url}?${queryString}`;
}
const methodUpperCase = method.toUpperCase();
const setBody = !(methodUpperCase === "GET" || methodUpperCase === "HEAD");
const response = await (mergedClientOpts.fetch ?? opts.baseFetch ?? globalThis.fetch)(url, {
body: setBody ? rBody : void 0,
method: methodUpperCase,
headers: finalHeaders,
...mergedClientOpts.init
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ error: {
code: "UNKNOWN",
message: response.statusText
} }));
const errorCode = errorData?.error?.code || "UNKNOWN";
const errorMessage = errorData?.error?.message || response.statusText;
throw new HttpClientError({
code: errorCode,
status: response.status,
procedureName: opts.procedureName,
message: errorMessage
});
}
if (response.headers.get("content-length") === "0" || response.status === 204) return;
if ((response.headers.get("content-type") || "").includes("application/json")) return opts.transformer.output.deserialize(await response.json());
return response.text();
}
//#endregion
//#region src/crpc/types.ts
/** Symbol key for attaching FunctionReference to options (non-serializable) */
const FUNC_REF_SYMBOL = Symbol.for("convex.funcRef");
//#endregion
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 };