graphql-nexus / nexus-plugin-prisma

Deprecated
MIT License
828 stars 118 forks source link

Cannot initialize Prisma client with custom path, shows error in dmmf/utils.js #835

Open lauriskuznecovs opened 4 years ago

lauriskuznecovs commented 4 years ago

INTRODUCTION

Everything was working in "nexus-plugin-prisma": "0.16.1" and problem appeared in all next versions.

ERROR

/home/user/projects/node_modules/nexus-plugin-prisma/dist/schema/dmmf/utils.js:14
        throw new Error(`\
        ^

Error: You most likely forgot to initialize the Prisma Client. Please run `prisma generate` and try to run it again.
If that does not solve your problem, please open an issue.
    at Object.exports.getPrismaClientDmmf (/home/user/projects/node_modules/nexus-plugin-prisma/dist/schema/dmmf/utils.js:14:15)
    at Object.exports.getTransformedDmmf (/home/user/projects/node_modules/nexus-plugin-prisma/dist/schema/dmmf/transformer.js:7:118)
    at new SchemaBuilder (/home/user/projects/node_modules/nexus-plugin-prisma/dist/schema/builder.js:126:24)
    at Object.build (/home/user/projects/node_modules/nexus-plugin-prisma/dist/schema/builder.js:67:21)
    at Object.onInstall (/home/user/projects/node_modules/nexus-plugin-prisma/dist/schema/index.js:47:78)
    at /home/user/projects/node_modules/@nexus/schema/dist/builder.js:299:52
    at Array.forEach (<anonymous>)
    at SchemaBuilder.beforeWalkTypes (/home/user/projects/node_modules/@nexus/schema/dist/builder.js:293:22)
    at SchemaBuilder.getFinalTypeMap (/home/user/projects/node_modules/@nexus/schema/dist/builder.js:375:14)
    at makeSchemaInternal (/home/user/projects/node_modules/@nexus/schema/dist/builder.js:980:94)
[nodemon] app crashed - waiting for file changes before starting...

ENVIRONMENT

OS: 18.04.5 LTS (Bionic Beaver)" NPM: 6.14.8 NODE: v12.18.3

COMMENTS

I tried to debug that faulty file - node_modules/nexus-plugin-prisma/dist/schema/dmmf/utils.js by checking whats in packagePath. I think it holds wrong path to Prisma client. It is @prisma/client even I am using custom path, which is outside node_modules.

REPRODUCTION

Commands to run:

npm i
npm run build
npm run dev

package.json

{
  "name": "masked",
  "author": "masked",
  "engines": {
    "node": ">=10.13"
  },
  "main": "server.js",
  "scripts": {
    "dev": "nodemon --watch src/server.js src/server.js",
    "start": "npm run prisma:migrate:up && npm run prisma:data:seed && NODE_ENV=production node src/server.js",
    "build": "npm run prisma:generate",
    "prisma:generate": "prisma generate",
    "prisma:introspect": "prisma introspect",
    "prisma:migrate:save": "prisma migrate save --experimental",
    "prisma:migrate:up": "prisma migrate up --experimental",
    "prisma:data:seed": "node prisma/seed.js",
    "eslint": "./node_modules/.bin/eslint ./"
  },
  "dependencies": {
    "@nexus/schema": "^0.15.0",
    "apollo-server": "^2.17.0",
    "dotenv-flow": "^3.2.0",
    "graphql": "^15.3.0",
    "jsonwebtoken": "^8.5.1",
    "nexus-plugin-prisma": "^0.18.2"
  },
  "devDependencies": {
    "babel-eslint": "^10.1.0",
    "eslint": "^7.8.1",
    "eslint-config-airbnb": "^18.2.0",
    "eslint-config-airbnb-base": "^14.2.0",
    "eslint-config-prettier": "^6.11.0",
    "eslint-plugin-import": "^2.22.0",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-prettier": "^3.1.4",
    "eslint-plugin-sonarjs": "^0.5.0",
    "nodemon": "^2.0.4",
    "prettier": "^2.1.1"
  },
  "standard": {
    "parser": "babel-eslint"
  }
}

prisma/prisma.schema

generator client {
  provider      = "prisma-client-js"
  output        = "./src/generated/client"
  binaryTargets = ["native", "linux-musl"]
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

///..... HERE are some models

src/server.js

const dotenvFlow = require('dotenv-flow')

// Try to load .env files (for env local only)
dotenvFlow.load([
  './.env',
  './prisma/.env'
])

const { ApolloServer } = require('apollo-server')
const { schema } = require('./schema')
const { createContext } = require('./context')

const port = parseInt(process.env.PORT, 10) || 4000
const dev = process.env.NODE_ENV !== 'production'
const path = '/api/graphql'

new ApolloServer({
  schema,
  context: createContext,
  introspection: true,
  playground: true,
  cors: {
    origin: '*',
    credentials: true,
  },
  formatError(error) {
    if (dev) {
      console.log(error)
    }
    return error
  },
}).listen({ port }, () =>
  console.log(`🚀 Server ready at: http://localhost:${port}${path}`),
)

