Skip to content
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

feat: Introduces JSON type to non-public env variables #757

Merged
merged 6 commits into from
Sep 8, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions cli/plasmo/src/features/env/env-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,25 @@ function cascadeEnv(loadedEnvFiles: LoadedEnvFiles) {
try {
envFileSet.add(name)
const result = dotenvExpand({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found no real benefit to the side-effects introduced by dotenvExpand, since there is explicit process.env var assignment in the iteration of the values from the .env files. If I'm mistaken, let me know, but leaving it in also conflicts with the ability to introduce this feature since it implicitly hydrates process.env

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Gathering my thought) the main idea with dotenvExpand is to have this:

PASSWORD="s1mpl3"
DB_PASS="prefix-$PASSWORD"

And the reason we want that is to have the same behavior as nextjs and other frameworks with built-in env parsing.

but leaving it in also conflicts with the ability to introduce this feature since it implicitly hydrates process.env

Can we run the expansion at the end of this loop? (on the parsed object)?

Perhaps that might be best. I.e on line 72, we'd do:

return dotenvExpand.expand({ parsed })

That way, we can hydrate the key for the JSON value manually first, then expand once we know everything's in-place?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok, that explanation makes more sense. I'll play around with it a bit more and make sure that still works

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I think my latest commit resolves this, but maybe you have some specific use cases you can test?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superb - works for me! Tested on some variant with the dnr as well!

ignoreProcessEnv: true,
parsed: dotenv.parse(contents)
})

if (!!result.parsed) {
vLog(`Loaded env from ${name}`)
const resultData = result.parsed || {}

for (const envKey of Object.keys(resultData)) {
for (const [envKey, envValue] of Object.entries(resultData)) {
if (typeof parsed[envKey] === "undefined") {
parsed[envKey] = resultData[envKey]
try {
parsed[envKey] = maybeParseJSON(envValue)
} catch (ex) {
eLog(`Failed to parse JSON directive ${envKey} in ${name}:`, ex.message)
}

// Pass through internal env variables
if (envKey.startsWith(INTERNAL_ENV_PREFIX)) {
process.env[envKey] = resultData[envKey]
process.env[envKey] = envValue
}
}
}
Expand All @@ -77,6 +82,13 @@ function cascadeEnv(loadedEnvFiles: LoadedEnvFiles) {
return parsed
}

const JSON_DIRECTIVE_RE = /^\s*json\((.+)\)\s*$/si

function maybeParseJSON(value: string): any {
const match = value.match(JSON_DIRECTIVE_RE)
return match ? JSON.parse(match[1]) : value
}

export const getEnvFileNames = () => {
const nodeEnv = process.env.NODE_ENV
const flagMap = getFlagMap()
Expand Down