objection.js: Class constructor Model cannot be invoked without 'new'

I’m getting the following error after upgrading to 0.8.0:

TypeError: Class constructor Model cannot be invoked without 'new'
  at new UserModel (/path/to/project/src/server/graphql/models/User/userModel.js:29:103)
  at Function.fromDatabaseJson (/path/to/project/node_modules/objection/lib/model/Model.js:443:19)
  at Object.createModels (/path/to/project/node_modules/objection/lib/queryBuilder/QueryBuilder.js:826:41)
  at Object.tryCatcher (/path/to/project/node_modules/bluebird/js/release/util.js:16:23)
  at Promise._settlePromiseFromHandler (/path/to/project/node_modules/bluebird/js/release/promise.js:512:31)
  at Promise._settlePromise (/path/to/project/node_modules/bluebird/js/release/promise.js:569:18)
  at Promise._settlePromise0 (/path/to/project/node_modules/bluebird/js/release/promise.js:614:10)
  at Promise._settlePromises (/path/to/project/node_modules/bluebird/js/release/promise.js:693:18)
  at Async._drainQueue (/path/to/project/node_modules/bluebird/js/release/async.js:133:16)
  at Async._drainQueues (/path/to/project/node_modules/bluebird/js/release/async.js:143:10)
  at Immediate.Async.drainQueues (/path/to/project/node_modules/bluebird/js/release/async.js:17:14)
  at runCallback (timers.js:672:20)
  at tryOnImmediate (timers.js:645:5)
  at processImmediate [as _immediateCallback] (timers.js:617:5)

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 8
  • Comments: 40 (3 by maintainers)

Most upvoted comments

You can also make it so that babel is using your node version by doing something like this:

{
  "presets": [
    ["env", {
      "targets": {
        "node": "current"
      }
      }],
    "stage-1"
  ],
  "plugins": []
}

If using TypeScript compiler, set output to at least es2015 in tsconfig.json

{
  "compilerOptions": {
     "target": "es2015"
  }
}

I am trying to use objection.js with Node in AWS Lambda (Node 8.10). I struggled for a few hours until I hit the jackpot. I tried several configuration recommendations and what finally did the trick was excluding the babel-plugin-transform-classes in the preset-env options. I share this for future reference, since it may help others searching for the same solution.

Cheers!

// webpack.config.js

...

{
  test: /\.(js|jsx)$/,
  exclude: /node_modules/,
  use: {
    loader: 'babel-loader',
    options: {
      presets: [
        [
          '@babel/preset-env',
          {
            target: { node: '8.10' }, // Node version on AWS Lambda
            modules: false,
            exclude: ['babel-plugin-transform-classes'],
          },
        ],
      ],
      plugins: [
        '@babel/plugin-proposal-class-properties',
        '@babel/plugin-proposal-object-rest-spread',
        '@babel/plugin-transform-runtime',
      ],
    },
  },
},

...

EDIT: As of objection 1.5.0 this problem should no longer exist. But please, stop transpiling your backend to ES5 in the year 2019! That’s idiotic! Target node 6 in your babel config instead. Node 6, that has everything objection needs, was released four years ago! Surely you are not using node versions < 6 are you? Transpiling to ES5 will, among other things, use regenerator to rewrite your async/await code into a switch/case state machine that adds quite a bit of overhead. END EDIT

Yep, please read the change log. Legacy node versions (0.10, 0.12) are no longer supported. You also need to migrate from the legacy ES5 inheritance to class and extend keywords. This is because of the way classes are implemented in Ecmascript. You cannot invoke class constructors without new and therefore this doesn’t work:

class Model {

}

function UserModel() {
  // You cannot do this.
  Model.apply(this, arguments);
}

And since objection Model is a native ES2015 class, you get that error. If you are using Babel you need to remove the babel-plugin-transform-es2015-classes plugin that does the conversion. You don’t need it anyway with node >= 4.0.0.

Check out the ESNext example project as an example of how to setup babel.

World should be ready for ES6 classes by now. We will not add support for ES5.

Yeah this is difficult. My JS environment is pretty crazy because I’m using Razzle for server-side rendering of a React app, and I use react-native-web to share code with iOS/Android with the same codebase.

Because I’m using Razzle, I don’t have full access to my full webpack+babel config. Even if I could edit my config, it would feel hacky to carve out an exception for objection.

Long story short, I found it easier to fork and compile objection to ES5+CommonJS, so that I don’t hit this error. If anybody else wants to use my compiled version, you can add the following to your package.json:

    "objection": "https://github.com/ericvicenti/objection.js",

I think this can be closed now that most people have migrated to objection 0.7.

@koskimas I believe you can use it as long as you’re using Babel 6. You just need to use the env preset package instead of es2015

And now the official 1.5.0 is released. No need for @next tag anymore.

Oh crap, some tests are broken because of this and I also need to wrap other classes. I’ll probably release the next RC during the next week.

@vjpr No I don’t think we should transpile objection. You should open issues in whatever project is preventing you from using libraries that use the class keyword.

@koskimas After all the reports, don’t you think its worth transpiling it? I don’t think the world is ready just yet. Most people run their code through babel, and its tricky to ignore one file from transpilation. It also entails having to ignore all the files that touch objection. Objection is the only lib in my stack that I need this complicated workaround for right now.

Just in case it helps anyone, I had a lot of trouble with @babel/preset-env and objection because my .browserslistrc was being read and included in its targets, meaning the transform-classes plugin was being used for my node 8.9.4 code when in fact no transpilation of classes was necessary.

There is an ignoreBrowserslistConfig option you can use to avoid this.

Ran into this too. Objection should export ES5 code (perhaps something like objection/es5), because most people are using a transpiler, and this forces the user to modify their babel config which may affect other things.

I’m not that familiar with next, but I did have this issue when running my Objection code in the server for testing with nightwatch.

For me, I had to execute require('babel-core/register'); after I’d required all of my Objection code. I ended up fixing it and not worrying much about how/why too deeply, but there’s also a bunch of stuff I found back then in this search that has to do with when/how to configure babel/es2015 that may help you, too: https://www.google.com/search?q=nightwatch+babel-core%2Fregister&oq=nightwatch+babel-core%2Fregister&aqs=chrome..69i57j0j69i65l3j0.4102j0j7&sourceid=chrome&ie=UTF-8

Hi, I’m trying to use objection.js in a next.js project but am also running into this problem with objection@1.0.0 and next@5.0.0. I’m running Node v9.6.0.

It probably has something to do with their babel preset next/babel but am not sure how to fix this.

Looks like this is the preset: https://github.com/zeit/next.js/blob/canary/server/build/babel/preset.js

You’re right, I’ll add a mention about Babel & friends to the change log. I’ll also leave this open for other people to find.