Typed ENV in Nx monorepo — workaround and asking for guidance #357
Replies: 2 comments 1 reply
-
|
I haven't done much exploration with Nx although it has been on my to-do list - so thanks for digging in! In our own monorepos, each app usually has its own Some of those sub packages could just import everything from the root, but at least it becomes explicit and gives you a chance to add more config if needed. (above assuming you have a root .env.schema and packages in I know Nx is a whole world with special ways of doing things so I'll have to dig in a little to test some things out. |
Beta Was this translation helpful? Give feedback.
-
|
Thanks man! I'll try adding .env.schema's to each app. Each one does have it's own set of env vars. I'll let you know how it goes. Saw you guys on the Syntax podcast the other day and thought, This is exactly what I need 😄 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi — I'm using varlock in an Nx monorepo and ran into an issue getting the typed
ENVfromvarlock/envto work across all apps and libs. Here's what was going on and what I did to fix it. I'd welcome any guidance on whether this is a reasonable approach or if there's a better way.My setup
tsconfig.base.json@generateTypesin.env.schemaso varlock generates anenv.d.tsat the repo root with the module augmentation forvarlock/env(e.g.TypedEnvSchema extends Readonly<CoercedEnvSchema>)The problem
That generated
env.d.tswasn't being picked up when building or type-checking individual apps/libs. So in code that didimport { ENV } from 'varlock/env', TypeScript was only seeing the package's own types (with an emptyTypedEnvSchema) and I got errors likeProperty 'APP_ENV' does not exist on type 'TypedEnvSchema'.From what I could tell, it came down to how Nx/TypeScript are set up: each project's tsconfig has its own
include/files, and those override the base rather than merging. So puttingenv.d.tsin the base config didn't pull it into the individual project builds. I also didn't want to add a triple-slash reference in every file that usesENV, or manually add the same include to every app and lib tsconfig.What I did to fix it
I ended up using a path mapping so that, for type-checking only,
varlock/envresolves to a small shim at the repo root:In
tsconfig.base.jsonI added the following tocompilerOptions.paths:"varlock/env": ["./varlock-env.d.ts"]
I added a shim file
varlock-env.d.tsat the repo root that:/// <reference path="./env.d.ts" />so the generated types (and the augmentation) are includedvarlock/envmodule with the same exports as the package (e.g.ENV,initVarlockEnv,redactSensitiveConfig, etc.) so the module declaration is complete when TypeScript resolves to this fileWith that, every app and lib that extends the base gets the typed
ENVautomatically. Runtime still uses the realvarlockpackage fromnode_modules; only type resolution goes through the shim.Where I'm unsure
env.d.tsinto the shim. If the package adds or changes exports in a future version, I'll need to update the shim to stay in sync. I'm not sure if there's a more maintainable way to do this.If you have any guidance—e.g. a recommended approach for monorepos, or a better way to wire in the generated types without maintaining a shim—I'd really appreciate it. Thanks for varlock and for any pointers you can share.
Beta Was this translation helpful? Give feedback.
All reactions