Error importing PrismaClient in code compiled from typescript [SyntaxError: Named export 'PrismaClient' not found]

30.8k Views Asked by At

In server.ts, importing PrismaClient like this:

import { PrismaClient } from '@prisma/client';

export const prisma = new PrismaClient();

throws an Error when building with tsc and running the compiled code:

yarn run build && yarn run start

import { PrismaClient } from '@prisma/client';
         ^^^^^^^^^^^^
SyntaxError: Named export 'PrismaClient' not found. The requested module '@prisma/client' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

    import pkg from '@prisma/client';
    const { PrismaClient } = pkg;
    
        at ModuleJob._instantiate (internal/modules/esm/module_job.js:104:21)
        at async ModuleJob.run (internal/modules/esm/module_job.js:149:5)
        at async Loader.import (internal/modules/esm/loader.js:166:24)
        at async Object.loadESM (internal/process/esm_loader.js:68:5)
    error Command failed with exit code 1.

So I did what was recommended and changed the code to:

import Prisma from '@prisma/client';

const { PrismaClient } = Prisma;
export const prisma = new PrismaClient();

And this code works after building with tsc and running the resulting code. But now running the typescript files with ts-node-dev throws this Error:

yarn run dev

TypeError: Cannot destructure property 'PrismaClient' of 'client_1.default' as it is undefined.
    at Object.<anonymous> (C:\Users\gfs10\Projetos\rest-api\src\server.ts:11:9)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Module._compile (C:\Users\gfs10\Projetos\rest-api\node_modules\source-map-support\source-map-support.js:547:25)
    at Module.m._compile (C:\Users\gfs10\AppData\Local\Temp\ts-node-dev-hook-9753341767331849.js:69:33)
    at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at require.extensions.<computed> (C:\Users\gfs10\AppData\Local\Temp\ts-node-dev-hook-9753341767331849.js:71:20)
    at Object.nodeDevHook [as .ts] (C:\Users\gfs10\Projetos\rest-api\node_modules\ts-node-dev\lib\hook.js:63:13)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
[ERROR] 19:03:38 TypeError: Cannot destructure property 'PrismaClient' of 'client_1.default' as it is undefined.

And changing the code to:

import Prisma from '@prisma/client';

export const prisma = new Prisma.PrismaClient();

throws this error:

yarn run dev

TypeError: Cannot read property 'PrismaClient' of undefined
    at Object.<anonymous> (C:\Users\gfs10\Projetos\rest-api\src\server.ts:11:34)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Module._compile (C:\Users\gfs10\Projetos\rest-api\node_modules\source-map-support\source-map-support.js:547:25)
    at Module.m._compile (C:\Users\gfs10\AppData\Local\Temp\ts-node-dev-hook-7015369495927739.js:69:33)
    at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at require.extensions.<computed> (C:\Users\gfs10\AppData\Local\Temp\ts-node-dev-hook-7015369495927739.js:71:20)
    at Object.nodeDevHook [as .ts] (C:\Users\gfs10\Projetos\rest-api\node_modules\ts-node-dev\lib\hook.js:63:13)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
[ERROR] 19:09:01 TypeError: Cannot read property 'PrismaClient' of undefined

How come? How can I make both work at the same time?

My tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "moduleResolution": "node",
    "outDir": "./build/",
    "rootDir": "./src/",
    "strict": true,
    "alwaysStrict": true,
    "noImplicitAny": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noFallthroughCasesInSwitch": true,
    "esModuleInterop": true,
    "declaration": true
  }
}

My package.json:

{
  "name": "rest-api",
  "version": "1.0.0",
  "description": "A REST API boilerplate.",
  "main": "server.ts",
  "author": "Gledyson Ferreira",
  "license": "MIT",
  "type": "module",
  "scripts": {
    "start": "node --experimental-specifier-resolution=node build/server.js",
    "dev": "SET NODE_ENV=development&& ts-node-dev --clear src/server.ts",
    "build": "tsc",
    "lint": "eslint --ext .ts ."
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^4.18.0",
    "@typescript-eslint/parser": "^4.18.0",
    "eslint": "^7.22.0",
    "prisma": "^2.19.0",
    "ts-node-dev": "^1.1.6",
    "typescript": "^4.2.3"
  },
  "dependencies": {
    "@prisma/client": "^2.19.0",
    "@types/bcrypt": "^3.0.0",
    "@types/cors": "^2.8.10",
    "@types/express": "^4.17.11",
    "@types/jsonwebtoken": "^8.5.1",
    "@types/morgan": "^1.9.2",
    "@types/node": "^14.14.35",
    "@types/passport": "^1.0.6",
    "@types/passport-jwt": "^3.0.5",
    "bcrypt": "^5.0.1",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "jsonwebtoken": "^8.5.1",
    "morgan": "^1.10.0",
    "passport": "^0.4.1",
    "passport-jwt": "^4.0.0"
  }
}

My server.ts

import express from 'express';
import Prisma from '@prisma/client';
import config from './config';
import api from './api';
import middleware from './middlewares';
import morgan from 'morgan';
import cors from 'cors';
import passport from 'passport';
import setReqUser from './services/passport';

export const prisma = new Prisma.PrismaClient();
const app = express();

app.disable('x-powered-by');
app.use(express.json());
app.use(morgan('tiny'));
app.use(cors());
app.use(passport.initialize());
setReqUser(passport);

app.use('/api/v1', api.authRoute);
app.use('/api/v1/users', api.userRoute);

app.use(middleware.unknownEndpoint);
app.use(middleware.errorHandler);

app.listen(config.port, () => {
  console.log(`
    ################################################
    
    Server running on port ${config.port} in ${config.env} mode.

    ################################################
  `);
});
3

There are 3 best solutions below

1
On BEST ANSWER

As you may know this issue was being worked on here.

In the mean time what you could do to proceed with your tests is to use dependency injection with a mocked prisma client and to move the deconstruction line

const { PrismaClient } = pkg;

to where your class or function uses it inside an if, i.e:

class MyClass {
  prisma: Prisma.PrismaClient

  def constructor(props) {
    if (!props?.prisma) {
      const { PrismaClient } = Prisma
      this.prisma = new PrismaClient({
        log: ['error']
      })
    } else {
      this.prisma = props.prisma
    }
  }
}

I know its not ideal but hopefully this does the trick.

to mock the PrismaClient you could mock it using jest-mock-extended like so

const mockPrisma = mockDeep<OriginalPrismaClient>();
1
On

If you just cloned this project then it's likely that you didn't generate the prisma client yet. I've ran npx prisma generate and it seemed to fix it.

0
On

Prisma doesn't support ES6 modules yet. I would suggest following this request and in the meantime using CommonJS i.e. removing "type": "module" from your package.json and setting the target in tsconfig.json to ES2018.