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

Astro Env #894

Merged
merged 49 commits into from
Aug 19, 2024
Merged

Astro Env #894

merged 49 commits into from
Aug 19, 2024

Conversation

florian-lefebvre
Copy link
Member

Summary

astro:env - Improve DX and security around environment variables in Astro

Links

proposals/0046-astro-env.md Outdated Show resolved Hide resolved
proposals/0046-astro-env.md Outdated Show resolved Hide resolved
proposals/0046-astro-env.md Outdated Show resolved Hide resolved
proposals/0046-astro-env.md Outdated Show resolved Hide resolved
proposals/0046-astro-env.md Outdated Show resolved Hide resolved
proposals/0046-astro-env.md Outdated Show resolved Hide resolved
proposals/0046-astro-env.md Outdated Show resolved Hide resolved
proposals/0046-astro-env.md Outdated Show resolved Hide resolved
Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
@theoephraim
Copy link

In doing a larger review of other tools, it looks like sveltkit is thinking along very similar lines to what I have proposed above - see https://kit.svelte.dev/docs/modules#$env-dynamic-private
They let you import from 4 different virtual modules for the combos of public/private and static/dynamic

They use the prefix only as the marker of public/private, and the import method to help control static/dynamic behaviour.

@florian-lefebvre
Copy link
Member Author

Yep we looked at it during the stage 2 rfc but thanks for bringing it again!

@theoephraim
Copy link

Maybe if this is something y'all have already thought through, and maybe I'm overestimating it's importance, but I think you want to make sure users can still benefit from build-time injection and the constant folding / tree-shaking that it enables.

I think anything that looks like import { SOME_VAR } from 'astro:env' is going to make this very difficult.

On the other hand, using anything like import AstroEnv from 'astro:env' and then using AstroEnv.SOME_VAR makes it fairly trivial to add extra entries in the vite's define configuration. Of course you probably won't want to automatically enable this for all env items have some rules about which ones can be replaced, based on the schema, or (less optimally) on how it was imported/used.

@florian-lefebvre
Copy link
Member Author

Just to make sure I understand correctly, if I have this:

import { FOO } from 'astro:env/client'

if (FOO) {
	// do something
}

and FOO is false, you expect the whole thing to be removed on build.

I have to admit I'm not familiar enough with vite to know if it currently works, we're doing some pretty simple stuff for public variables so maybe it works already? I think @bluwy may know

@bluwy
Copy link
Member

bluwy commented Jun 10, 2024

Using import { FOO }, import * as AstroEnv, or import AstroEnv (if we support this) will all work with Rollup's treeshaking, so I don't think we have to change the syntax to accommodate it.

@theoephraim
Copy link

Ah - right of course because it's not rewritten by vite/rollups define... However this does also mean it needs to be an actual constant and not some proxy or function call. Thanks for confirming!

@narration-sd
Copy link

narration-sd commented Jun 18, 2024

Very glad to hear about this, as I think it will allow me to unwind all the complexity made when Astro 4 summarily removed ability for import.met.env in astro.config, for a package adding Sanity live Presentation editing on Astro.

I have no idea why the discussion I raised a the time didn't inform me about this -- you 'd have gotten early feedback, and I would have had a great deal less trouble.

The trouble came because of the ferocious, non-traceable deployment-only errors which occur if you allow the client to one way or another access any code which had touched what looked innocent, the server-side variables when produced by the recommended method. This confuses Vite, in very bad ways.

@narration-sd
Copy link

I'd like to ask -- when do you foresee this becoming a more-than-experimental feature (months, etc.)??

@florian-lefebvre
Copy link
Member Author

This feature should go out of experimental in a few minors, hard to tell at this time

@florian-lefebvre
Copy link
Member Author

New related RFC #956

@florian-lefebvre
Copy link
Member Author

New related RFC #957

@braden-w
Copy link

braden-w commented Jul 27, 2024