src/context.js

const { PrismaClient } = require('../prisma/src/generated/client')

const prisma = new PrismaClient()

const createContext = (ctx) => {
  return {
    ...ctx,
    prisma,
  }
}

module.exports = { createContext }

src/schema/index.js

const { nexusSchemaPrisma } = require('nexus-plugin-prisma/schema')
const { makeSchema } = require('@nexus/schema')
const { PrismaClient } = require('../../prisma/src/generated/client')

const Query = require('./Query')
const Mutation = require('./Mutation')
const User = require('./User')

const nexusPrisma = nexusSchemaPrisma({
  experimentalCRUD: true,
})

const index = makeSchema({
  types: [
    Query,
    Mutation,
    User,
  ],
  plugins: [nexusPrisma],
  outputs: {
    schema: __dirname + '/../../schema.graphql',
    typegen: __dirname + '/../generated/nexus.ts',
  },
  typegenAutoConfig: {
    contextType: 'Context.Context',
    sources: [
      {
        source: '.prisma/client',
        alias: 'prisma',
      },
      {
        source: require.resolve('../context'),
        alias: 'Context',
      },
    ],
  },
})

module.exports = { schema: index }
betofigueiredo commented 4 years ago

@lauriskuznecovs I had the same problem. For me was a conflict between my @prisma/client dependency with the nexus-plugin-prisma dependency.

I was using in my project:

"@prisma/cli": "2.7.1"
"@prisma/client": "2.7.1"

and nexus-plugin-prisma was using:

"@prisma/cli": "2.7.0"
"@prisma/client": "2.7.0"

I updated my package.json to use 2.7.0 and got it working.

A possible solution for you

I see that you are using:

"@nexus/schema": "^0.15.0"
"nexus-plugin-prisma": "^0.18.2"

try to change your nexus-plugin-prisma to 0.19.0. I'm using this configuration and it's working.

lauriskuznecovs commented 3 years ago

@lauriskuznecovs I had the same problem. For me was a conflict between my @prisma/client dependency with the nexus-plugin-prisma dependency.

I was using in my project:

"@prisma/cli": "2.7.1"
"@prisma/client": "2.7.1"

and nexus-plugin-prisma was using:

"@prisma/cli": "2.7.0"
"@prisma/client": "2.7.0"

I updated my package.json to use 2.7.0 and got it working.

A possible solution for you

I see that you are using:

"@nexus/schema": "^0.15.0"
"nexus-plugin-prisma": "^0.18.2"

try to change your nexus-plugin-prisma to 0.19.0. I'm using this configuration and it's working.

It did not helped. I got same error. Do you also have custom path for Prisma client?

If tried to debug file in which as an error:

