Is there a way in SST Function to have it BAKE in ...
# help
d
Is there a way in SST Function to have it BAKE in environment vars? rather than passing them in as Function.environment ? Lambda@Edge does not support environment vars so it would be cool if there was an option to bake them in at build-time?
t
This is sort of what we do with StaticSite, basically do a find replace once everything is deployed
Are the variables you want to bake in referencing other resources created by sst?
Eg an sst.Api or a queue
d
yes…. but should this not be possible just with the native Function esbuild script?
no, for this right now its just baking in envs from the build systems’ envs
t
Yeah I was asking because if all the values are available you can do this with a dynamic require
Copy code
const Config = require(process.env.ENV_CONFIG)
esbuild should bundle those inline
that can point to a file that exports an object
{ OPT1: "Hello"}
Another option is to just bundle all the configs for all environments and at runtime do
Config[my_env].OPT1
d
Guess I didn’t need that then 🙂
c
Copy code
const Config = require(process.env.ENV_CONFIG)
This line is throwing a few typescript issues @thdxr
Require statement not part of import statement.eslint@typescript-eslint/no-var-requires
d
Copy code
// eslint-disable-line no-eval
If you put 
/* eslint-disable no-eval */
 before any code in a 
.js
 file, that will disable the 
no-eval
 rule for the entire file.