@florian-lefebvre Thank you for your work on this RFC! It's exciting to see Astro moving towards improved environment variable handling. I have a few questions that I hope can contribute to the discussion:

  1. Cross-context Usage:

The current proposal seems to focus primarily on using environment variables within the Astro application context. However, in many projects, we might need to access these variables in non-Astro contexts as well (e.g., standalone scripts where we still want database connections, debugging astro actions in isolation, etc.). Is there a way we could extend this proposal to allow for seamless use of environment variables across all contexts?

  1. Comparison with T3 env:

The T3 env package offers some nice features like runtime validation, type inference, and the ability to use environment variables outside of the main application. How does this proposal compare to T3 env in terms of features and ergonomics? After using the RFC, I found the ergonomics feel slightly more awkward, especially since I was unable to use it in my scripts due to point 1. If we're going to recommend Astro users to use Astro env, what benefits does it provide that aren't provided in using the alternatives?

This might instead be going into the direction of a standalone module that can be imported in both Astro and non-Astro contexts. It might look something like this:

import { createEnv } from 'astro/env';

export const env = createEnv({
  clientPrefix: 'PUBLIC_',
  server: {
    DATABASE_URL: z.string().url(),
    API_KEY: z.string().min(1),
  },
  client: {
    PUBLIC_API_URL: z.string().url(),
  },
  runtimeEnv: process.env,
});

Where env is imported as a typesafe object whenever we need to use it.

This approach would allow for consistent environment variable usage across all parts of a project, including scripts and other non-Astro files.

@florian-lefebvre
Copy link
Member Author

Hey @braden-w thanks for bringing this up! It's out of scope of this RFC but we're not against it! That's something often asked and source of confusion so I think that's something we could tackle. Would you mind creating a new roadmap discussion for this with as much info/context as you can? Then we can share it to gather more feedback and usecases

@hxjo
Copy link

hxjo commented Aug 7, 2024

Hello there,

First of all, thank you very much for your work, I love Astro and the people behind it.

I have a question regarding environment variables, why are we currently only reading those passed from .env.* and with the CLI command ?
It means all environment variables present on the machine are ignored ; this is very impractical when those are handled by, for example, kubernetes and injected in the pod ; which makes me rely on process.env for now.

While I understand exposing the whole process.env is not desirable, maybe something similar to Vite with a prefix might do the trick ?

Again, thanks a lot for your work, and I'm eager to try this new api.
Have a great day

@florian-lefebvre
Copy link
Member Author

There are a few scenarios:

  • In dev and build, we use loadEnv from vite and merge its result inside process.env so I don't see why those global k8s vars would not be available
  • In SSR, it uses whatever thing the adapter specified, eg. process.env for node, Deno.env.get() for deno etc
  • You can access this implementation directly by calling getSecret('KEY'). It's literally an interface for the point above

If you think that's a bug, feel free to open an issue on the main repo and ping me! Happy to look into this

@hxjo
Copy link

hxjo commented Aug 8, 2024

  • In SSR, it uses whatever thing the adapter specified, eg. process.env for node, Deno.env.get() for deno etc

Ooh, that makes sense. I'm in SSR with node which explains the need to use process.env then.

  • You can access this implementation directly by calling getSecret('KEY'). It's literally an interface for the point above

I'll try that today then !

Does not seem like a bug at all, just a misunderstanding from me.
Thanks for the clarification!

@florian-lefebvre
Copy link
Member Author

This is a call for consensus, and we aim to close the RFC in the next three days. Let us know if you have any important concerns.

@florian-lefebvre
Copy link
Member Author

The final comment period has ended and this RFC is accepted. The feature will be unflagged in Astro 5.0.

@florian-lefebvre florian-lefebvre merged commit 32a8e17 into main Aug 19, 2024
@florian-lefebvre florian-lefebvre deleted the feat/astro-env-rfc branch August 19, 2024 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.