prisma: `pnpm install` not running `prisma generate`

Bug description

When installing within a PNPM monorepo the generator isn’t being run. I suspect it might have something to do with PNPM symlinking dependencies and therefore messing with the client postinstall script. Just a guess though.

How to reproduce

Reproduction: https://github.com/scriptcoded/prisma-issue-6603

  1. Make sure PNPM is installed. (https://pnpm.io/installation)
  2. Clone the reproduction repo: git clone git@github.com:scriptcoded/prisma-issue-6603.git
  3. Enter the app directory: cd prisma-issue-6603/app
  4. Install dependencies using PNPM: pnpm i
  5. Run the application: pnpx ts-node index.ts
  6. Observe that the Prisma client has not been generated

Expected behavior

The Prisma client should be generated and the application should run without issues.

Prisma information

Project set up accoring to the Start from scratch guide.

Environment & setup

  • OS: Manjaro Linux x86_64
  • Database: PostgreSQL 12
  • Node.js version: v14.15.2
  • Prisma version:
prisma               : 2.21.2
@prisma/client       : 2.21.2
Current platform     : debian-openssl-1.1.x
Query Engine         : query-engine e421996c87d5f3c8f7eeadd502d4ad402c89464d (at ../node_modules/.pnpm/@prisma+engines@2.21.0-36.e421996c87d5f3c8f7eeadd502d4ad402c89464d/node_modules/@prisma/engines/query-engine-debian-openssl-1.1.x)
Migration Engine     : migration-engine-cli e421996c87d5f3c8f7eeadd502d4ad402c89464d (at ../node_modules/.pnpm/@prisma+engines@2.21.0-36.e421996c87d5f3c8f7eeadd502d4ad402c89464d/node_modules/@prisma/engines/migration-engine-debian-openssl-1.1.x)
Introspection Engine : introspection-core e421996c87d5f3c8f7eeadd502d4ad402c89464d (at ../node_modules/.pnpm/@prisma+engines@2.21.0-36.e421996c87d5f3c8f7eeadd502d4ad402c89464d/node_modules/@prisma/engines/introspection-engine-debian-openssl-1.1.x)
Format Binary        : prisma-fmt e421996c87d5f3c8f7eeadd502d4ad402c89464d (at ../node_modules/.pnpm/@prisma+engines@2.21.0-36.e421996c87d5f3c8f7eeadd502d4ad402c89464d/node_modules/@prisma/engines/prisma-fmt-debian-openssl-1.1.x)
Default Engines Hash : e421996c87d5f3c8f7eeadd502d4ad402c89464d
Studio               : 0.371.0

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 40
  • Comments: 21 (6 by maintainers)

Commits related to this issue

Most upvoted comments

Hey @jlarmstrongiv this has not been released as it would cause many side-effects and breaking changes. Issues with automatic pnpm generation have not been fixed. However, if you just want to have multiple generated clients in your monorepo, you can have per-package generation folders (in their node_modules folder) instead of the root one. You can simply add this to your schema:

generator client {
  provider = "prisma-client-js"
  output = "../node_modules/.prisma/client" // <-- generate in your package node_modules, not the root
}
import { PrismaClient } from '.prisma/client' // <-- import the dot generated folder, not @prisma/client

@scriptcoded thanks for your bug report!

At the moment, it gets generated in your workspace’s node_modules and not in the package’s node_modules (if you run pnpx prisma generate). This would be fine for only one package but not many.

Now, there’s another problem, you want to import @prisma/client. That’s not possible because of pnpm and the way we resolve the generated .prisma/client. In short, when you install, pnpm will put @prisma/client in your workspace’s node_modules. This has three effects:

  1. We can’t resolve the .prisma/client via @prisma/client because they don’t live in the same node_modules folder. The one is in the workspace, and the other is in the package.
  2. When you import @prisma/client it then tries to import the neighbor .prisma/client. For the reason explained above, this is not possible. Even though pnpm claims to hardlink, this does not happen on the folders (not possible).
  3. For the same reasons, we would not be able to provide the right types for each package (assuming that you have multiple packages using multiple clients, each with a different schema).
  4. That’s how things are resolved by import / require.

For the reasons above, I suggest that on such a pnpm monorepo setup, you would not import @prisma/client, but you would import the generated .prisma/client directly instead. It would be wise that we document this.

If you would like to give it a try, please use prisma@2.24.0-integration-fix-paths.3 and @prisma/client@2.24.0-integration-fix-paths.3. It still won’t generate automatically on install, but at least you can do pnpx prisma generate in your package’s folder. Not closing the issue until that works automatically on install. Your feedback is very welcome 😃

Still happening

I can confirm this. For now you can workaround it by adding a manual postinstall script to your package running prisma generate like so:

{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "postinstall": "prisma generate"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/node": "^14.14.41",
    "prisma": "^2.21.2",
    "ts-node": "^9.1.1",
    "typescript": "^4.2.4"
  },
  "dependencies": {
    "@prisma/client": "^2.21.2"
  }
}