/node_modules/nexus-plugin-prisma/dist/schema/dmmf/utils.js

exports.getPrismaClientDmmf = (packagePath) => { console.log(packagePath) // Returns "@prisma/client"
    let dmmf = undefined;
    try { console.log(require(packagePath).dmmf)  // Returns "undefined"
        dmmf = require(packagePath).dmmf;
    }
    catch (error) {
        throw new Error(`Failed to import prisma client package at ${packagePath}. The following error occured while trying:
        ${error.stack}`);
    }
    if (!dmmf) {
        throw new Error(`\
You most likely forgot to initialize the Prisma Client. Please run \`prisma generate\` and try to run it again.
If that does not solve your problem, please open an issue.`);
    }
    return dmmf;
};
betofigueiredo commented 3 years ago

@lauriskuznecovs I'm not using a custom path, just the normal import:

const { PrismaClient } = require('@prisma/client');

And the 'nexus-plugin-prisma' is handling the '@prisma/client' dependency for me. I don't have it in my package.json now.

lauriskuznecovs commented 3 years ago

As I mentioned above I am using custom path for client.

generator client {
  provider      = "prisma-client-js"
  output        = "./src/generated/client" <------------ here
  binaryTargets = ["native", "linux-musl"]
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

///..... HERE are some models

That is described in Prisma docs, so there should not be a problem with custom path. https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/generating-prisma-client#specifying-a-custom-output-path

betofigueiredo commented 3 years ago

It shouldn't be a problem, but maybe nexus is handling some prisma-client config as well and it's conflicting.

In my file the generator is only setting the provider:

generator client {
    provider = "prisma-client-js"
}
fullStackDataSolutions commented 3 years ago

I'm using a custom location for storing the client. The client works but when I try to add it to nexus I get the same error.

Here's the versions I'm using:

"nexus-plugin-prisma": "^0.22.0" "@prisma/cli": "^2.9.0" "@prisma/client": "^2.9.0"

I suspect the error is somewhere in this code:

plugins: [
        nexusSchemaPrisma()
    ],
    typegenAutoConfig: {
        contextType: 'Context.Context',
        sources: [
            {
                source: require.resolve(
                    '../generated/prisma/saved_search/client'
                ),
                alias: 'savedSearch'
            },
            {
                source: require.resolve('../utils/types'),
                alias: 'Context'
            }
        ]
    }
lauriskuznecovs commented 3 years ago

I can confirm this is still an issue with current latest versions.

"dependencies": {
    "@prisma/client": "^2.13.1",
    "apollo-server": "^2.17.0",
    "dotenv-flow": "^3.2.0",
    "graphql": "^15.4.0",
    "nexus": "^1.0.0",
    "nexus-plugin-prisma": "^0.27.0"
  },
david-on-github commented 3 years ago

Hello @lauriskuznecovs,

This confused me also. The client path should be set in the nexusPrisma config inputs.prismaClient property. https://nexusjs.org/docs/plugins/prisma/overview#configuration

And reference the type definition file in the sourceTypes.

export const PRISMA_PATH = path.resolve(__dirname, '../../generated/prisma2');

const nexusPrismaConfig: NexusPrismaOptions = {
  inputs: { prismaClient: PRISMA_PATH }
};

export const schema = makeSchema({
  types: types,
  plugins: [nexusPrisma(nexusPrismaConfig)],
  ...
  sourceTypes: {
    modules: [
      {
        module: `${PRISMA_PATH}/index.d.ts`,
        alias: 'prisma'
      }
    ]
  }
});
Hugoo commented 3 years ago

I'm also having this issue when trying to deploy my app to Google App Engine. Everything works locally, but the remote deploy fails (the GAE node install mechanism is a bit obscure tho). I'm not using any custom path.

image

I'm trying to use Prisma in a monorepo with 2 services. The prisma folder is a symlink to ../shared/prisma.