Advanced tRPC Techniques
1. Introduction
tRPC (Type-safe Remote Procedure Call) is a powerful tool for building type-safe APIs. This lesson delves into advanced techniques to enhance your tRPC implementations, focusing on best practices, performance, and error handling.
2. Advanced Concepts
2.1 Middleware in tRPC
Middleware allows you to intercept requests before they reach your procedure. This can be useful for logging, authentication, and validation.
import { initTRPC } from '@trpc/server';
const t = initTRPC.create();
const loggerMiddleware = t.middleware(async ({ ctx, next }) => {
console.log('Request:', ctx);
const result = await next();
console.log('Response:', result);
return result;
});
const appRouter = t.router({
getUser: t.procedure.use(loggerMiddleware).query((opts) => {
return getUserFromDatabase(opts.input);
}),
});
2.2 Batch Requests
Batching allows you to combine multiple requests into a single call, reducing the number of round trips.
const batchRouter = t.router({
getUsers: t.procedure.input(z.array(z.string())).query(async (opts) => {
return Promise.all(opts.input.map(id => getUserFromDatabase(id)));
}),
});
3. Performance Optimizations
3.1 Caching
Implement caching strategies to reduce load times and database hits.
const cache = new Map();
const cachedGetUser = t.procedure.query(async (opts) => {
if (cache.has(opts.input)) {
return cache.get(opts.input);
}
const user = await getUserFromDatabase(opts.input);
cache.set(opts.input, user);
return user;
});
3.2 Optimizing Data Fetching
Use pagination and filtering to minimize the amount of data transferred.
const paginatedUsers = t.procedure
.input(z.object({ page: z.number(), limit: z.number() }))
.query(async (opts) => {
const { page, limit } = opts.input;
return await getUsersFromDatabase(page, limit);
});
4. Error Handling
Proper error handling enhances user experience and debugging.
const userRouter = t.router({
getUser: t.procedure
.input(z.string())
.query(async (opts) => {
try {
return await getUserFromDatabase(opts.input);
} catch (error) {
throw new Error('User not found');
}
}),
});
5. Testing Strategies
Testing your tRPC procedures ensures reliability and correctness.
import { createTRPCRouter } from '@trpc/server/testing';
const router = createTRPCRouter(appRouter);
test('getUser returns user data', async () => {
const result = await router.getUser.query('user-id-123');
expect(result).toEqual(expectedUserData);
});
6. FAQ
What is tRPC?
tRPC allows you to create fully type-safe APIs without needing to write RESTful endpoints or GraphQL schemas.
How does middleware work in tRPC?
Middleware functions can be defined to intercept requests and responses, allowing for additional logic like authentication or logging.