Apollo-server: Class constructor DataSource cannot be invoked without 'new' using Babel

Created on 23 Jan 2019  路  12Comments  路  Source: apollographql/apollo-server

I created my own Custom DataSource class using Knex as the backend, but I keep getting this error about my call to the DataSource superclass: Class constructor DataSource cannot be invoked without 'new' using Babel

I read the previous issues pertaining to this error, and everybody solved it by simply upgrading to es6+ but I am using the latest ECMA and it is still happening.

The issue is with the super() here:

const { DataSource } = require("apollo-datasource");
class RoleAPI extends DataSource {
  constructor(database) {
    super(); // Line referenced throwing the the error
    this.database = database;
  }
  initialize(config) {
    this.context = config.context;
  }
  async getAllRoles() {
    const roles = await this.database("auth_role").select("name");
    return roles;
  }
}
module.exports = RoleAPI;

For reference, here is my server definition:

import database from "./common/database";
import UserAPI from "./resolvers/datasources/user";
import RoleAPI from "./resolvers/datasources/role";
const dataSources = () => ({
  roleAPI: new RoleAPI(database),
  userAPI: new UserAPI(database)
});
const app = express();
const server = new ApolloServer({
  typeDefs,
  resolvers,
  dataSources,
  playground: GQL_PLAYGROUND,
  introspection: GQL_INTROSPECTION
});

Here is the DataSource's usage:

const { GraphQLScalarType } = require("graphql");
const { Kind } = require("graphql/language");
const resolvers = {
  Role: {},
  Query: {
    roles: async (parent, args, datasources) =>
      datasources.roleAPI.getAllRoles
  }
}

I am running @babel/core, @babel/runtime @babel/node and "@babel/preset-env" all ~7.2.0 - still to no avail. Also the error is returned when I try and run queries in the Playground - queries that previously worked until I setup the DataSource. Instead of the data, it returns the error about the call to super(). Nothing in the console.

Most helpful comment

For anyone that runs into this problem - I solved it by adding this to my .babelrc file and it seems to have fixed it.

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "current"
        }
      }
    ]
  ],
  "plugins": ["@babel/plugin-transform-runtime"]
}

All 12 comments

For anyone that runs into this problem - I solved it by adding this to my .babelrc file and it seems to have fixed it.

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "current"
        }
      }
    ]
  ],
  "plugins": ["@babel/plugin-transform-runtime"]
}

Did not solve it for me :-(

@vaskaloidis Yes, this can be avoided by not transpiling classes in your own user code which extend the native classes provided by RESTDataSource. The mixture of compiled and native classes has been historically difficult, but modern versions of Node.js support native classes, so this would seem to be a result of over-transpiling code which could benefit from the native ECMAScript class support provided in modern Node.js versions.

@mschipperheyn Do you have a Babel configuration in place that you could share? What version of Node.js are you using?

@abernix I fixed this using babel.config.js:

process.env.BUILD_TARGET === 'client'
            ? [
                require.resolve('@babel/preset-env'),
                {
                    modules: false,
                },
              ]
            : [
                require.resolve('@babel/preset-env'),
                {
                    targets: {
                        node: 'current',
                    },
                    exclude: [
                        'babel-plugin-transform-classes',
                        '@babel/plugin-transform-classes',
                    ],
                    modules: false,
                },
              ];

@vaskaloidis As you said, adding:

    {
      "targets": {
        "node": "current"
      }
    }

Solved the problem

This is my .babelrc:

{
  "presets": [
    [
    "@babel/preset-env",
    {
      "targets": {
        "node": "current"
      }
    }
  ]
  ],
  "plugins": ["@babel/plugin-proposal-object-rest-spread"],
  "sourceMaps": "inline",
  "retainLines": true
}

I successfully solved this issue with babel-preset-latest-node

My .babelrc:

{
  "presets": [["latest-node", { "target": "current" }]]
}

Closing this because the issue has been solved above.

How do I do if I'm using the typescript compiler ?

@NitroBAY same question here

@NitroBAY , @ahouzzer , here is solution for TS:
https://github.com/apollographql/apollo-server/issues/1388#issuecomment-406756378

To future readers: I solved this problem setting target and moduleResolution in tsconfig.json like this...

{
  "compilerOptions": {
    "outDir": "dist",
    "rootDir": "src",
    "lib": [
      "esnext"
    ],
    "strict": true,
    "esModuleInterop": true,
    "target": "ES2015",
    "moduleResolution": "node"
  },
  "include": [
    "src/**/*"
  ]
}

seriously, people?

Was this page helpful?
0 / 5 - 0 ratings