#Get routes URLs list as Union Type for the client

20 messages · Page 1 of 1 (latest)

drowsy trench
#

I've been playing with tRPC, and the server side of Vue's metaframework Nuxt v3, for the backend of my apps. And they are cool, but I always get back to Nest because of the TS decorators and the nice practices. So the only thing that amazed me from tRPC and Nuxt backend was the ability to have completion of the route URLs in the client.

So 2 questions:
1. Is there a way to get a list of all the URLs of all the modules injected in the main app, so I can convert to a type and export it?
**2. ** Is there a solution for this that I'm not aware of?

Thank you. 🔥🤝

tulip steppe
#

Swagger or nestia are probably what you're looking for

drowsy trench
#

Thanks for the info and for your time, and sorry for the late response. Will check those.

drowsy trench
#

@tulip steppe I hope not bothering you with the tagging. I wanted you to know that I achieved what I needed.

function getRoutes(router: any): string[] {
  const routes: string[] = []

  for (const controller of router._router.stack) {
    if (controller.route && controller.route.path) {
      const path = controller.route.path
      routes.push(path)
    }
  }

  return routes
}

function generateRouterType(router) {
  const routes = getRoutes(router)
  writeFileSync(
    'server-router.ts',
    `export const routes = ${JSON.stringify(routes, null, 2)} as const

export type ServerRouter = typeof routes[number]
   `,
  )
}

async function generateBootstrap() {
  let _app
  await bootstrap((app: INestApplication) => {
    _app = app
    return false
  })
  await _app.listen(5003)
  const router = _app.getHttpAdapter().getInstance()
  generateRouterType(router)
  exit(0)
}

generateBootstrap()

I defined a generate:types script in package.json which then executes the above script.

Of course, it doesn't feel "magical" like in Nuxt and tRPC, because it's not automatic, it doesn't work at authoring time, only at runtime, I have to execute a script, it creates the Nest app, listens to it so the routes are generated. But it does the job.

Now in the frontend, I create a function to make the API requests, which accepts an url as first parameter with the ServerRouter type
getting completion of all the endpoints.

drowsy trench
#

But I think I'm going to try Nestia! 🤝🔥🤯

quaint spear
drowsy trench
quaint spear
drowsy trench
#

You need a nestia.config.ts with the code:

import { INestiaConfig } from "@nestia/sdk";
 
const config: INestiaConfig = {
    input: "src/controllers",
    output: "src/api",
    distribute: "packages/api",
};
export default config;

and create the controllers and api directories inside the src directory, and the packages directory in the root, with an api directory inside.

#

Then, run: npx nestia start . if you are at the app's root in the terminal or npx nestia start <directory> if you are at a different path in the terminal.

Then install nestia:

npm install -D nestia

And then:

npx nestia setup.

That will iterate all your modules, controllers, and generate the client sdk in src/api.

#

Then in your client's app directory, to make a request to the Nest API:

import api from '../src/api' // Import the client sdk from the Nest app directory

const email = ref('')
const password = ref('')

// Create a connection
const connection: api.IConnection = {
  host: 'http://localhost:5000/api'
}
async function login() {
  // Call the api.functional proceeded by the name of your controllers and their routes, passing the connection as first argument
// and the payload (data, body) as second argument
  const data = await api.functional.auth.login(connection, {
    email: email.value, 
    password: password.value
  })
  alert(data.email)
}
quaint spear
quaint spear
drowsy trench
quaint spear
drowsy trench
#

Thanks! Going to check ts-rest. Looks like tRPC and i loved tRPC.

quaint spear
drowsy trench
#

Judging by the little time I played with it, I would say it similar to tRPC in that it is type safe for the client, but the way to get there is different.
In tRPC we create a server router and export its type to use in the client and we also have the trpc client. But we use the /trpc endpoint for everything. Every request that is intended to mutate something, is sent as a POST request (mutation), and every request that is for retrieval/get, is sent as a GET request (query).

In Nestia, we keep using the Nest server and routers, but nestia parses all modules/controllers/routes info, and creates a client (sdk) with the parameters and return types and we keep using the traditional HTTP methods.

In my case, I want to keep using TypeScript decorators and opinionated standards set by Nest team, so tRPC doesn't work for me.
That's why I was trying to get the list of all routes so I could build a union type for my client, and I finally achieved it thanks to ChatGPT.
But Nestia also achieves the same thing. So I will keep giving Nestia a try.

The premise of typia, what Nestia uses for data validation and transformation, and Nestia as a whole is SPEED. I prioritize User Experience (UX) over speed.
The use of JSDoc to define the fields validators is against UX, it's redundant (TypeScript already have types, why make a new language on top of another language!?) and it's against aesthetics (using comments to implement logic).