prisma: `prisma generate` fails in yarn2 / yarn3 workspaces

Bug description

We are using prisma in a yarn2 monorepo consisting of multiple workspaces. We were on version 2.23.0 before and everything was working fine. After upgrading to 2.29.0, prisma tries to run npm to install @prisma/client, even though it’s already installed in the current folder. This fails, as npm is unable to recognize the imported workspace.

yarn prisma generate
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
npm ERR! code EUNSUPPORTEDPROTOCOL
npm ERR! Unsupported URL Type "workspace:": workspace:core-api-plugins/article-import-edeka

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/valentinmorlock/.npm/_logs/2021-08-16T10_13_58_979Z-debug.log
Error: Command failed with exit code 1: npm install -D prisma@2.29.1

How to reproduce

clone this repo: https://github.com/v-morlock/prisma-yarn2-repro

yarn
cd workspace 
yarn prisma generate

Expected behavior

Prisma should generate its files

Prisma information

Environment & setup

  • OS: macOS
  • Database: mySQL
  • Node.js version: 16.1.0

Prisma Version

2.29.1, stopped working on 2.26.0

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 18
  • Comments: 15 (2 by maintainers)

Most upvoted comments

For what it’s worth, the following changes were sufficient in my case. I’m using Prisma with Yarn 3 (zero-installs / plug ‘n’ play) in a monorepo.

I started from @nishils’s suggestion (which worked) and simplified it as much as I could while still keeping everything functional:

  1. Just install prisma and @prisma/client as per the docs
yarn add -D prisma
yarn add @prisma/client
  1. Change the output directory to something outside of node_modules:
generator client {
  output = "../src/__generated__/prisma"
}
  1. Use pnpify to be able to run the command-line script
yarn add @yarnpkg/pnpify
yarn pnpify prisma generate

If anyone is interested here’s the patch we use to get prisma to work fully with PnP. It just swaps prisma’s bundled resolve for an actual require statement, and disables a sanity check that assumes the location of the prisma client, which doesn’t make sense in a PnP world. To get this to work, you’ll also need to add a packageExtension to prisma to get it to install resolve as a dependency. With all this, we have prisma working fully with PnP in a workspace set up. This patch is for prisma 2.30.3, but I’m guessing that you’d only need to perform similar patching in a newer version.

diff --git a/build/index.js b/build/index.js
index a34d93d52218ef223a8f6510b86778291fe5a9fa..0dfe9cf98f02033241f97b0710adbde371f1f1c1 100755
--- a/build/index.js
+++ b/build/index.js
@@ -34191,7 +34191,7 @@ var require_resolve2 = __commonJS((exports2) => {
     resolve: () => resolve,
     resolvePkg: () => resolvePkg2
   });
-  var import_resolve = __toModule3(require_resolve());
+  var import_resolve = __toModule3(require("resolve"));
   var import_path10 = __toModule3(require("path"));
   async function resolve(id, options) {
     const _options = {preserveSymlinks: false, ...options};
@@ -34259,9 +34259,6 @@ var require_predefinedGeneratorResolvers = __commonJS((exports2) => {
       return resolvedClientDir;
     if (clientDir === void 0)
       return resolvedClientDir;
-    const relDir = import_path10.default.relative(CLIDir, clientDir).split(import_path10.default.sep);
-    if (relDir[0] !== ".." || relDir[1] === "..")
-      return void 0;
     return resolvedClientDir;
   }
   var predefinedGeneratorResolvers = {

For what it’s worth, the following changes were sufficient in my case. I’m using Prisma with Yarn 3 (zero-installs / plug ‘n’ play) in a monorepo.

I started from @nishils’s suggestion (which worked) and simplified it as much as I could while still keeping everything functional:

1. Just install `prisma` and `@prisma/client` as per the docs
yarn add -D prisma
yarn add @prisma/client
2. Change the output directory to something outside of `node_modules`:
generator client {
  output = "../src/__generated__/prisma"
}
3. Use `pnpify` to be able to run the command-line script
yarn add @yarnpkg/pnpify
yarn pnpify prisma generate

this alone has resolved the identical problem i was experiencing.

thank you!

It would be really nice to have a fix for this - as I’ve mentioned, everything was working fine until 2.26.0, so this is really blocking us from upgrading prisma.

I can reproduce this. Looks like we are unable to resolve @prisma/client and we are trying to install it via npm(as there is not yarn.lock file the directory which we use to detect usage of yarn). NPM doesn’t support that workspace protocol and it throws the above error. Even if I stop installation of packages using PRISMA_GENERATE_SKIP_AUTOINSTALL=1, it can’t resolve the client.

Yarn 2/3 is not really supported (#1439) so I am not sure if this is actionable for us but I will still mark this as a confirmed bug.

how I keep using the prisma generate with our project (yarn 3, PnP, workspaces):

The overall gist is to “run the generation of PrismaClient in docker and get the generated file into your host fs and then expose them with a yarn workspace”

Generating the client files

Use a dockerfile to mount your schema and run the generation

# We are using the --platform to support alpine images on M1 for prisma
FROM --platform=linux/amd64 node-alpine

RUN npm i -g prisma@4.8.1
RUN npm i @prisma/client@4.8.1

# Copy relevant files
COPY . .

CMD ["prisma", "generate"]

And run this by mounting wherever you are putting your generated files:

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

using different names for the one inside the schema and the one when mounting the file system just to showcase what is what docker build -t prismagen . docker run -v $(PWD)/output:/app/generated prismagen

note: here I just used normal paths, you’d have to set up all to match your project structure

Exposing the generated files

assuming you have experience on how to use yarn workspaces

For, this is basically creating a new workspace and use it somewhere else

{
  "name": "your-project",
  "version": "1.0.0",
  "private": true,
  "workspaces": [
    "prisma"
  ],
  "scripts": {
  },
  "devDependencies": {
  },
  "packageManager": "yarn@3.3.0"
}

And then use it in your other workspaces, like:

 "dependencies": {
    "@your-project/prisma": "1.0.0",

And then import the stuff

import { PrismaClient } from "@your-project/prisma";