ng-universal
ng-universal copied to clipboard
TypeError: Class constructor Type cannot be invoked without 'new' - nest runtime error when using angular library + mikro orm
Is there an existing issue for this?
- [X] I have searched the existing issues
Current behavior
Runtime error when running a nest app. It appears to be related to mixing ES Modules with CommonJS modules but I am unable to deep dive to the point of resolving it on my own.
Minimum reproduction code
https://github.com/rat-matheson/nest-mikro-bug/
Steps to reproduce
I've created the following two repositories to demonstrate the issue.
- angular library - https://github.com/rat-matheson/nest-mikro-bug-lib/
- nest application - https://github.com/rat-matheson/nest-mikro-bug/
transformType.ts is in a separate library package generated through the angular cli. It is a simple implementation of the mikro orm Type class
app.service.ts is just a place in my nest application where I tried instantiating the class.
C:\Users\joelw\eclipse-workspace\tower-poi\packages\nest-bug-repo\projects\ngx-tmp\bug-repo\src\transformType.ts:3
export class TransformType<JsType = any, DbType = any> extends Type<JsType, DbType> {
^
TypeError: Class constructor Type cannot be invoked without 'new'
at new TransformType (C:\Users\joelw\eclipse-workspace\tower-poi\packages\nest-bug-repo\projects\ngx-tmp\bug-repo\src\transformType.ts:3:1)
at Function.TransformType.newTransform (C:\Users\joelw\eclipse-workspace\tower-poi\packages\nest-bug-repo\projects\ngx-tmp\bug-repo\src\transformType.ts:8:18)
at Object.<anonymous> (C:\Users\joelw\eclipse-workspace\tower-poi\packages\nest-bug-repo\src\app.service.ts:5:15)
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)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (C:\Users\joelw\eclipse-workspace\tower-poi\packages\nest-bug-repo\src\app.controller.ts:2:1)
Expected behavior
The nest application should just start normally without throwing the runtime exception. If I move transformType.ts to the nest project and just reference it there, everything starts fine. So something is happening when the class is being packaged in a separate library and imported into the nest application.
I don't think the issue is really related to mikro orm as I've had similar problems trying to include other packages that did not involve mikro orm.
Package
- [X] I don't know. Or some 3rd-party package
- [ ]
@nestjs/common
- [ ]
@nestjs/core
- [ ]
@nestjs/microservices
- [ ]
@nestjs/platform-express
- [ ]
@nestjs/platform-fastify
- [ ]
@nestjs/platform-socket.io
- [ ]
@nestjs/platform-ws
- [ ]
@nestjs/testing
- [ ]
@nestjs/websockets
- [x] Other (see below)
Other package
@mikro-orm/core
NestJS version
8.4.4
Packages versions
package.json for the nest application package.json for the angular library
Angular info
Angular CLI: 12.2.17
Node: 16.13.2 (Unsupported)
Package Manager: npm 8.1.0
OS: win32 x64
Angular: 12.2.16
... common, compiler, compiler-cli, core
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1202.17
@angular-devkit/build-angular 12.2.17
@angular-devkit/core 12.2.17
@angular-devkit/schematics 12.2.17
@angular/cli 12.2.17
@schematics/angular 12.2.17
ng-packagr 12.2.7
rxjs 6.6.7
typescript 4.3.5
Nest Info
[System Information]
OS Version : Windows 10
NodeJS Version : v16.13.2
NPM Version : 8.1.0
[Nest CLI]
Nest CLI Version : 8.2.5
[Nest Platform Information]
platform-express version : 8.4.4
schematics version : 8.0.10
testing version : 8.4.4
common version : 8.4.4
core version : 8.4.4
cli version : 8.2.5
Node.js version
v16.13.2
In which operating systems have you tested?
- [ ] macOS
- [X] Windows
- [ ] Linux
Other
If I upgrade to angular 13, it only produces .mjs files which I've also had issues incorporating into a nest app, so I'm sticking with angular 12 for the moment. Although in this simple case, it seems a little strange for me to be using angular to create a library that extends Type, I have lots of libraries that are shared between the backend and front end and up until now, the angular cli has been great at managing them.
I can't start you repo because I can't install @ngx-tmp/bug-repo
. NPM says it is not found
Thanks so much for taking a look at this. I've updated the nest application repository ( nest-mikro-bug ) to use the paths config in the tsconfig.json rather than the private npm repository I was using. You will need to do the following:
- get the updated nest-mikro-bug code - it will update the tsconfig.json and the package.json
- npm install
- switch to nest-mikro-bug-lib and build it->
ng build @ngx-tmp/bug-repo
- update the tsconfig.json for nest-mikro-bug to point to your output (in case your workspace has a different name than mine). You need to change this line - tsconfig.json#L22
- run
nest start
to start up nest
I tried something new. I built with nest, but than did the following:
- installed module-alias so I could more clearly specify which bundle I wanted to use
- ran using "node dist/main.js"
I was careful to use the umd module as this document says it is the format to use for node.js. The result was:
$ node dist/main.js
C:\Users\joelw\eclipse-workspace\tower-poi\packages\ngx-tmp\dist\ngx-tmp\bug-rep
o\bundles\ngx-tmp-bug-repo.umd.js:411
var _this = _super.apply(this, __spreadArray([], __read(argument
s))) || this;
^
TypeError: Class constructor Type cannot be invoked without 'new'
at new TransformType (C:\Users\joelw\eclipse-workspace\tower-poi\packages\ng
x-tmp\dist\ngx-tmp\bug-repo\bundles\ngx-tmp-bug-repo.umd.js:411:29)
at Function.TransformType.newTransform (C:\Users\joelw\eclipse-workspace\tow
er-poi\packages\ngx-tmp\dist\ngx-tmp\bug-repo\bundles\ngx-tmp-bug-repo.umd.js:41
6:19)
Not sure if it helps much but it is something new. Here's some context around line 411
var TransformType = /** @class */ (function (_super) {
__extends(TransformType, _super);
function TransformType() {
var _this = _super.apply(this, __spreadArray([], __read(arguments))) || this;
_this.options = {};
return _this;
}
I made a bit of progress. It seems nestjs was including the umd build from angular package. When I explicitly set the only build to be the esm2015 build in the package.json, nestjs was able to properly load the package at runtime.
//Went from this
{
"name": "@ngx-tmp/bug-repo",
"version": "0.0.1",
"license": "UNLICENSED",
"peerDependencies": {
"@mikro-orm/core": "^5.1.3"
},
"dependencies": {
"tslib": "^2.3.0"
},
"main": "bundles/ngx-tmp-bug-repo.umd.js",
"module": "fesm2015/ngx-tmp-bug-repo.js",
"es2015": "fesm2015/ngx-tmp-bug-repo.js",
"esm2015": "esm2015/ngx-tmp-bug-repo.js",
"fesm2015": "fesm2015/ngx-tmp-bug-repo.js",
"typings": "ngx-tmp-bug-repo.d.ts",
"sideEffects": false
}
// to this where I updated "main" to point to esm2015
{
"name": "@ngx-tmp/bug-repo",
"version": "0.0.1",
"license": "UNLICENSED",
"peerDependencies": {
"@mikro-orm/core": "^5.1.3"
},
"dependencies": {
"tslib": "^2.3.0"
},
"main": "esm2015/ngx-tmp-bug-repo.js",
"module": "fesm2015/ngx-tmp-bug-repo.js",
"es2015": "fesm2015/ngx-tmp-bug-repo.js",
"esm2015": "esm2015/ngx-tmp-bug-repo.js",
"fesm2015": "fesm2015/ngx-tmp-bug-repo.js",
"typings": "ngx-tmp-bug-repo.d.ts",
"sideEffects": false
}
Is there a way to somehow tell nestjs which target build to use in the package.json rather than having to manually update items in the node_modules folder?
That generally should be something that typescript is determining, and how node
is running, not anything specific to Nest
Yes, now that I've gone a bit deeper, I can see that you are right. Two possible solutions are:
- figuring out some way for angular to get angular to set "main" to the esm2015 build in the package.json
- figuring out some way to get nest to use the "esm2015" build instead of "main" from the package.json
For (1), I've looked and I don't see any easy way to do it. I probably have to create a post build script. Do you have any ideas on how to do (2)?
Feel free to close this issue if you have no ideas where to go from here. I was hoping you might know something about the nest build process such that I can either override the module import target or possible set which angular target to use.
https://github.com/nestjs/ng-universal/issues/842#issuecomment-1118243358