t
I haven't actually tested using
require
like that with esbuild so it might not work
d
yea, @thdxr, doesn’t seem to work. It compiles, but we see
process.env
in the bundle output.
Perhaps adding
define
property to the build props? https://github.com/evanw/esbuild/issues/438#issuecomment-705120203
t
Ah I think we do support custom esbuild config
d
@thdxr is that an issue though…. with it overriding any defaults you guys have in place now? perhaps some kinda plugin? https://github.com/rw3iss/esbuild-envfile-plugin
t
I think we merge the configs with our standard
d
ah … cool
t
I haven't used esbuild plugins yet so I'm not familiar off the top of my head
c
Copy code
Error: Cannot configure the "define" option in "/esbuild.js". Only the "plugins" option is currently supported.
Looks like there is a check to prevent any customization of the esbuild config beyond plugins
f
This approach only works for static value right?
d
yes?
f
It won’t work if you want to set values that aren’t available at build time, ie.
Copy code
TABLE_NAME: table.tableName
d
correct
not for CDK resource values…. but it should work for things like
this.stackName
no?
f
Right. There’s a trick where you use CloudFront origin headers to pass “environment variables” to edge functions https://stackoverflow.com/a/58101487/7667989
I was thinking to bake it into SST
d
hmmm…. ya… I remember that as well.
f
table.tableName
should work in this case
d
hmmm… maybe this is cleaner for now…. is there any limits to CF headers?
f
oh good call
The maximum length of a request, including the path, the query string (if any), and headers, is 20,480 bytes
As a reference, Lambda env var limit is 4kb
d
that seems like alot
20,480 chars = 20,480 bytes I think?
f
yeah 20kb
d
unfortunately the headers method wont work for us because our distro is in another stack that our lambda@edge. 😄
@Frank if your cool with it, I’m going to see if I can update
Function
here to allow for inline config? Similar to what you did on line 283.
that sound like it would work? then allow for
esbuildConfig
to be an object OR a string.
Being able to define esbuildConfig inline also work, but we still want some restrictions on what they can override.
SST relies on configs like
metafile
etc
d
but if you allow for a config path …. why not also allow for inline config?
f
on the phone be back in 30min 🙂
back, yeah inline config works! If it only allowed
plugins
and
define
, would it work for you guys?
d
yup
almost there now with PR
f
Man u guys move fast.. yeah I will cut a release with it tonite
c
currently we are just doing what was already there (only allowing
plugins
)
but if you think
defines
is okay that would probably be good to have too
d
@Frank running into an issue between
nodeBuilder.ts
esbuild.js
….. we’re allowing esbuildConfig to be a string or a type that allows for
plugins: [Plugin]
which is fine for nodeBuilder but we are base64 encoding it to be sent to
esbuild.js
which you guys are already decoding for
defaultConfigValue
. We’d do the same thing for customConfig but at that point its either a Base64encoded string or a string path. So all I could think of is to again test for
!fs.existsSync(customConfig)
and if YES then its a string path and if NO then
Buffer.from
that or @Camilo Bravo was thinking to add a
--inline-config
flag to
esbuild.js
and assume its a base64 string of flag exists
f
This just reminded me why we didn’t take inline esbuild config, it’s b/c
plugins
isn’t serializable right? ie.
plugin
is an import right?
Copy code
esbuildConfig: {
  plugins: [plugin]
}
Sorry I was confused earlier.
d
is that the case? I’m not sure, I was hoping it would somehow just work 😛
plugin could indeed be imported about yes
does that mean it would not work? Guess I’m not sure why that would make it not serializable ?
f
Yeah, 2 reasons: 1. a plugin contain callback functions 2.
sst start
also needs to run esbuild to build the functions, if defined inline,
sst start
won’t be able to figure out what to import.
d
hmmm. doh… I guess PlanB is just allow for Function.bundle to set
define
?
Gonna put a pin in this for the night. Dinner calls. 🙂 Let us know what you think of define option though.
f
Yup. Let’s allow the custom config to accept both
define
and
plugins
. Does that work?
t
Maybe you're too far along but a dumb work around is writing the env vars to a file in your sst code which is referenced by your js code
d
@thdxr Ya, that only works for static values but would not work for
this.stackName
which I think should be avail to be passed into
define
?
t
You can write that to a file inside your stack
pseudocode
Copy code
fs.write("src/handler/config.js", JSON.stringify({ stack: this.stackname }))
d
Ya I can see it working but a bit wonky. Also for static values that already come from .env this would be just one more file. Be nice to just have all statics in .env
@Frank how should we go about adding define support? If we add it to the external config file it still doesn’t let us pass in things like
this.stackName
. Unless we extend FunctionBundleNodejsProps to allow for
define
?
f
@Dan Van Brunt there’s a recent PR for allowing the
keepNames
esbuild config. I was thinking we can add
define
to the allowed config similarly https://github.com/serverless-stack/serverless-stack/pull/807/files
d
@Frank but doesn’t that mean that we have to use an external (not inline)
esbuildConfig
?
If so, then it would not allow us to pass in
this.stackName
f
hmm i see.. I was under the impression that you were going to use the
esbuild-envfile-plugin
, and plugins had to be defined in external file.
d
well… that would take care of 1of2 cases
we store all all statics in envs but we also need to pass in things like
this.stack
which is why we went down the path to try and allow for inline config.
f
Right.. just to sum it up, you need to configure both the
define
and
plugins
esbuild config. And we are stuck right now b/c •
define
has to be configured inline to access `this.stackName`; • but
plugins
has to be configured externally That sounds right?
Let me know if I’m understanding this correctly, and then I’m going to chat with @thdxr and @Jay quickly about it 😁
c
yes I believe that is correct. Let me just ask Dan real quick!
d
@Frank @Camilo Bravo close actually. We don’t even need plugins IF we can have access to define, as it would allow us to do what we’re using a plugin to do.
f
We settled on this https://github.com/serverless-stack/serverless-stack/issues/850 In short, you can do this:
Copy code
bundling: {
  esbuildConfig: {
    define: ...,
    keepNames: ...,
    plugins: "path/to/esbuild.js"
  }
}
You can pass in
define
inline, and
plugins
through an external file.
Can you confirm this works for you?
c
yes that should work because we will be able to define all derived variables using that define which is what we were using a plugin for previously
@Dan Van Brunt confirm?
f
Hey @Camilo Bravo @Dan Van Brunt in v0.34.7, you can now configure
define
inline like this:
Copy code
bundle: {
    esbuildConfig: {
      define: { … },
    },
  },
c
Thank you for moving so quickly on this! Much appreciated