-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prisma loads .env, processes differently from RWJS #5657
Comments
Hey @joconor, amazing breakdown! 👏 It definitely feels like there's starting to be a bit too much cruft in the code that runs when importing some Redwood packages... as you've demonstrated, it's quite the rabbit hole. And it also just feels a bit too mutative to have packages start executing code as soon as they're imported. I investigated it a bit here where I traced an error with the At first as I was unsure how importing I'll try to find some time this week to dive into this more and consider the two suggestions you mentioned. |
@dthyresson sure, and I can probably prioritize it now that the we're refactoring the CLI—I can make it a part of that. |
I've been looking at this recently and while I think I'm starting to understand what's going on, some parts are still a little hard to put into focus 100%. But TL;DR I will fix this in steps so that RW always evaluates .env first. As to parsing multiline env vars, we can easily add support for that by toggling this option: https://github.com/motdotla/dotenv/tree/v14.3.2#multiline. I'm linking to v14.3.2 because that's the version of dotenv dotenv-defaults is pinned to unfortunately. dotenv is already on v16, so it'd be ideal if they upgraded soon than later. Maybe I can spur them on. For most commands, it's true that prisma evaluates .env first. But I'm not so sure that the execution order of it all is so simple as to render dotenv-defaults moot. I may be wrong cause there's a lot going on here and I'm not super familiar with prisma's internals, but I'll try to explain. It seems that the earliest env evaluation is in // node_modules/.prisma/client/index.js
// ...
const { warnEnvConflicts } = require('@prisma/client/runtime/index')
warnEnvConflicts({
rootEnvPath: config.relativeEnvPaths.rootEnvPath && path.resolve(dirname, config.relativeEnvPaths.rootEnvPath),
schemaEnvPath: config.relativeEnvPaths.schemaEnvPath && path.resolve(dirname, config.relativeEnvPaths.schemaEnvPath)
})
const PrismaClient = getPrismaClient(config)
exports.PrismaClient = PrismaClient
Object.assign(exports, Prisma) It's It evalutes .env again, just without checking for conflicts. And we don't instantiate When I turn on debug flags and step through code, I often see this: prisma:tryLoadEnv Environment variables loaded from /Users/dom/prjcts/rwprj/rwprj/.env +0ms
rw, loading env... # I added this for debugging
prisma:tryLoadEnv Environment variables loaded from /Users/dom/prjcts/rwprj/rwprj/.env +0ms
[dotenv][DEBUG] "SESSION_SECRET" is already defined in `process.env` and was NOT overwritten
[dotenv][DEBUG] "DATABASE_URL" is already defined in `process.env` and was NOT overwritten Prisma is evaluating .env twice, sandwiching redwood's evaluation. So it seems that defaults still get loaded for env vars that are undefined. It's certainly unclean that prisma goes first, ever, so I'll fix that. We definitely want this to be deterministic. I'm having a hard time getting the config option you mentioned to be And as to these suggestions
For full transparency, right now I don't see either happening just yet. You can already pass options to dotenv via |
@jtoar Thanks! I'll check it out in my environment. I remember it was a bit tricky to reproduce 😏 |
Those are the best kinds of issues 😅 |
Running
yarn rw dev
invokesconst rwProjectRoot = requireFromCli('./dist/lib/index.js').getPaths().base in packages/core/src/bins/redwood.ts
which invokes
import {
getPaths as getRedwoodPaths,
getConfig as getRedwoodConfig,
} from '@redwoodjs/internal' in packages/cli/src/lib/index.js
which invokes
export { generate } from './generate/generate' in packages/internal/src/index.ts
which invokes
import { generateGraphQLSchema } from ‘./graphqlSchema' in packages/internal/src/generate/generate.ts
which invokes
import { rootSchema } from '@redwoodjs/graphql-server' in packages/internal/src/generate/graphqlSchema.ts
which invokes
export * from './functions/graphql' in packages/graphql-server/src/index.ts
which invokes
import { RedwoodError } from '@redwoodjs/api' in packages/graphql-server/src/functions/graphql.ts
which invokes
export * from './validations/validations' in packages/api/src/index.ts
which invokes
import { PrismaClient } from '@prisma/client' in packages/api/src/validations/validations.ts
And causes Prisma to attempt to evaluate
.env
. Usually this is successful. When Prisma generates client code,.prisma/client/index.js
is generated with aconfig
object. Theconfig
hasrelativeEnvPaths.rootEnvPath
which normally points to the root of the RedwoodJS project, which is where it (usually) finds the.env
file. But under some circumstances, the generatedrelativeEnvPaths.rootEnvPath
may be null, in which case Prisma will not find and evaluate.env
Because Prisma is evaluating
.env
very early in the invocation ofyarn rw dev
, RedwoodJS's use ofdotenv-default
becomes a moot point. By default,dotenv-default
(anddotenv
) will not overwrite variables already present in the environment.Normally, all this is fine. But it can lead to a subtle and difficult to diagnose bug: In those cases where Prisma fails to find & evaluate .env, and RedwoodJS itself does the evaluation of .env, RedwoodJS doesn't (seem) to handle multiline environment variables correctly. Prisma is masking this failure of RedwoodJS's parsing of .env.
My specific case of RedwoodJS not handling a multiline env var is with Google API credentials. This is a multiline single-quoted string with embedded double-quotes. A multiline JSON string.
When Prisma fails to find and evaluate .env, and RedwoodJS does, only the first line of that multiline variable is read (i.e.,
CREDS='{
).Suggestion: Prisma .env should be kept separate from RedwoodJS .env.
Second suggestion: RedwoodJS should provide the ability to pass
options
todotenv
/dotenv-default
to allow control over how it parses multiline variables as well as other options available in that package.The text was updated successfully, but these errors were encountered: