In case anybody is interested in using this with the createTRPCProxyClient object on SvelteKit to expose an /api/trpc/ route... This is how I've done it
// $lib/trpc.ts
import type { AppRouter } from '$lib/server/trpc/routes';
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import SuperJSON from 'superjson';
import { svelteQueryWrapper } from 'trpc-svelte-query-adapter';
import type { QueryClient } from '@tanstack/svelte-query';
const client = createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:5173/api/trpc'
})
],
transformer: SuperJSON
});
export const trpc = (queryClient?: QueryClient) =>
svelteQueryWrapper<AppRouter>({
client,
queryClient
});
// $lib/server/trpc/index.ts
import { initTRPC } from '@trpc/server';
import type { Context } from '$lib/server/trpc/context';
import superjson from 'superjson';
import { ZodError } from 'zod';
const t = initTRPC.context<Context>().create({
transformer: superjson
});
export const { procedure, router, middleware, createCallerFactory } = t;
// $lib/server/trpc/context.ts
import type { RequestEvent } from '@sveltejs/kit';
import type { inferAsyncReturnType } from '@trpc/server';
export const createContext = async (event: RequestEvent) => ({ event });
export type Context = inferAsyncReturnType<typeof createContext>;
// $lib/server/trpc/caller.ts
import { createCallerFactory } from '$lib/server/trpc';
import { appRouter } from '$lib/server/trpc/routes';
export const createCaller = createCallerFactory(appRouter);
// $lib/server/trpc/routes/index.ts
import { clients } from './clients';
import { files } from './files';
import { projects } from './projects';
import { users } from './users';
import { router } from '$lib/server/trpc';
export const appRouter = router({
users
});
export type AppRouter = typeof appRouter;
// $lib/server/trpc/routes/users.ts
import { isLogged } from '$lib/server/trpc/middlewares/auth';
import { router, procedure } from '$lib/server/trpc';
import { db } from '$lib/server/database/index';
import { client } from '$lib/server/database/schema';
import { eq } from 'drizzle-orm';
import { clientSchema } from '$lib/zod';
export const users = router({
list: procedure
// use query for GET
.query(async () => db.select().from(client)),
delete: procedure
.use(isLogged)
.input(userSchema.pick({ id: true }))
// use mutation for POST
.mutation(async ({ input: { id } }) => {
db.delete(user).where(eq(user.id, id));
})
});
// routes/api/trpc/[...path]/+server.ts
import { createContext } from '$lib/server/trpc/context';
import { appRouter } from '$lib/server/trpc/routes';
import type { RequestHandler } from '@sveltejs/kit';
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
const requestHandler: RequestHandler = (event) =>
fetchRequestHandler({
req: event.request,
router: appRouter,
endpoint: '/api/trpc',
createContext: () => createContext(event)
});
export const GET = requestHandler;
export const POST = requestHandler;
// routes/+layout.svelte
<script lang="ts">
import { QueryClientProvider } from '@tanstack/svelte-query';
import type { PageData } from './$types';
export let data: PageData;
</script>
<QueryClientProvider client={data.queryClient}>
<main>
<slot />
</main>
</QueryClientProvider>
I am using Lucia so that's why I have the ctx.event.locals.user and session in the auth middleware to stop non-logged in users acceessing certain routes.
In case anybody is interested in using this with the
createTRPCProxyClient
object on SvelteKit to expose an/api/trpc/
route... This is how I've done itI am using Lucia so that's why I have the
ctx.event.locals.user
andsession
in the auth middleware to stop non-logged in users acceessing certain routes.Bonus in case you're interested to see what's in the Zod user schema.