Open Ernxst opened 2 months ago
We can't generate types for environment variables because they are not globally unique - they're scoped to the specific target they're attached to.
it's a bit challenging to try and collect all the environment variables from everywhere to produce a unique list of variables that may be available
a work around is to manually define them the same way sst-env.d.ts defines them
That's fair, then again you can access a resource on the type level even if it's not scoped to the target you're currently in and it will throw at runtime. I guess the same can be true here, but I agree it only really works if you're using the same env vars in all your functions (which I currently am).
this might not be what you really want but you could do new sst.Secret("Name", value)
and link that to all your functions if you want the typesafety
The secrets approach works until two functions need the same env var but with different values (I have a sentry helper function which grabs the dsn from the env instead of being passed as an argument). I was using define
in the esbuild config as build-time vars, but I also needed to do the same when bundling the workers for testing so defining it in the sst config seemed best. Given my use-case, the following works well since all my workers will need the same env vars:
/// <reference path="./../../sst-env.d.ts" />
declare module "sst" {
export interface Resource {
SentryRelease: string;
SentryDsn: string;
AppName: string;
FunctionOrigin: string;
}
}
export type {};
Just had a play around and have come up with a solutio to achieve better scoping of env vars in a monorepo setup. My setup is an infra
package with the following package.json exports:
"exports": {
".": "./src/index.d.ts",
"./env/cloudflare": "./src/env/cloudflare.d.ts",
"./env/sentry": "./src/env/sentry.d.ts",
},
My ./src/index.d.ts
is simply:
/// <reference path="./../../sst-env.d.ts" />
declare module "sst" {
export interface Resource {}
}
export type {};
Which just gives me the original generated types, then in src/env/sentry.d.ts
, I only include sentry specific env vars:
/// <reference path="./../../sst-env.d.ts" />
declare module "sst" {
export interface Resource {
SentryRelease: string;
SentryDsn: string;
}
}
export type {};
This way, in packages that have a target which will use these env vars, you only need to include the specific export in your tsconfig:
{
"compilerOptions": {
"types": [
"@repo/infra",
"@repo/infra/env/sentry"
]
},
}
This way, you can scope env vars only to where they will be defined. Keep in mind, this approach falls apart if you have multiple targets in the same package who do not share all env vars. I think I prefer this approach rather than requiring sst to generate them
Given that environment variables are linked to
Resource
(v0.1.1
) - I can access them in the app - it also makes sense they should be included in the generated types.The above config produces the following
sst-env.d.ts
But I can still access
Resource.WorkerName
in my worker as well as it being listed as a variable in the cloudflare dashboard:I should add, I'm not sure how the types should be generated if I reference the same variable in multiple functions