I just ran into this issue. It does work with the import {PrismaClient} from '../node_modules/.prisma/client just not sure if it’ll pass our code review process.
changing the .prisma to

generator client {
  provider = "prisma-client-js"
  output   = "../src/generated/foo"
}

seems to avoid the issues

I love Prisma, but it doesn’t seem to work for me on pnpm, and I assume it also doesn’t work on Yarn 2 for more or less the same reason.

Was it such a good idea to make the Prisma client to be generated on node_modules, assuming it can change depending on which package management you use? Maybe it wasn’t obvious in the beginning that this would be a problem…

We have moved on to NPM workspaces since this issue was created and I can confirm that they suffer from the same issue. The following root package.json file works like a charm for anyone interested.

{
  "name": "my-project",
  "workspaces": [
    "apps/api"
  ],
  "scripts": {
    "postinstall": "npm exec -w apps/api prisma generate"
  }
}

I should note that it also requires our generator to look like this. The output references the root node_modules:

generator client {
  provider        = "prisma-client-js"
  output          = "../../../node_modules/.prisma/client"
}

Just ran into this issue today 😞 pnpm + turborepo

Hey everyone. pnpm maintains a cache of all installed dependencies so that it does not need to install them twice. With that, it also prevents a postinstall hook to run twice. This unfortunately breaks a core assumption. For now we suggest that you use this workaround, until we design a proper fix.

Here’s another workaround that worked for me. It does not require us to change Prisma client output directory and we can simply import from @prisma/client as usual.

import Prisma1, * as Prisma2 from "@prisma/client";

const Prisma = Prisma1 || Prisma2;
const prisma = new Prisma.PrismaClient();

same problem, This’s my methods.

image

And PrismaClient imported use ‘@prisma/client’, like this

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

const prisma: PrismaClient = new PrismaClient();

Just ran into this issue today 😞 pnpm + turborepo

Had to create a bit more complicated workaround because of a few issues.

  • import { PrismaClient } from '.prisma/client' not an option because I’m re-exporting prisma from a dedicated db package. Since there’s no package.json in .prisma/client, browser packages using various derived types would pick up and try to bundle index.js, not index-browser.js.
  • output = "../node_modules/.prisma/client" sort of worked, but for some reason dist/*.d.ts files could resolve the paths and types, but not src/*.ts. Possible related to my personal TS and repo config, but who knows. I’ve spent over a week retooling my monorepo and trying different configs by now.

Edit: simplified solution - create a client generation script and add it to package postinstall:

#!/bin/sh

if [ -x "node_modules/prisma" ]
then
  pnpm prisma generate
else
  # for multistage docker build, dev deps won't be installed in production mode
  pnpm dlx $(pnpm list --depth 0 --dev --parseable | grep -o -m 1 'prisma@[0-9]\+\.[0-9]\+\.[0-9]\+$' ) generate
fi

# link to store from package node_modules because weird TS path resolution quirks
rm -rf node_modules/.prisma && mkdir node_modules/.prisma
ln -s $(realpath node_modules/@prisma/client/../../)/.prisma/client node_modules/.prisma/client
exit 0

You can define your own output location with defining output in the generator block of Prisma Client if that helps - then Prisma Client is generated at that path @andrerpena.

Thaaar be dragons in postinstall. The kind that loop forever…

Proceed with caution.