Move Fast & Break Nothing. End-to-end typesafe APIs made easy.
as CustomErrorCodesas CustomErrorCodes in every instance I want to use it in? const { error: invalidCaptcha } = await tryCatch(
api.verification.isCaptchaValid({ guildId, uuid }),
);
console.log(invalidCaptcha?.cause?.code); // Property code does not exist on type {}. const { error: invalidCaptcha } = await tryCatch(
api.verification.isCaptchaValid({ guildId, uuid }),
);
console.log(invalidCaptcha?.cause?.code); // Property code does not exist on type {}. if (!verificationCache) {
throw new TRPCError({
code: "BAD_REQUEST",
message:
"This captcha has expired.",
cause: {
code: "CAPTCHA_EXPIRED",
},
});
} if (!verificationCache) {
throw new TRPCError({
code: "BAD_REQUEST",
message:
"This captcha has expired.",
cause: {
code: "CAPTCHA_EXPIRED",
},
});
}@hono/trpc-server@hono/trpc-server adapter.AppRouterAppRouter from the server:import type { AppRouter } from "../server/trpc"
const trpc = createTRPCReact<AppRouter>()import type { AppRouter } from "../server/trpc"
const trpc = createTRPCReact<AppRouter>()#report/repository/compose.ts#report/repository/compose.ts) that Node.js TypeScript can't resolve. When the frontend tries to infer types from AppRouterAppRouter, compilation fails.
queryClient.prefetchInfiniteQueryqueryClient.prefetchInfiniteQuery. I noticed there's no infiniteQueryOptionsinfiniteQueryOptions alternative to queryOptionsqueryOptions on trpc.{aRouter}.{procedure}trpc.{aRouter}.{procedure}, so I'm assuming I have to configure queryOptionsqueryOptions somehow to get it to take.useInfiniteQueryuseInfiniteQuery I get the following error: Type 'DefinedTRPCQueryOptionsOut<LedgerResponse, LedgerResponse, TRPCClientErrorLike<{ transformer: true; errorShape: DefaultErrorShape; }>, { keyPrefix: false; }>' is missing the following properties from type 'UseInfiniteQueryOptions<unknown, Error, InfiniteData<unknown, unknown>, readonly unknown[], unknown>': getNextPageParam, initialPageParam ts(2769) Type 'DefinedTRPCQueryOptionsOut<LedgerResponse, LedgerResponse, TRPCClientErrorLike<{ transformer: true; errorShape: DefaultErrorShape; }>, { keyPrefix: false; }>' is missing the following properties from type 'UseInfiniteQueryOptions<unknown, Error, InfiniteData<unknown, unknown>, readonly unknown[], unknown>': getNextPageParam, initialPageParam ts(2769)queryOptions({...}, {getNextPageParam, initialPageParam})queryOptions({...}, {getNextPageParam, initialPageParam}) I then get Object literal may only specify known properties, and 'getNextPageParam' does not exist in type 'UndefinedTRPCQueryOptionsInObject literal may only specify known properties, and 'getNextPageParam' does not exist in type 'UndefinedTRPCQueryOptionsIn"@trpc/client": "^11.7.2""@trpc/client": "^11.7.2" as a dependency to the mobile app, it crashes on start immediately. _unstableCoreDoNotImport.createRecursiveProxy is not a function (it is undefined)
_unstableCoreDoNotImport.createRecursiveProxy is not a function (it is undefined), js engine: hermes
Error: Couldn't find a 'component', 'getComponent' or 'children' prop for the screen 'App'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing._unstableCoreDoNotImport.createRecursiveProxy is not a function (it is undefined)
_unstableCoreDoNotImport.createRecursiveProxy is not a function (it is undefined), js engine: hermes
Error: Couldn't find a 'component', 'getComponent' or 'children' prop for the screen 'App'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing.await queryClient.invalidateQueries({ queryKey: scheduleKey });
// I compute the query key in a reusable hook
function useScheduleQueryKey() {
const api = useTRPC();
const [weekStart] = useScheduleParams();
return api.schedule.getWeek.queryKey({ weekStart });
}await queryClient.invalidateQueries({ queryKey: scheduleKey });
// I compute the query key in a reusable hook
function useScheduleQueryKey() {
const api = useTRPC();
const [weekStart] = useScheduleParams();
return api.schedule.getWeek.queryKey({ weekStart });
}getWeek.queryKey()getWeek.queryKey() or by passing the key as the only arg;queryClient.invalidateQueries(queryKey) // Have a feeling this only works becuase it seems to just invalidate any active query so this is likely a red herringqueryClient.invalidateQueries(queryKey) // Have a feeling this only works becuase it seems to just invalidate any active query so this is likely a red herringsetQueryDatasetQueryData on it fine; queryClient.setQueryData(scheduleKey, onMutateResult.currentData); queryClient.setQueryData(scheduleKey, onMutateResult.currentData);
the /_next/data/.../abc.jsonthe /_next/data/.../abc.json returned application/json type response placeholderDataplaceholderData option, or my Component's own custom skeletons=<number>skeletons=<number> prop, the fact is that I get either of those rendered only on the very first fetch (on page load). .status === 'pending'.status === 'pending' and so no skeletons/placeholders show on the "Load more..." scenario.@hono/trpc-server@hono/trpc-server package which gives me middleware for trpc to run with hono. They even have an example with cloudflare workers and a d1 database, so I know it is possible to do what I am trying to do.create: publicProcedure
.input(z.object({ title: z.string() }))
.mutation(async ({ ctx, input }) => {
console.error(input);
const quest = await ctx.db
.insertInto("quest")
.values(input)
.returningAll()
.executeTakeFirst();
return quest;
}),create: publicProcedure
.input(z.object({ title: z.string() }))
.mutation(async ({ ctx, input }) => {
console.error(input);
const quest = await ctx.db
.insertInto("quest")
.values(input)
.returningAll()
.executeTakeFirst();
return quest;
}),const app = new Hono<{ Bindings: Bindings }>();
app.use(
"/trpc/*",
trpcServer({
router: appRouter,
createContext: (_, c) => createContext(c),
}),
);
app.use(
"/*",
cors({
origin: "http://localhost:5173",
credentials: true,
}),
);
export default app;const app = new Hono<{ Bindings: Bindings }>();
app.use(
"/trpc/*",
trpcServer({
router: appRouter,
createContext: (_, c) => createContext(c),
}),
);
app.use(
"/*",
cors({
origin: "http://localhost:5173",
credentials: true,
}),
);
export default app;context.tscontext.tsimport { createDb } from "./db";
import type { Bindings } from "./types";
import type { Context as HonoContext } from "hono";
export const createContext = (c: HonoContext<{ Bindings: Bindings }>) => ({
db: createDb(c.env.questboard),
});
export type Context = Awaited<ReturnType<typeof createContext>>;import { createDb } from "./db";
import type { Bindings } from "./types";
import type { Context as HonoContext } from "hono";
export const createContext = (c: HonoContext<{ Bindings: Bindings }>) => ({
db: createDb(c.env.questboard),
});
export type Context = Awaited<ReturnType<typeof createContext>>;export function useChatInstanceQuery(chatId?: string) {
const trpc = useTRPC();
const getToken = useGetToken();
const queryClient = useQueryClient();
const query = useQuery({
queryKey: ["chats", chatId],
staleTime: Infinity,
queryFn: chatId
? async () => {
const messages = await queryClient.fetchQuery(
trpc.getChatHistory.queryOptions({ chatId }),
);
const chat = createChat({ chatId, getToken, messages });
return chat;
}
: skipToken,
});
return query;
}export function useChatInstanceQuery(chatId?: string) {
const trpc = useTRPC();
const getToken = useGetToken();
const queryClient = useQueryClient();
const query = useQuery({
queryKey: ["chats", chatId],
staleTime: Infinity,
queryFn: chatId
? async () => {
const messages = await queryClient.fetchQuery(
trpc.getChatHistory.queryOptions({ chatId }),
);
const chat = createChat({ chatId, getToken, messages });
return chat;
}
: skipToken,
});
return query;
}`instanceof Chat`instanceof ChatRootLayoutRootLayout when trying to fetch data via tRPC.app/layout.tsxapp/layout.tsx)import { TRPCReactProvider } from "@/trpc/react";
import { api } from "@/trpc/server";
export default async function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
// This line seems to be the source of the uncached access
const categories = await api.product.category.public_getAll();
return (
<html lang="en" className={`${geist.variable}`}>
<body>
<TRPCReactProvider>
{/* ... layout content using categories ... */}
{children}
</TRPCReactProvider>
</body>
</html>
);
}import { TRPCReactProvider } from "@/trpc/react";
import { api } from "@/trpc/server";
export default async function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
// This line seems to be the source of the uncached access
const categories = await api.product.category.public_getAll();
return (
<html lang="en" className={`${geist.variable}`}>
<body>
<TRPCReactProvider>
{/* ... layout content using categories ... */}
{children}
</TRPCReactProvider>
</body>
</html>
);
}Error: Route "/": Uncached data was accessed outside of <Suspense>. This delays the entire page from rendering, resulting in a slow user experience.
Learn more: https://nextjs.org/docs/messages/blocking-route
headers()headers() call within my createContextcreateContext function in src/trpc/server.tssrc/trpc/server.ts:15 | const createContext = cache(async () => {
> 16 | const heads = new Headers(await headers()); // <- Error points here
| ^
17 | heads.set("x-trpc-source", "rsc");15 | const createContext = cache(async () => {
> 16 | const heads = new Headers(await headers()); // <- Error points here
| ^
17 | heads.set("x-trpc-source", "rsc");