Skip to content
This repository has been archived by the owner on Jun 7, 2024. It is now read-only.

feat: rfc api #4

Closed
wants to merge 20 commits into from
Closed

feat: rfc api #4

wants to merge 20 commits into from

Conversation

florian-lefebvre
Copy link
Owner

@florian-lefebvre florian-lefebvre commented Feb 22, 2024

@florian-lefebvre florian-lefebvre marked this pull request as ready for review March 10, 2024 15:26
@florian-lefebvre florian-lefebvre changed the title feat: work on rfc api feat: rfc api Mar 10, 2024
Comment on lines +98 to +103
Those variables can be accessed at runtime (if your host supports it). They can be accessed through `locals`.

```ts
// src/pages/index.astro
Astro.locals.env.MY_DYNAMIC_VAR
```
Copy link

Choose a reason for hiding this comment

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

Dynamic variables would be accessible through a virtual module as well. I know @ lilnasy suggested using something like Astro.env.KEY but I think the issue is that it makes it hard to use env variables outside of .astro files and endpoints
-- You 😄

Same argument applies to Astro.locals.env right?

I know we shouldn't use virtual imports with the astro: prefix, but is astro:env used currently? If it isn't and this is to implement the API as it would be in Astro maybe it should be imported from there.

But if we want to be safe it could be from astro-env:values or #astro-env;

Copy link
Owner Author

Choose a reason for hiding this comment

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

Well I initially wanted a virtual module for this but env relies on the current requests with some adapters like cloudflare so locals (in userland but Astro.env in core) looks like the best place for it. This is based on a convo on Discord with arsh and alex

Comment on lines +45 to +48
virtualImport: readFileSync(
resolve(`./stubs/dynamic-env/${runtime}.mjs`),
"utf-8",
),
Copy link

Choose a reason for hiding this comment

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

This seems problematic for projects with mixed output.

Values read from the runtime on pre-rendered pages will run on Node, not the adapter's runtime.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ah that's interesting! Actually this is a workaround but that will eventually be part of the adapter api. Does it change anything tho? I don't think so. @alexanderniebuhr I'm interested in your thoughts on this

Choose a reason for hiding this comment

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

In theory I don't think it matters. The only thing which is important, IIUC, is that the variable is set and available in both (node & other runtime) and be named the same.

The only difference would be how the var is resolved, correct?
The only question is, does it work for runtimes without fs if you use readFileSync here?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Here the usage of fs doesn't matter because it's inside the integration. In the core implementation, this piece of code will not exist anyway because adapters will provide the implementation as an entrypoint or something

Copy link

Choose a reason for hiding this comment

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

That is not the problematic part. The file will be loaded by Node since this run at build time. But if the project tries to read a dynamic variable on a prerendered page it will break.

When deploying to Cloudflare, for example, it will use the code that works on SSR on Cloudflare, but that code doesn't run on Node.

It will break on the route using it, not here

Copy link
Owner Author

Choose a reason for hiding this comment

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

Alright so the logic would be

  • On build/prerender, use node env resolution
  • In SSR, use the adapter logic if defined, otherwise fallback to node env resolution
    Is there a way to know what is the current case and use that somehow?

Copy link

Choose a reason for hiding this comment

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

Is there a way to know what is the current case and use that somehow?

There is no easy way for it currently. You can do a runtime check of what runtime are you on between Node and the adapter's runtime by checking typeof process. This allows detecting whether it is running on Node in those cases.

Choose a reason for hiding this comment

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

checking typeof process

That wouldn't work in all cases.. I guess the safer way would be to use Astro's config to see which adapter is set 🤔

});
},
"astro:server:setup": ({ server }) => {
// TODO: do not kill the terminal, show in the error overlay
Copy link

Choose a reason for hiding this comment

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

I did a quick read over that logic in core, and it doesn't seem like an integration has access to it as it is today.

Copy link
Owner Author

Choose a reason for hiding this comment

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

thanks! That was suggested by erika or nate, i'll just throw then

Comment on lines +8 to +12
get(_target, prop, _receiver) {
if (typeof prop === "string") {
return getEnvVariable(prop, { locals });
}
},
Copy link

Choose a reason for hiding this comment

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

Writing to this proxy will be silently ignored.

> p = new Proxy({}, {get: (_, prop) => prop})
Proxy [ {}, { get: [Function: get] } ]
> p.foo
'foo'
> p.foo = 123
123
> p.foo
'foo'

I think it should either be a true write, allowing envs to be modified or it should throw an error.

Suggested change
get(_target, prop, _receiver) {
if (typeof prop === "string") {
return getEnvVariable(prop, { locals });
}
},
get(target, prop, _receiver) {
if (typeof prop === "string") {
return target[prop] ?? getEnvVariable(prop, { locals });
}
},

Copy link
Owner Author

Choose a reason for hiding this comment

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

I'm not familiar with proxies at all tbh! Any improvement is more than welcome

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants