API

Adding new endpoint

How to add new endpoint to the API.

To define a new API endpoint, you can either extend an existing entity (e.g. add new customer note) or create a new, separate module.

Create new module

To create a new module you can create a new folder in the modules folder. For example modules/posts.

Then you would need to create a router declaration for this module. We're following a convention with the filename suffixes, so you would need to create a file named posts.router.ts in the modules/posts folder.

modules/posts/posts.router.ts
import { createTRPCRouter } from "../../trpc";
import { getAllPosts } from "./posts.controller";
 
export const postsRouter = createTRPCRouter({
  getAll: publicProcedure
    .input(filtersSchema)
    .query(({ input }) => getAllPosts(input)),
});

We're using publicProcedure here, but you can also use protectedProcedure to restrict access to the endpoint.

Read more about protected routes.

Maybe mutation?

The same way you can define a mutation for the new entity, just by changing the query to mutation:

modules/posts/posts.router.ts
export const postsRouter = createTRPCRouter({
  create: protectedProcedure
    .input(postSchema)
    .mutation(({ input }) => createPost(input)),
});

That way you also validate if the input is correct and the user is authorized to perform this action.

Implement logic

Then you would need to create a controller for this module. There is a place, where the logic happens, e.g. for the getAll endpoint we would need to create a getAllPosts function which will fetch posts from the database.

modules/posts/posts.controller.ts
import { db } from "@turbostarter/db/client";
import { posts } from "@turbostarter/db/schema";
 
export const getAllPosts = (filters: Filters) => {
  return db.select().from(posts).all().where(/* your filter logic here */);
};

Register router

To make the module and its endpoints available in the API you need to register a router for this module in the router.ts file:

router.ts
import { postsRouter } from "./modules/posts/posts.router";
import { createTRPCRouter } from "./trpc";
 
export const appRouter = createTRPCRouter({
  posts: postsRouter,
  /* other routers from your app logic */
});
 
export type AppRouter = typeof appRouter;

It's fully type-safe!

By exporting the AppRouter type you get fully type-safe RPC calls in the client. It's important because without producing a huge amount of code, we're fully type-safe from the frontend code. It helps avoid passing incorrect data to the procedure and streamline consuming returned types without a need to define these types by hand.

Last updated on

On this page

Ship your startup everywhere. In minutes.Get TurboStarter