Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for nestjs compiler plugins (e.g. for swagger) #2147

Closed
maku opened this issue Dec 5, 2019 · 73 comments · Fixed by #6677
Closed

support for nestjs compiler plugins (e.g. for swagger) #2147

maku opened this issue Dec 5, 2019 · 73 comments · Fixed by #6677
Assignees
Labels
community This is a good first issue for contributing outdated scope: node Issues related to Node, Express, NestJS support for Nx type: feature

Comments

@maku
Copy link

maku commented Dec 5, 2019

I would like to use a nestjs compiler plugin (e.g. described in https://trilon.io/blog/nestjs-swagger-4-whats-new for generation of swagger definition)

How can I do this with nx?

@creadicted
Copy link

That has nothing todo with nx.
Use it like it is described in the documentation of nestjs and you are fine.

@maku
Copy link
Author

maku commented Dec 5, 2019

@creadicted Sorry I don't get you. nestjs is "managed" by nx. The build process is executed via "ng...". So we are not using the "Nest CLI" and the nestjs docu says that the way to go is to have a custom webpack configuration in combination with ts-loader...

@creadicted
Copy link

creadicted commented Dec 5, 2019

@maku Ok I am sorry you were right.
I researched a bit and run in a rabbit hole.

I used a custom webpack.config.js for the project
angular.json

 "projects": {
    "api": {
      "architect": {
        "build": {
          "builder": "@nrwl/node:build",
          "options": {
            "webpackConfig": "apps/api/webpack.config.js"
          },

checked what will be injected in there and extended it with the getCustomTransformers
webpack.config.js

module.exports = function(webpackConfig, context) {
  webpackConfig.module = {
    rules: [
      {
        test: /\.(j|t)sx?$/,
        loader: 'ts-loader',
        options: {
          configFile: context.options.tsConfig,
          transpileOnly: true,
          experimentalWatchApi: true,
          getCustomTransformers: (program) => ({
            before: [require('@nestjs/swagger/plugin').before({}, program)]
          }),
        }
      }
    ]
  };
  return webpackConfig;
};

But I will now get errors:

Module build failed (from ./node_modules/ts-loader/index.js):
TypeError: Cannot read property 'getTypeChecker' of undefined
    at ControllerClassVisitor.visit (\node_modules\@nestjs\swagger\dist\plugin\visitors\controller-class.visitor.js:12:37)

I am not sure if this is because of something else that is conflicted or some decorators that I missed.

If I have a bit more time I can test it with a blank project. I super unfamiliar with ts-loader and webpack but I thought I give it a try.

@FrozenPandaz FrozenPandaz added community This is a good first issue for contributing scope: node Issues related to Node, Express, NestJS support for Nx type: feature labels Dec 5, 2019
@FrozenPandaz
Copy link
Collaborator

This is an interesting way of generating API configuration.

I'm not too familiar with doing this either but you may want to make sure you're on the same version of typescript that's used by the nest cli.

If someone can figure out a good config for customWebpack, we can create a plugin similar to our @nrwl/react/plugins/babel plugin.

@djedlajn
Copy link

djedlajn commented Dec 6, 2019

@FrozenPandaz @creadicted

I have managed to get a bit further in configuring the plugin with custom webpack config.

Pretty much the same setup as with @creadicted

workspace.json

        "build": {
          "builder": "@nrwl/node:build",
          "options": {
            "outputPath": "dist/apps/auth-rights-api",
            "main": "apps/auth-rights-api/src/main.ts",
            "tsConfig": "apps/auth-rights-api/tsconfig.app.json",
            "assets": ["apps/auth-rights-api/src/assets"],
            "webpackConfig": "./apps/auth-rights-api/webpack.config.js"
          },
          "configurations": {
            "production": {
              "optimization": true,
              "extractLicenses": true,
              "inspect": false,
              "fileReplacements": [
                {
                  "replace": "apps/auth-rights-api/src/environments/environment.ts",
                  "with": "apps/auth-rights-api/src/environments/environment.prod.ts"
                }
              ]
            }
          }
        },

webpack.config.js

const CopyPlugin = require('copy-webpack-plugin');
const GeneratePackageJsonPlugin = require('generate-package-json-webpack-plugin');
const path = require('path');
const packageJson = require('../../package.json');

/**
 * Extend the default Webpack configuration from nx / ng.
 */

const getCustomTransformers = program => ({
  before: [require('@nestjs/swagger/plugin').before({}, program)]
});

module.exports = (config, context) => {
  // Extract output path from context
  const {
    options: { outputPath, sourceRoot }
  } = context;

  const newRules = config.module.rules.map(rule => {
    if (rule.loader === 'ts-loader') {
      return {
        ...rule,
        options: {
          ...rule.options,
          getCustomTransformers
        }
      };
    }
    return rule;
  });

  // Install additional plugins
  config.plugins = config.plugins || [];
  config.plugins.push(...extractRelevantNodeModules(outputPath));
  config.plugins.push(
    new CopyPlugin([
      { from: path.join(sourceRoot, '../', '.production.env'), to: path.join(outputPath, '.production.env') }
    ])
  );

  config.module.rules = newRules;

  return config;
};

/**
 * This repository only contains one single package.json file that lists the dependencies
 * of all its frontend and backend applications. When a frontend application is built,
 * its external dependencies (aka Node modules) are bundled in the resulting artifact.
 * However, it is not the case for a backend application (for various valid reasons).
 * Installing all the production dependencies would dramatically increase the size of the
 * artifact. Instead, we need to extract the dependencies which are actually used by the
 * backend application. We have implemented this behavior by complementing the default
 * Webpack configuration with additional plugins.
 *
 * @param {String} outputPath The path to the bundle being built
 * @returns {Array} An array of Webpack plugins
 */
function extractRelevantNodeModules(outputPath) {
  return [copyYarnLockFile(outputPath), generatePackageJson()];
}

/**
 * Copy the Yarn lock file to the bundle to make sure that the right dependencies are
 * installed when running `yarn install`.
 *
 * @param {String} outputPath The path to the bundle being built
 * @returns {*} A Webpack plugin
 */
function copyYarnLockFile(outputPath) {
  return new CopyPlugin([{ from: 'yarn.lock', to: path.join(outputPath, 'yarn.lock') }]);
}
/**
 * Generate a package.json file that contains only the dependencies which are actually
 * used in the code.
 *
 * @returns {*} A Webpack plugin
 */
function generatePackageJson() {
  const implicitDeps = [
    'class-transformer',
    'class-validator',
    '@nestjs/platform-express',
    'rxjs',
    'reflect-metadata',
    'tslib'
  ];
  const dependencies = implicitDeps.reduce((acc, dep) => {
    acc[dep] = packageJson.dependencies[dep];
    return acc;
  }, {});
  const basePackageJson = {
    dependencies
  };
  const pathToPackageJson = path.join(__dirname, '../../package.json');
  return new GeneratePackageJsonPlugin(basePackageJson, pathToPackageJson);
}

My webpack config does a bit more. But the important part is newRules.

I have successfully added getCustomTransformers but when I try to run it i get following error.

    openapi.ApiResponse({ status: 201 }),
    ^
ReferenceError: openapi is not defined
    at Module../apps/auth-rights-api/src/app/auth/auth.controller.ts (/home/netrunner/tp/dist/apps/auth-rights-api/main.js:156:5)
    at __webpack_require__ (/home/netrunner/tp/dist/apps/auth-rights-api/webpack:/webpack/bootstrap:19:1)
    at Module../apps/auth-rights-api/src/app/auth/auth.module.ts (/home/netrunner/tp/dist/apps/auth-rights-api/main.js:185:74)
    at __webpack_require__ (/home/netrunner/tp/dist/apps/auth-rights-api/webpack:/webpack/bootstrap:19:1)
    at Module../apps/auth-rights-api/src/app/app.module.ts (/home/netrunner/tp/dist/apps/auth-rights-api/main.js:103:75)
    at __webpack_require__ (/home/netrunner/tp/dist/apps/auth-rights-api/webpack:/webpack/bootstrap:19:1)
    at Module../apps/auth-rights-api/src/main.ts (/home/netrunner/tp/dist/apps/auth-rights-api/main.js:512:73)
    at __webpack_require__ (/home/netrunner/tp/dist/apps/auth-rights-api/webpack:/webpack/bootstrap:19:1)
    at Object.0 (/home/netrunner/tp/dist/apps/auth-rights-api/main.js:946:18)
    at __webpack_require__ (/home/netrunner/tp/dist/apps/auth-rights-api/webpack:/webpack/bootstrap:19:1)

I suspect that openapi is missing from the bundle that webpack produces. It would be great if nx could be extended a bit more easily overall. Similar to how composing of wepback config works with ``

@quanganh206
Copy link

Hi @FrozenPandaz, I success with Webpack build on NestJS app but still have problem with uglify it for production. Is there any small tip here to overcome it?

@creadicted
Copy link

creadicted commented Jan 14, 2020

Hi @FrozenPandaz, I success with Webpack build on NestJS app but still have problem with uglify it for production. Is there any small tip here to overcome it?

@quanganh206 Can you share how you succeeded?

@prmichaelsen
Copy link

prmichaelsen commented Feb 17, 2020

Chiming in here. I've configured my webpack like @djedlajn and still get:

TypeError: Cannot read property 'getTypeChecker' of undefined
    at ControllerClassVisitor.visit (/Users/mchpatr/playground/parm/node_modules/@nestjs/swagger/dist/plugin/visitors/controller-class.visitor.js:12:37)

Here's my webpack.config with some differences from @djedlajn's

// webpack.config.ts

/**
 * Extend the default Webpack configuration from nx / ng.
 * this webpack.config is used w/ node:build builder
 * see angular.json greenroom-rest-api
 */
module.exports = (config, context) => {
  // Install additional plugins
  console.log('loading plugins')

  addSwagger(config);

  return config;
};


/**
 * Adds nestjs swagger plugin 
 * 
 * nestjs swagger: https://docs.nestjs.com/recipes/swagger#plugin
 * ts-loader: https://github.com/Igorbek/typescript-plugin-styled-components#ts-loader
 * 
 * Someone else has done this, see:
 * https://github.com/nrwl/nx/issues/2147 
 */
const addSwagger = (config) => {
  const rule = config.module.rules
    .find(rule => rule.loader === 'ts-loader');
  if (!rule)
    throw new Error('no ts-loader rule found');
  rule.options = {
    ...rule.options,
    getCustomTransformers: (program) => ({
      before: [require('@nestjs/swagger/plugin').before({
        classValidatorShim: true,
      }, program)]
    }),
  };
}

Changing the typescript version to match that of nestjs/nest-cli did not fix the issue.

I was able to add program = ts.createProgram([sourceFile.fileName], {}); to controller-class.visitor and model-class.vistor and then I ran into the same openapi is not defined issue.

@prmichaelsen
Copy link

prmichaelsen commented Feb 17, 2020

Believe it or not, I figured it out.

const webpack = require('webpack');
// ...
  config.plugins = [
    ...(config.plugins || []),
    new webpack.ProvidePlugin({
      'openapi': '@nestjs/swagger',
    })
  ]  
// ...

The global openapi object is not defined which causes the error. You can use a webpack shim to define it: https://webpack.js.org/guides/shimming/

I'm still curious how @djedlajn managed to fix the TypeError: Cannot read property 'getTypeChecker' of undefined.

@prmichaelsen
Copy link

prmichaelsen commented Feb 17, 2020

Ok, final working solution. It's probably sinful, but here you go nonetheless.

The main problem seems to be that nx isn't passing the program to the plugins. To get around this, I just created the program myself in my webpack.config.ts like so:

const program = ts.createProgram([
  path.join(__dirname, 'main.ts')
], {});

So the final webpack.config.ts is:

const path = require('path');
const webpack = require('webpack');
const ts = require('typescript');

/**
 * Extend the default Webpack configuration from nx / ng.
 * this webpack.config is used w/ node:build builder
 * see angular.json greenroom-rest-api
 */
module.exports = (config, context) => {
  // Install additional plugins
  console.log('loading plugins')

  addSwagger(config);

  config.plugins = [
    ...(config.plugins || []),
    new webpack.ProvidePlugin({
      'openapi': '@nestjs/swagger',
    })
  ]  

  return config;
};

/**
 * Adds nestjs swagger plugin 
 * 
 * nestjs swagger: https://docs.nestjs.com/recipes/swagger#plugin
 * ts-loader: https://github.com/Igorbek/typescript-plugin-styled-components#ts-loader
 * getCustomTransformers: https://github.com/TypeStrong/ts-loader#getcustomtransformers
 * 
 * Someone else has done this, see:
 * https://github.com/nrwl/nx/issues/2147 
 */
const addSwagger = (config) => {
  const rule = config.module.rules
    .find(rule => rule.loader === 'ts-loader');
  if (!rule)
    throw new Error('no ts-loader rule found');
  rule.options = {
    ...rule.options,
    getCustomTransformers: () => {
      const program = ts.createProgram([
        path.join(__dirname, 'main.ts')
      ], {});
      return {
        before: [require('@nestjs/swagger/plugin').before({
          classValidatorShim: true,
        }, program)]
      };
    },
  };
}

And angular.json:

// angular.json
//...
        "build": {
          "builder": "@nrwl/node:build",
          "options": {
            "outputPath": "dist/apps/greenroom-rest-api",
            "main": "apps/greenroom-rest-api/src/main.ts",
            "tsConfig": "apps/greenroom-rest-api/tsconfig.app.json",
            "assets": ["apps/greenroom-rest-api/src/assets"],
            "webpackConfig": "apps/greenroom-rest-api/webpack.config.ts"
          },
//...

@fwoelffel
Copy link

fwoelffel commented Feb 26, 2020

Hi there,

Here's my webpack.config.js:

const swaggerPlugin = require('@nestjs/swagger/plugin');
module.exports = config => {
  const rule = config.module.rules.find(rule => rule.loader === 'ts-loader');
  if (!rule) throw new Error('no ts-loader rule found');
  rule.options.getCustomTransformers = program => ({
    before: [
      swaggerPlugin.before(
        {
          dtoFileNameSuffix: ['.dto.ts', '.ro.ts', '.entity.ts']
        },
        program
      )
    ]
  });
  return config;
};

It looks like it work but the generated Swagger documentation is missing a lot of information. It doesn't even seem to bother about the dtoFileNameSuffix option.

Has anyone managed to get this fully working?

@prmichaelsen
Copy link

See my comment above, it is working.

@fwoelffel
Copy link

See my comment above, it is working.

Thanks for you answer @prmichaelsen. Sadly, I'm getting the exact same results with your code (which was my starting point). Are you absolutely sure your solution is taking the given options in account? I mean classValidatorShim is true by default, maybe you should try with false and see if it remove the descriptions inferred from class-validator.

I'm in the process of migrating my app to a nx workspace. The Swagger plugin was working perfectly fine when the app was built through the NestJS' CLI.

@prmichaelsen
Copy link

I will give it another try. Mine was working using it with classValidatorShim.

@thomas-jakemeyn
Copy link

thomas-jakemeyn commented Mar 6, 2020

Thank you for the inspiration! I did this, which is safer in my opinion. However, I could not get it to work as it should so far...

const CopyPlugin = require('copy-webpack-plugin');
const GeneratePackageJsonPlugin = require('generate-package-json-webpack-plugin');
const path = require('path');
const packageJson = require('./package.json');
const swaggerPlugin = require('@nestjs/swagger/plugin');
const webpack = require('webpack');

/**
 * Extend the default Webpack configuration from nx / ng.
 */
module.exports = (config, context) => {
  // Extract output path from context
  const {
    options: { outputPath },
  } = context;

  installNestSwaggerPlugin(config);

  // Install additional plugins
  config.plugins = config.plugins || [];
  config.plugins.push(...extractRelevantNodeModules(outputPath));
  config.plugins.push(new webpack.ProvidePlugin({
    'openapi': '@nestjs/swagger',
  }));

  return config;
};

/**
 * Add NestJS Swagger plugin.
 *  - NestJS Swagger: https://docs.nestjs.com/recipes/swagger#plugin
 *  - ts-loader: https://github.com/Igorbek/typescript-plugin-styled-components#ts-loader
 *  - getCustomTransformers: https://github.com/TypeStrong/ts-loader#getcustomtransformers
 *  - Someone else has done this: https://github.com/nrwl/nx/issues/2147
 */
const installNestSwaggerPlugin = config => {
  const rule = config.module.rules.find(rule => rule.loader === 'ts-loader');
  if (!rule) {
    throw new Error('Could not install NestJS Swagger plugin: no ts-loader rule found!');
  }
  const decorated = rule.options && rule.options.getCustomTransformers;
  const decorator = program => {
    const customTransformers = (decorated && decorated(...args)) || {};
    const before = customTransformers.before || [];
    before.push(swaggerPlugin.before({
      classValidatorShim: true,
    }, program));
    customTransformers.before = before;
    return customTransformers;
  };
  rule.options = rule.options || {};
  rule.options.getCustomTransformers = decorator;
};

/**
 * This repository only contains one single package.json file that lists the dependencies
 * of all its frontend and backend applications. When a frontend application is built,
 * its external dependencies (aka Node modules) are bundled in the resulting artifact.
 * However, it is not the case for a backend application (for various valid reasons).
 * Installing all the production dependencies would dramatically increase the size of the
 * artifact. Instead, we need to extract the dependencies which are actually used by the
 * backend application. We have implemented this behavior by complementing the default
 * Webpack configuration with additional plugins.
 *
 * @param {String} outputPath The path to the bundle being built
 * @returns {Array} An array of Webpack plugins
 */
function extractRelevantNodeModules(outputPath) {
  return [copyYarnLockFile(outputPath), generatePackageJson()];
}

/**
 * Copy the Yarn lock file to the bundle to make sure that the right dependencies are
 * installed when running `yarn install`.
 *
 * @param {String} outputPath The path to the bundle being built
 * @returns {*} A Webpack plugin
 */
function copyYarnLockFile(outputPath) {
  return new CopyPlugin([{ from: 'yarn.lock', to: path.join(outputPath, 'yarn.lock') }]);
}

/**
 * Generate a package.json file that contains only the dependencies which are actually
 * used in the code.
 *
 * @returns {*} A Webpack plugin
 */
function generatePackageJson() {
  const implicitDeps = [
    'class-transformer',
    'class-validator',
    '@nestjs/platform-express',
    'reflect-metadata',
    'swagger-ui-express',
  ];
  const dependencies = implicitDeps.reduce((acc, dep) => {
    acc[dep] = packageJson.dependencies[dep];
    return acc;
  }, {});
  const basePackageJson = {
    dependencies,
  };
  const pathToPackageJson = path.join(__dirname, 'package.json');
  return new GeneratePackageJsonPlugin(basePackageJson, pathToPackageJson);
}

@nartc
Copy link
Contributor

nartc commented Mar 11, 2020

I might not have a very sophisticated models but I was able to get the plugin to work just fine.

// custom-webpack.config.js
const tsAutoMapperPlugin = require('@nartc/automapper-transformer-plugin').default; // my own custom plugin
const swaggerPlugin = require('@nestjs/swagger/plugin');

module.exports = (config, context) => {
  for (const rule of config.module.rules) {
    if (rule.loader !== 'ts-loader') {
      continue;
    }

    rule.options.getCustomTransformers = program => ({
      before: [
        swaggerPlugin.before(
          {
            dtoFileNameSuffix: ['.model.ts']
          },
          program
        ),
        tsAutoMapperPlugin(program).before
      ]
    });
  }

  return config;
};
// angular.json
{
   "build": {
          "builder": "@nrwl/node:build",
          "options": {
            "outputPath": "dist/apps/api",
            "main": "apps/api/src/main.ts",
            "tsConfig": "apps/api/tsconfig.app.json",
            "assets": ["apps/api/src/assets"],
            "webpackConfig": "custom-webpack.config.js"
          },
}
// test.model.ts 
export class Test {
  foo: string;
  bar: number;
}
// webpack result
/***/ "./apps/api/src/app/test.model.ts":
/*!****************************************!*\
  !*** ./apps/api/src/app/test.model.ts ***!
  \****************************************/
/*! exports provided: Test */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Test", function() { return Test; });
class Test {
    static _OPENAPI_METADATA_FACTORY() { // what swagger plugin produces
        return { foo: { required: true, type: () => String }, bar: { required: true, type: () => Number } };
    }
    static __NARTC_AUTOMAPPER_METADATA_FACTORY() { // what my plugin produces
        return { foo: () => String, bar: () => Number };
    }
}

@BrucePauker
Copy link

I tried to use your solution @prmichaelsen. It did compile and serve the project, however when I go on the documentation, it doesn't seem that the plugin had some effect.
For example, it doesn't automatically shows the returned entity from the controller or it doesn't bind the enums type in the entity files. Does somebody know why ?

@nicolasremise
Copy link

nicolasremise commented Apr 6, 2020

Hi,

I may have found a solution for people who can't make the proposed solutions work properly (@BrucePauker).

After several days of trying to make the NESTJS graphql plugin work with NX using the different solutions proposed above, without success. I realized that Nx passes the transpileOnly: true option to ts-loader so the graphql plugin worked but didn't change any decorators.

I passed the transpileOnly option to false when I added my plugin to the custom webpack configuration and 🎉 !

@jakubnavratil
Copy link

@nicolrem Can u share your solutions please?

@nicolasremise
Copy link

@trubit I just add a custom webpack config like this:

const path = require('path');
const ts = require('typescript');

/**
 * Adds nestjs grapqhl plugin
 *
 * Someone else has done this, see:
 * https://github.com/nrwl/nx/issues/2147
 */
const addGraphqlPlugin = (config) => {
  const rule = config.module.rules.find((rule) => rule.loader === 'ts-loader');
  if (!rule) throw new Error('no ts-loader rule found');
  rule.options = {
    ...rule.options,
    getCustomTransformers: (program) => {
      return {
        before: [require('@nestjs/graphql/plugin').before({}, program)],
      };
    },
    transpileOnly: false, // Required because if true, plugin can't work properly
  };
};

/**
 * Extend the default Webpack configuration from nx / ng to add Nestjs' graphql plugin and disable transpileOnly option.
 * this webpack.config is used w/ node:build builder
 */
module.exports = (config, context) => {
  console.log('Loading additional plugins...');

  addGraphqlPlugin(config);

  return config;
};

@Cammisuli Cammisuli self-assigned this May 22, 2020
@lifeofdubem
Copy link

Ok, final working solution. It's probably sinful, but here you go nonetheless.

The main problem seems to be that nx isn't passing the program to the plugins. To get around this, I just created the program myself in my webpack.config.ts like so:

const program = ts.createProgram([
  path.join(__dirname, 'main.ts')
], {});

So the final webpack.config.ts is:

const path = require('path');
const webpack = require('webpack');
const ts = require('typescript');

/**
 * Extend the default Webpack configuration from nx / ng.
 * this webpack.config is used w/ node:build builder
 * see angular.json greenroom-rest-api
 */
module.exports = (config, context) => {
  // Install additional plugins
  console.log('loading plugins')

  addSwagger(config);

  config.plugins = [
    ...(config.plugins || []),
    new webpack.ProvidePlugin({
      'openapi': '@nestjs/swagger',
    })
  ]  

  return config;
};

/**
 * Adds nestjs swagger plugin 
 * 
 * nestjs swagger: https://docs.nestjs.com/recipes/swagger#plugin
 * ts-loader: https://github.com/Igorbek/typescript-plugin-styled-components#ts-loader
 * getCustomTransformers: https://github.com/TypeStrong/ts-loader#getcustomtransformers
 * 
 * Someone else has done this, see:
 * https://github.com/nrwl/nx/issues/2147 
 */
const addSwagger = (config) => {
  const rule = config.module.rules
    .find(rule => rule.loader === 'ts-loader');
  if (!rule)
    throw new Error('no ts-loader rule found');
  rule.options = {
    ...rule.options,
    getCustomTransformers: () => {
      const program = ts.createProgram([
        path.join(__dirname, 'main.ts')
      ], {});
      return {
        before: [require('@nestjs/swagger/plugin').before({
          classValidatorShim: true,
        }, program)]
      };
    },
  };
}

And angular.json:

// angular.json
//...
        "build": {
          "builder": "@nrwl/node:build",
          "options": {
            "outputPath": "dist/apps/greenroom-rest-api",
            "main": "apps/greenroom-rest-api/src/main.ts",
            "tsConfig": "apps/greenroom-rest-api/tsconfig.app.json",
            "assets": ["apps/greenroom-rest-api/src/assets"],
            "webpackConfig": "apps/greenroom-rest-api/webpack.config.ts"
          },
//...

This works for me. Thanks

@Mdev303
Copy link

Mdev303 commented Jun 10, 2020

Yeah but it seem to only work for the swagger plugin what about "@nestjs/graphql/plugin" ?

@jakubnavratil
Copy link

It works, based on this #2147 (comment)

@gioragutt
Copy link
Contributor

gioragutt commented Aug 19, 2021

Hey @cfremgen, they have not released a new version since the PR was merged, so you'd have to wait for them to release to get this behavior.

Also, what @gms1 is true for when it will work.

@nartc
Copy link
Contributor

nartc commented Aug 19, 2021

What @gms1 and @gioragutt said, this feature will become available in the next release and there will be usage instruction in the release blog post. Thank you all!

@nartc
Copy link
Contributor

nartc commented Aug 25, 2021

12.8 has been released. The blog post is also out: https://blog.nrwl.io/micro-frontends-using-module-federation-presets-for-react-and-storybook-typescript-compiler-4120cf134816

Check it out!

@cfremgen
Copy link

cfremgen commented Aug 30, 2021

Has anyone got this working successfully? I'm getting the openapi error described earlier in this issue.

ReferenceError: openapi is not defined

@xmlking
Copy link
Contributor

xmlking commented Sep 6, 2021

nx --version
12.8.0

still getting ReferenceError: openapi is not defined error

 nx run api:serve 

>  NX  Using webpack 5. Reason: detected version 5 in node_modules/webpack/package.json

(node:8019) [DEP_WEBPACK_WATCH_WITHOUT_CALLBACK] DeprecationWarning: A 'callback' argument needs to be provided to the 'webpack(options, callback)' function when the 'watch' option is set. There is no way to handle the 'watch' option without a callback.
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:8019) [DEP_WEBPACK_DEPRECATION_ARRAY_TO_SET] DeprecationWarning: Compilation.modules was changed from Array to Set (using Array method 'reduce' is deprecated)
(node:8019) [DEP_WEBPACK_MODULE_ERRORS] DeprecationWarning: Module.errors was removed (use getErrors instead)
chunk (runtime: main) main.js (main) 20.5 KiB (javascript) 937 bytes (runtime) [entry] [rendered]
webpack compiled successfully (25dae5d5cedc54db1d01)
Debugger listening on ws://localhost:9229/006dc754-708c-4ded-b31b-b453b8e78a99
Debugger listening on ws://localhost:9229/006dc754-708c-4ded-b31b-b453b8e78a99
For help, see: https://nodejs.org/en/docs/inspector
Issues checking in progress...

/Users//Developer//yeti/dist/apps/api/main.js:33
    openapi.ApiResponse({ status: 200 }),
    ^
ReferenceError: openapi is not defined
  
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
No issues found.
        "tsPlugins": [
          {
            "name": "@nestjs/swagger/plugin",
            "options": {
              "dtoFileNameSuffix": [".dto.ts",".vm.ts"]
            }
          }
        ],

@xmlking
Copy link
Contributor

xmlking commented Sep 6, 2021

is this happening because I am using webpack 5 ?

@TicTak21
Copy link

Still not working...

nx: 12.7.2

"@nestjs/core": "^8.0.0",
"@nestjs/swagger": "^5.0.9"

@nartc
Copy link
Contributor

nartc commented Sep 10, 2021

@xmlking please open a new issue with a reproduce.
@TicTak21 have you tried 12.8 yet? https://blog.nrwl.io/micro-frontends-using-module-federation-presets-for-react-and-storybook-typescript-compiler-4120cf134816 This feature is available since Nx 12.8

@TicTak21
Copy link

@nartc my apologies. Just migrated to latest version(12.9.0) and it worked.
Thank you!

ManojBahuguna pushed a commit to ManojBahuguna/nx that referenced this issue Sep 16, 2021
* feat(node): add TS plugins support for build executor

ISSUES CLOSED: nrwl#2147

* docs(node): add tsPlugins to node build executor schema

* chore(node): reformat schema json

* chore(repo): update yarn.lock

* cleanup(node): adjust tsPlugins test for node build executor

* cleanup(node): remove packageJson check for tsPlugins test

* cleanup(node): increase timeout for tsPlugins e2e test

* cleanup(node): use type import for typescript types instead of importing typescript

Co-authored-by: Chau Tran <[email protected]>
Co-authored-by: Miroslav Jonas <[email protected]>
@Langstra
Copy link

We upgraded to nx 12.8.0 and tried addingf the nestjs/swagger plugin. After adding the plugin and starting the nestjs application we got a lot of typing errors. It also tries to check all the files in the testing directory and not just the src directory. Any ideas on how to have this plugin respect the tsconfig settings?

"build": {
          "builder": "@nrwl/node:build",
          "outputs": ["{options.outputPath}"],
          "options": {
            "outputPath": "dist/apps/api",
            "main": "apps/api/src/main.ts",
            "tsPlugins": ["@nestjs/swagger/plugin"],
            "tsConfig": "apps/api/tsconfig.app.json",
.....
          }
}

@nartc
Copy link
Contributor

nartc commented Oct 11, 2021

@Langstra Sorry to hear that. Can you create a new issue with a reproduce?

@Langstra
Copy link

Will try to do so 👌

@Frankitch
Copy link

Frankitch commented Nov 18, 2021

@xmlking @cfremgen I'm working with nx 13.1.4 and I get the ReferenceError: openapi is not defined like you, did you solve this issue?

@gioragutt
Copy link
Contributor

@Frankitch are all your nx plugins versions aligned?

@Frankitch
Copy link

@Frankitch are all your nx plugins versions aligned?

@gioragutt Mmmm... I think so :

  "dependencies": {
    "@angular/animations": "^12.2.13",
    "@angular/cdk": "^12.2.13",
    "@angular/common": "^12.2.13",
    "@angular/compiler": "^12.2.13",
    "@angular/core": "^12.2.13",
    "@angular/forms": "^12.2.13",
    "@angular/material": "^12.2.13",
    "@angular/platform-browser": "^12.2.13",
    "@angular/platform-browser-dynamic": "^12.2.13",
    "@angular/router": "^12.2.13",
     "@nestjs/common": "^7.0.0",
    "@nestjs/config": "^0.6.3",
    "@nestjs/core": "^7.0.0",
    "@nestjs/jwt": "^7.0.0",
    "@nestjs/passport": "^7.0.0",
    "@nestjs/platform-express": "^7.0.0",
    "class-transformer": "^0.4.0",
    "class-validator": "^0.12.2",
    "reflect-metadata": "^0.1.13",
    "rxjs": "~6.6.0",
    "swagger-ui-express": "^4.1.6",
    "tslib": "^2.3.1",
  },
  "devDependencies": {
    "@angular/cli": "^12.2.13",
    "@angular/compiler-cli": "^12.2.13",
    "@angular/language-service": "^12.2.13",
    "@angular/localize": "^12.2.13",
    "@nestjs/schematics": "^7.0.0",
    "@nestjs/swagger": "^4.0.0",
    "@nestjs/testing": "^7.0.0",
    "@ngxs/devtools-plugin": "^3.7.2",
    "@nrwl/angular": "13.1.4",
    "@nrwl/cli": "13.1.4",
    "@nrwl/cypress": "13.1.4",
    "@nrwl/eslint-plugin-nx": "13.1.4",
    "@nrwl/jest": "13.1.4",
    "@nrwl/nest": "13.1.4",
    "@nrwl/node": "13.1.4",
    "@nrwl/tao": "13.1.4",
    "@nrwl/workspace": "13.1.4",
    "typescript": "4.3.5",
    "webpack": "^5.64.0",
    "webpack-merge": "^5.8.0",
    "webpack-node-externals": "^3.0.0"
  }

@cfremgen
Copy link

@xmlking @cfremgen I'm working with nx 13.1.4 and I get the ReferenceError: openapi is not defined like you, did you solve this issue?

No, I was unable to get this working after a couple of hours. Same issue, all compatible NX versions.

I am guessing something realted to my project complexity or another dependency, but I don't have the time to try to narrow it down at this time.

@nartc
Copy link
Contributor

nartc commented Nov 18, 2021

@Frankitch @cfremgen if either one of you can provide a sample reproduce, I'm happy to take a look. And when you have a reproduce, please create a new issue and we can start tracking in that new issue. Sorry for the inconvenience

@Frankitch
Copy link

@cfremgen @nartc @xmlking @gioragutt I finally got it: in my case, it was due to a missing "module": "commonjs", (don't know why...) in the tsconfig.app.json of nestjs.

@CanKattwinkel
Copy link

If you come here as you debug this not working in your setup in 2022, it might be that your DTO is not following the file naming convention. By default all dto's must be in a my-file.dto.ts format as pointed out here.

@tienpvse1
Copy link

Thanks for the merge, would love to see a working example. Attempted the following with no luck, but this was pretty much a guess based on the commits I saw.

In angular.json:

image

worked like a charm, thanks !!!

@clayrisser
Copy link

How do I use the @nestjs/swagger/plugin with babel-loader?

@dan-cooke
Copy link
Contributor

dan-cooke commented Nov 3, 2022

tsPlugins option has been removed in NX 15, any ideas on what we do now?

#12966

Additionally any of the recommended webpack solutions in this thread result in "Invalid arguments" error

@beeman
Copy link
Contributor

beeman commented Nov 3, 2022

@clayrisser @dan-cooke FYI it's always better to create a new issue and reference this one than start commenting on an issue that's been closed over a year ago.

If only so you don't ping dozens of people that interacted/subscribed to this issue. Eg:
image

@DaSchTour
Copy link
Contributor

@beeman it's good that it was commented here. As i now know that I should not migrate to NX 15.

@prmichaelsen
Copy link

prmichaelsen commented Nov 4, 2022 via email

@github-actions
Copy link

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 21, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
community This is a good first issue for contributing outdated scope: node Issues related to Node, Express, NestJS support for Nx type: feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.