nest icon indicating copy to clipboard operation
nest copied to clipboard

[Feature] NestJS Route Exporter

Open unckleg opened this issue 5 years ago • 13 comments

Feature Request

NestJS Route exporter

Is your feature request related to a problem? Please describe.

While developing SPA's or any other REST dependent app there is common challenge for developers how to share routes from server/service to applications.

Describe the solution you'd like

I've created workable version of route exporter for NestJS by traversing all controllers/routes and exporting them to dev specified directory file. Exported file can be typescript or javascript it depending on what developer wants. If it's typescript file then it's fully typehinted. If it's javascript it's just pure javascript file.

After exporting routes file, developers can push them to some repository and use them as API interface for their applications.

I'd like to create same route-exporter module for NestJS and solve this common challenge.

So here are few examples how it should work:


import { routeExporter } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);

  /**
   * app       | Used for traversing app controllers
   * baseUri   | Used as baseUri - Optional we can set baseUri from app by default
   * directory | Used as directory where routes will be exported - Optional we can define default dir to be exported
   * file      | Filename and file-type (ts,js) that will be exported in <root>/directory/fileName.{ts/js} - Optional we can define default filename to be exported
   */
  routeExporter(app);

  // Or 
  routeExporter(app, 'http://localhost:3001', 'common', 'api.ts');

  // Or
  routeExporter(app, {
    baseUri: 'http://localhost:3001',
    output: 'common/api.ts'
  });

  // Use _includes_ to specify from which controllers to export routes
  routeExporter(app, {
    baseUri: 'http://localhost:3001',
    output: 'common/api.ts',
    includes: [
      HelloController,
    ],
  });
  
  // Use normalize to normalize exported const name.
  routeExporter(app, {
    baseUri: 'http://localhost:3001',
    output: 'common/api.ts',
    normalize: (controllerName: string): string => {
      return controllerName.replace('Controller', 'Endpoints')
    },
  });
 

  await app.listen(3000);
}

bootstrap();

So if we have let's say HeaderController the output for api.ts file would be:

Typescript

If we wanna export api.js and have HeaderController in our app the output for api.js file would be:

Javascript

@kamilmysliwiec What do you think ? I'd like to create PR for this one.

Thanks!

unckleg avatar Jul 24 '20 06:07 unckleg

This seems interesting. What's the main difference between this and something like OpenAPI with choice generators to create calls from swagger files?

jmcdo29 avatar Jul 24 '20 07:07 jmcdo29

Hi @jmcdo29

There are multiple OpenAPI files generator libraries, the main difference here is that in essence OpenAPI generates specifications for developers that helps them understand and interact with existing API's on OpenAPI platform that are specified in swagger files, on the other side there are multiple pros using route-exporter. Here are some of them:

  • Developers define routeExporter on one place that exports them. (Exporting params can be dynamic if service is pipelined with some deploy system, or using .env files/process.env or anything else...)
  • REST endpoint signatures are changed and expanded while developing REST app (this is most important) They will not waste time on changing their request PATHS or request METHODS on apps if they are changed on NestJS side while developing.
  • Exported routes can be used as git repository, or manipulate with exported output through some build pipeline that will deliver routes to their apps.
  • The more they define dev friendly controller endpoint methods, the more they will have dev friendly interface on their apps.
  • IDE's will be happy with output file/files.
  • Developers will be happy with autocomplete and simplicity of usage.
  • They will consume them in their applications (there is nice interface proposal) with all required request props (PATH, METHOD). Property name that contains PATH & METHOD can be interpreted as ALIAS. For example the usage with fetch api would be:.
import { Api: { HEADER: { create } } } from 'src/api'; // This can be git repo or delivered through build pipeline. 

fetch(create.path, { method: create.method }).then(json);

This can be extended more:

  • Support method alias normalizing on runtime.
  • Support controller alias normalizing on runtime.
  • Support controller including.
  • Support controller excluding.
  • Use decorators in controllers instead of API proposed above.
  • Use some interface in modules instead of API proposed above.

What should be done if this is considered as "Nice to have".

  • Agree what would be best interface on NestJS side.
  • Exclude route exported directory/directories from compiler pass since they are generated and watched.

unckleg avatar Jul 24 '20 07:07 unckleg

Are there any leads from this? Are we going to implement this at some-point in the future, is it stale :confused:

YashKumarVerma avatar Dec 10 '20 17:12 YashKumarVerma

Thanks for bringing this back up. I think this looks really cool, and I could see it being pretty useful. My concern is adding it to the main codebase as it may not be for everyone, but I could see it being a nice library to publish so it's an opt in kind of thing, just like swagger already is.

Does this require any of Nest's internals, or is it mainly getting the http engine (does this work for Fastify and Express?) and look at the router that's created?

jmcdo29 avatar Dec 10 '20 18:12 jmcdo29

@YashKumarVerma

Thanks from my side for bringing it up also.

I'm going to create a PR for this one with implementation and API and then we can discuss more? :)

unckleg avatar Dec 10 '20 21:12 unckleg

Like I said, rather than adding this to @nestjs/common or @nestjs/core, I could see this itself being a library on its own. Maybe it's not as easy due to missing how it's implemented, but I'm not sure why we'd want to bring this into these packages

jmcdo29 avatar Dec 10 '20 21:12 jmcdo29

This library attempts to implement something like this: https://github.com/samchon/nestia

TimonLukas avatar Mar 02 '21 10:03 TimonLukas

If I understood the core issue correctly, it looks like a tool like https://openapi-generator.tech/ could fit the bill.

Nest.js is already capable of generating openAPI document and then a javascript/typescript client (based on axios, fetch, redux-toolkit-query…) can be derived from it using the program linked above.

Delapouite avatar Jul 30 '21 12:07 Delapouite

REST endpoint signatures are changed and expanded while developing REST app (this is most important) They will not waste time on changing their request PATHS or request METHODS on apps if they are changed on NestJS side while developing. Exported routes can be used as git repository, or manipulate with exported output through some build pipeline that will deliver routes to their apps. IDE's will be happy with output file/files. They will consume them in their applications (there is nice interface proposal) with all required request props (PATH, METHOD). Property name that contains PATH & METHOD can be interpreted as ALIAS

Al of these features can be implemented using OpenAPI client generators.

Ginden avatar Oct 14 '21 15:10 Ginden

I saw that issue before nestjs/nest-cli#15

Sikora00 avatar Nov 25 '21 10:11 Sikora00

Not an issue, its enhancement :)

unckleg avatar Nov 25 '21 11:11 unckleg

@unckleg ofc, I meant a github issue

Sikora00 avatar Nov 25 '21 12:11 Sikora00

If I understand correctly, and as others have already said - this requirement can be fully satisfied using openadpi-generator. It generates methods based on the operationId in swagger, which can be customized on Nest's side. We've used it in our app to generate a typed axios client, with some tweaks to the default template to make it more user friendly. Hit me up if you'd like some help, it's not the most intuitive software.

Papooch avatar Sep 09 '22 13:09 Papooch

@kamilmysliwiec #10529 was more to do with making the functionality available internally rather than generating files. Or are you keeping these similar topics together?

milosdakic avatar Nov 07 '22 23:11 milosdakic

Closing as there have been no PRs related to this feature over the past 3 years. For folks looking for a comprehensive route explorer, check out NestJS Devtools app https://www.devtools.nestjs.com/

kamilmysliwiec avatar May 19 '23 10:05 kamilmysliwiec