-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Comments
That has nothing todo with nx. |
@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... |
@maku Ok I am sorry you were right. I used a custom webpack.config.js for the project
checked what will be injected in there and extended it with the 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:
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. |
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 |
I have managed to get a bit further in configuring the plugin with custom webpack config. Pretty much the same setup as with @creadicted
My webpack config does a bit more. But the important part is I have successfully added
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 `` |
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? |
Chiming in here. I've configured my webpack like @djedlajn and still get:
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 I was able to add |
Believe it or not, I figured it out. const webpack = require('webpack');
// ...
config.plugins = [
...(config.plugins || []),
new webpack.ProvidePlugin({
'openapi': '@nestjs/swagger',
})
]
// ... The global I'm still curious how @djedlajn managed to fix the |
Ok, final working solution. It's probably sinful, but here you go nonetheless. The main problem seems to be that const program = ts.createProgram([
path.join(__dirname, 'main.ts')
], {}); So the final 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
//...
"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"
},
//... |
Hi there, Here's my 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 Has anyone managed to get this fully working? |
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 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. |
I will give it another try. Mine was working using it with classValidatorShim. |
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);
} |
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 };
}
} |
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. |
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 I passed the |
@nicolrem Can u share your solutions please? |
@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;
}; |
This works for me. Thanks |
Yeah but it seem to only work for the swagger plugin what about "@nestjs/graphql/plugin" ? |
It works, based on this #2147 (comment) |
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! |
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! |
Has anyone got this working successfully? I'm getting the openapi error described earlier in this issue.
|
nx --version still getting
"tsPlugins": [
{
"name": "@nestjs/swagger/plugin",
"options": {
"dtoFileNameSuffix": [".dto.ts",".vm.ts"]
}
}
], |
is this happening because I am using |
Still not working... nx: 12.7.2 "@nestjs/core": "^8.0.0",
"@nestjs/swagger": "^5.0.9" |
@xmlking please open a new issue with a reproduce. |
@nartc my apologies. Just migrated to latest version(12.9.0) and it worked. |
* 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]>
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?
|
@Langstra Sorry to hear that. Can you create a new issue with a reproduce? |
Will try to do so 👌 |
@Frankitch are all your nx plugins versions aligned? |
@gioragutt Mmmm... I think so :
|
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. |
@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 |
@cfremgen @nartc @xmlking @gioragutt I finally got it: in my case, it was due to a missing |
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 |
How do I use the |
Additionally any of the recommended webpack solutions in this thread result in "Invalid arguments" error |
@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: |
@beeman it's good that it was commented here. As i now know that I should not migrate to NX 15. |
well, I'm actually interested in getting these updates.
…On Thu, Nov 3, 2022 at 10:25 AM beeman ***@***.***> wrote:
@clayrisser <https://github.com/clayrisser> @dan-cooke
<https://github.com/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.
—
Reply to this email directly, view it on GitHub
<#2147 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACAJU3CMD5ZJ7R6XMQEL5ATWGPYOZANCNFSM4JVVJANQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
Patrick Michaelsen
(602) 345-0196
***@***.***
patryc LLC
|
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. |
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?
The text was updated successfully, but these errors were encountered: