dependency-env
v0.1.1
Published
Loads environment variables that dependencies declared as exported in their package.json
Readme
dependency-env
Modularized Environment Variables.
Loads environment variables that dependencies declared as exported in their package.json
npm install --save dependency-envNOT PRODUCTION READY
Idea:
Bring the sandboxing model to environment variables.
If you add
dependency-envto yourdependencies, then you can evaldependencyEnvin any of your npmscripts, and it will ensure that your immediate dependencies (and only your immediate dependencies) can set environment variables that are set only for the remainder of that one script.
Inside your package.json:
"scripts": {
"doStuff": "eval $(dependencyEnv) && restOfCommandHere"
}Then on the command line you can do:
npm run-script doStuffNote that in these examples,
dependencyEnvitself is not a globally installed binary. When you depend ondependency-env, it makes sure thatdependencyEnvis in./node_modules/.bin/, whichnpmalways ensures is added to your path when for the duration ofrun-scripts. This is standardnpmbehavior that we're using here - we happen to be using it to be bootstrapping creating an environment that uses an (arguably) better model for constructingPATHs and any other env variable.
You might want to eval
eval $(./node_modules/.bin/dependencyEnv)directly in your own build scripts becausenpm run-scripthas a large overhead.
Conventions:
Any
package.jsonmay include an"exportedEnvVars"field which maps environment variables by their names to their respective variable configs.Each variable config should have a
"val"field.By default environment variables are scoped to the package they reside in. This means that the environment variable name must be prefixed to indicate the package it was exported from. We do this by placing
PACKAGE_NAME__at the beginning of each exported var from thepackage.jsonfor the package namedpackage-name(we replace hyphens with single underscores and then include a double underscore. For example, for a package namedmy-package, by default, environment variables must begin withMY_PACKAGE__, such asMY_PACKAGE__FOO, orMY_PACKAGE__BAR_BAR.Environment variables may declare that they are paths that should be absolute paths that are resolved relative to the location of the
package.jsonthey reside in. Set "resolveAsRelativePath": falseEnvironment variables may declare themselves global by including
"global": truein their configuration. For global variables, there is another optional field calledglobalCollisionBehaviorwhich determines how to resolve values when multiple packages set the same variable name. Options are"fail"(the default),"clobber", or"joinPath"(which will combine all the values from all package via:).See below for examples:
Examples of package.json fields:
"exportedEnvVars": {
"PATH": {
"val": "./src/_stage2",
"resolveAsRelativePath": true,
"global": true,
"globalCollisionBehavior": "joinPath"
}
},
"PACKAGE_NAME__SOME_VAR": {
"val": "foo",
"resolveAsRelativePath": false
},
"ANOTHER_GLOBALVAR": {
"val": "./lib/ocaml",
"resolveAsRelativePath": true,
"global": true,
"globalCollisionBehavior": "fail"
}
},Motivation:
npm's run-script has a great feature that will augment the PATH environment
variable to include /node_modules/.bin, only for the duration of the
run-script. This is great because it means changing of paths is scoped to a
particular duration, and in a predefined way that your dependencies get to
influence. But there are some shortcomings of npm run-script, and some ways
that we can take the idea further beyond simply augmenting a PATH, but
setting and augmenting arbitrary environment variables.
npmrun-scriptonly modifies thePATHand only for the sake of setting upbin. Dependencies might want to set other environment variables.npmrun-scriptis slow (often hundreds ofmsoverhead to startup). Let's not be slow. The examples here demonstrate usingdependency-envwithrun-scriptin this doc are merely for convenience.dependency-envprovides a way to not needrun-scriptto correctly wire up paths to binaries that your deps publish if your dependencies configurePATHusingdependency-env.- On windows,
npm'sbinfeatures might only be able to link entire directories, not specific binary files (on some network mount file systems). It's not likedependency-envworks on windows, but it could pretty easily and it's set up to do that since it doesn't rely on symlinks. npm'sbinfeature allows you to rely on binaries produced by your transitive dependencies. Those transitive dependencies might be implementation details of your immediate dependencies, and they're likely to change and break you.dependency-envenforces that you've declared pacakges as dependencies in order for those dependencies to contribute to your scripts'dependency-envenvironment.npm'sbinfeature requires that you list the binaries to expose, before yourpostinstallscript even runs. Furthermore, those binaries need to exist before thepostinstallis executed. That's not good for compiled packages becausepostinstallis the thing that will generate those binaries.
