Comparing version 0.2.0 to 0.4.0
158
index.js
'use strict'; | ||
module.exports = function(options) { | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var ini = require('ini'); | ||
var through2 = require('through2'); | ||
var hasOwn = Object.prototype.hasOwnProperty; | ||
var exts = require.extensions; | ||
function extend(dest, src) { | ||
for (var prop in src) { | ||
if (hasOwn.call(src, prop)) { | ||
dest[prop] = src[prop]; | ||
} | ||
} | ||
} | ||
// Custom types...it should be easy to | ||
var types = { | ||
'.ini': ini.parse, | ||
'.json': JSON.parse, | ||
}; | ||
// Copied from Node.js core. | ||
function stripBOM(content) { | ||
// Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) | ||
// because the buffer-to-string conversion in `fs.readFileSync()` | ||
// translates it to FEFF, the UTF-16 BOM. | ||
if (content.charCodeAt(0) === 0xFEFF) { | ||
content = content.slice(1); | ||
} | ||
return content; | ||
} | ||
function bind(handler) { | ||
return function (file) { | ||
try { | ||
return handler(stripBOM(fs.readFileSync(file, 'utf8'))); | ||
} catch (e) { | ||
e.message = file + ': ' + e.message; | ||
throw e; | ||
} | ||
}; | ||
} | ||
module.exports = env; | ||
function env(options) { | ||
var vars = {}; | ||
var added = false; | ||
if (typeof options !== 'object') { | ||
options = {file: options + ''}; | ||
} | ||
if (options.file) { | ||
var env = require(process.cwd() + "/" + options.file); | ||
var file = path.resolve(options.file); | ||
var type = options.type || path.extname(file); | ||
for (var prop in env) { | ||
process.env[prop] = env[prop]; | ||
if (type && type[0] !== '.') { | ||
type = '.' + type; | ||
} | ||
var handler = null; | ||
if (options.handler) { | ||
handler = bind(options.handler); | ||
} else if (!type) { | ||
handler = require; | ||
} else if (types[type]) { | ||
handler = bind(types[type]); | ||
} else if (exts[type]) { | ||
handler = require; | ||
} else { | ||
throw new TypeError('gulp-env: Unknown type: ' + type); | ||
} | ||
extend(vars, handler(file)); | ||
added = true; | ||
} | ||
if (options.vars) { | ||
var vars = options.vars | ||
for (var prop in vars) { | ||
process.env[prop] = vars[prop]; | ||
if (vars == null) { | ||
extend(vars, options.vars); | ||
} else { | ||
extend(vars, options.vars); | ||
} | ||
added = true; | ||
} | ||
return set(added ? vars : null); | ||
}; | ||
function noopPipe(chunk, enc, cb) { | ||
cb(null, chunk); | ||
} | ||
function noopFlush(cb) { | ||
cb() | ||
} | ||
function defaultRestore() { | ||
return false; | ||
} | ||
function once(f) { | ||
var reference = function () { | ||
f(); | ||
reference = noopFlush; | ||
return reference.apply(this, arguments); | ||
}; | ||
return reference; | ||
} | ||
function makeOld(vars) { | ||
var old = {}; | ||
for (var i in vars) { | ||
if (hasOwn.call(vars, i) && hasOwn.call(process.env, i)) { | ||
old[i] = process.env[i]; | ||
} | ||
} | ||
return old; | ||
} | ||
function restoreOld(vars, old, force) { | ||
var res = false; | ||
for (var i in vars) { | ||
if (hasOwn.call(vars, i)) { | ||
if (force) { | ||
if (hasOwn.call(old, i)) { | ||
process.env[i] = old[i]; | ||
res = true; | ||
} else { | ||
delete process.env[i]; | ||
} | ||
} else if (process.env[i] === '' + vars[i]) { | ||
if (hasOwn.call(old, i)) { | ||
process.env[i] = old[i]; | ||
res = true; | ||
} else { | ||
delete process.env[i]; | ||
} | ||
} | ||
} | ||
} | ||
return res; | ||
} | ||
env.set = set; | ||
function set(vars) { | ||
var ret = through2.obj(); | ||
if (vars != null) { | ||
var old = makeOld(vars); | ||
extend(process.env, vars); | ||
var restore = ret.restore = restoreOld.bind(null, vars, old); | ||
ret.reset = through2.obj(noopPipe, once(restore)); | ||
ret.reset.force = through2.obj(noopPipe, once(restore.bind(null, true))); | ||
} | ||
return ret; | ||
} |
{ | ||
"name": "gulp-env", | ||
"version": "0.2.0", | ||
"description": "Add env vars from a .env file to your process.env", | ||
"version": "0.4.0", | ||
"description": "Add env vars to your process.env", | ||
"main": "index.js", | ||
@@ -11,3 +11,3 @@ "scripts": { | ||
"type": "git", | ||
"url": "git://github.com/moveline/gulp-env.git" | ||
"url": "git://github.com/crystalschang/gulp-env.git" | ||
}, | ||
@@ -18,14 +18,27 @@ "keywords": [ | ||
"env", | ||
"process.env" | ||
"process.env", | ||
"gulpfriendly" | ||
], | ||
"author": "Moveline", | ||
"contributors": [ | ||
"Moveline", | ||
"Isiah Meadows <isiahmeadows@gmail.com> (https://github.com/impinball)", | ||
"Russell Matney (https://github.com/russmatney)" | ||
], | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/moveline/gulp-env/issues" | ||
"url": "https://github.com/crystalschang/gulp-env/issues" | ||
}, | ||
"homepage": "https://github.com/moveline/gulp-env", | ||
"homepage": "https://github.com/crystalschang/gulp-env", | ||
"devDependencies": { | ||
"chai": "^1.9.1", | ||
"gulp": "^3.9.0", | ||
"mocha": "^1.21.4" | ||
}, | ||
"typescript": { | ||
"definition": "./gulp-env.d.ts" | ||
}, | ||
"dependencies": { | ||
"ini": "^1.3.4", | ||
"through2": "^2.0.0" | ||
} | ||
} |
340
README.md
gulp-env | ||
======== | ||
Add env vars to your process.env | ||
Add or modify variables in your `process.env`. | ||
Purpose | ||
======== | ||
Often, two processes running at the same time need different environmental variables (for example: running tests and a server from the same gulp process). `gulp-env` helps simplify that problem, by letting you establish your env vars whenever you'd like, in a simpler interface. You can set values from an external `.json`, `.ini`, or other file, or programmatically set them directly by using `env({vars:{}})` or `env.set(vars)`. | ||
Install | ||
@@ -14,78 +18,320 @@ ======== | ||
The TypeScript definition file is available in gulp-env.d.ts within the base directory. | ||
Usage | ||
======== | ||
====== | ||
##Quick Example | ||
### Example | ||
``` | ||
//gulpfile.js | ||
gulp = require('gulp'), | ||
nodemon = require('nodemon'), | ||
env = require('gulp-env'); | ||
Nodemon server: | ||
```js | ||
// gulpfile.js | ||
var gulp = require('gulp'); | ||
var nodemon = require('gulp-nodemon'); | ||
var env = require('gulp-env'); | ||
gulp.task('nodemon', function() { | ||
//nodemon server ... | ||
env({ | ||
file: '.env.json', | ||
vars: { | ||
// any variables you want to overwrite | ||
} | ||
}); | ||
nodemon({ | ||
script: 'server.js', | ||
ext: 'js html' | ||
// other config ... | ||
}); | ||
}); | ||
gulp.task('set-env', function () { | ||
env({ | ||
file: ".env.json", | ||
vars: { | ||
//any vars you want to overwrite | ||
} | ||
}); | ||
gulp.task('default', ['nodemon']); | ||
``` | ||
ES6 web development: | ||
```js | ||
import gulp from 'gulp'; | ||
import browserify from 'browserify'; | ||
import transform from 'vinyl-transform'; | ||
import babel from 'gulp-babel'; | ||
import concat from 'gulp-concat'; | ||
import jshint from 'gulp-jshint'; | ||
import uglify from 'gulp-uglify'; | ||
import sourcemaps from 'gulp-sourcemaps'; | ||
gulp.task('debug', () => { | ||
const envs = env.set({ | ||
NODE_ENV: 'debug' | ||
}); | ||
return gulp.src('src/main.js') | ||
.pipe(envs) | ||
.pipe(babel({optional: [ | ||
'utility.inlineEnvironmentVariables' | ||
]})) | ||
.pipe(uglify()) | ||
.pipe(transform(file => browserify(file).bundle())) | ||
.pipe(envs.reset) | ||
.pipe(gulp.dest('dist')); | ||
}); | ||
``` | ||
gulp.task('default', ['set-env', 'nodemon']) | ||
Simple CoffeeScript library's gulpfile: | ||
```coffee | ||
gulp = require 'gulp' | ||
coffee = require 'gulp-coffee' | ||
mocha = require 'gulp-mocha' | ||
env = require 'gulp-env' | ||
CSON = require 'cson-safe' | ||
gulp.task 'compile', -> | ||
gulp.src('src') | ||
.pipe coffee() | ||
.pipe gulp.dest('dest') | ||
gulp.task 'test', ['compile'], -> | ||
gulp.src('test') | ||
.pipe envs = env | ||
file: 'config.cson' | ||
handler: CSON.parse | ||
.pipe mocha() | ||
.pipe envs.reset | ||
``` | ||
##The Details | ||
## Details | ||
gulp-env handles two options: `file` and `vars`. | ||
`gulp-env` has full test coverage for JSON files, JS modules, INI files, and custom handlers. The entire API below is covered as well. It can also be used in the middle of a Gulp pipeline, where this returns a no-op stream. Note that the `process.env` changes happen synchronously, at the time when the function is called. | ||
###options.file | ||
Read a file and set `process.env` accordingly. Both of these forms are equivalent. | ||
The `file` option uses `require()` under the hood to pull in data and assign it to | ||
the `process.env`. `gulp-env` has test coverage for two options: JSON, and a JS | ||
object exported as a module. | ||
```js | ||
env(file: string) => EnvStream | ||
env({file: string}) => EnvStream | ||
``` | ||
Set one or more hardcoded values in `process.env` directly. | ||
```js | ||
env({vars: Object}) => EnvStream | ||
env.set(vars: Object) => EnvStream | ||
``` | ||
//.env.json | ||
Parse a file, overriding some of its variables. | ||
```js | ||
env({ | ||
// file to read | ||
file: string, | ||
// overrides | ||
vars: Object, | ||
}) => EnvStream | ||
``` | ||
Parse a file with a custom parser. | ||
```js | ||
env({ | ||
// file to read | ||
file: string, | ||
// custom handling, `contents` is the file's contents | ||
handler: (contents: string) => Object, | ||
// optional overrides | ||
vars?: Object, | ||
}) => EnvStream | ||
``` | ||
Parse a file as a different type. | ||
```js | ||
env({ | ||
// file to read | ||
file: string, | ||
// Treat it like this type. See `options.type` for limitations. | ||
type: string, | ||
// overrides | ||
vars?: Object, | ||
}) => EnvStream | ||
``` | ||
### `file`, `options.file` | ||
The `file` option loads the file's contents automatically, calling `require` if it isn't a `.ini` file or if there is no `handler`. You can omit the extension as far as `require` allows if it's already registered, since this uses `require` under the hood as a fallback. | ||
```js | ||
// .env.json | ||
{ | ||
MONGO_URI: "mongodb://localhost:27017/testdb | ||
MONGO_URI: "mongodb://localhost:27017/testdb" | ||
} | ||
//.env | ||
// .env.js | ||
module.exports = { | ||
MONGO_URI: "mongodb://localhost:27017/testdb | ||
} | ||
MONGO_URI: "mongodb://localhost:27017/testdb", | ||
}; | ||
//gulpfile.js | ||
var env = require('gulp-env') | ||
// gulpfile.js | ||
var env = require('gulp-env'); | ||
process.env.MONGO_URI === "mongodb://localhost:27017/testdb"; // maybe false | ||
// Any of these will work: | ||
env(".env"); // if the file can be found via `require` | ||
env(".env.json"); | ||
env({file: ".env"}); // if the file can be found via `require` | ||
env({file: ".env.json"}); | ||
process.env.MONGO_URI === "mongodb://localhost:27017/testdb"; // true | ||
``` | ||
### `options.vars` | ||
Properties on this object overwrite all existing external properties given by file loading, handlers, etc. All of these will also be added to `process.env`. | ||
```js | ||
// gulpfile.js | ||
var env = require('gulp-env'); | ||
env({ | ||
file: ".env" | ||
//OR | ||
file: ".env.json" | ||
}) | ||
file: 'env.ini', | ||
vars: { | ||
MONGO_URI: "mongodb://localhost:27017/testdb-for-british-eyes-only", | ||
PORT: 9001 | ||
} | ||
}); | ||
``` | ||
###options.vars | ||
For the case of just setting environment variables programmatically, you can use `env.set`. | ||
Properties passed to the vars option will be set on process.env as well. | ||
These properties will overwrite the external file's properties. | ||
```js | ||
// These two are equivalent. They both can also be used in Gulp streams. | ||
env({vars: vars}); | ||
env.set(vars); | ||
``` | ||
### `options.handler` | ||
This customizes the parsing of the file. If this is given, the extension name is ignored, and the handler itself is directly called. This is very useful in cases where this module doesn't already support the format. Internally, the module uses this hook for its INI and JSON readers. | ||
The function, if given, is called with two arguments: | ||
- `contents` - the file's contents | ||
- `filename` - the file's name | ||
Notes: | ||
- You don't need this if the file type itself is already registered in `require.extensions`. | ||
- If the file doesn't exist, then `contents` is undefined. `filename` is still passed, though. | ||
- If the extension is omitted, then `filename` reflects that, i.e. the extension is omitted. | ||
```coffee | ||
# CSON is frequently used in CoffeeScript projects. Why not use that? | ||
env = require 'gulp-env' | ||
CSON = require 'cson-safe' | ||
env | ||
file: '.env.cson' | ||
handler: (contents) -> CSON.parse contents | ||
``` | ||
//gulpfile.js | ||
var env = require('gulp-env') | ||
```js | ||
// Or, why can't we use YAML? | ||
var env = require('gulp-env'); | ||
var jsyaml = require('js-yaml'); | ||
env({ | ||
vars: { | ||
MONGO_URI: "mongodb://localhost:27017/testdb-for-british-eyes-only", | ||
PORT: 9001 | ||
} | ||
}) | ||
file: '.env.yaml', | ||
handler: function(contents, filename) { | ||
return jsyaml.safeLoad(contents, {filename: filename}); | ||
}, | ||
}); | ||
``` | ||
TODO | ||
======== | ||
### `options.type` | ||
- handle ini files | ||
Treats the file input as if its extension was `type`. It doesn't work for `require`d files, since Node.js doesn't have hooks to do that, but it currently works for `json` and `ini` types. Others may potentially be added over time. If you think another one should be added, please, by all means, submit a PR. | ||
```js | ||
var env = require('gulp-env'); | ||
env({ | ||
file: '.env', | ||
type: 'ini', | ||
}); | ||
// You can also specify it as an extension, as opposed to a type. | ||
env({ | ||
file: '.env', | ||
type: '.ini', | ||
}); | ||
``` | ||
### EnvStream | ||
Instances of this interface are returned for `env()` and `env.set()`. These are standard through2 object streams with the following extra methods: | ||
- Reset the environment to its former state synchronously. This is designed to be most useful outside of gulpfiles. It returns a boolean, true if any properties were reset, false otherwise. Pass a truthy value as an argument to forcefully restore, i.e. ignore conflicts. | ||
```js | ||
envs.restore(force?: boolean) => boolean | ||
``` | ||
- Reset the environment to its former state. Similar to `.restore()`, but is called after the incoming stream is flushed, i.e. after all previous Gulp plugins have had their effect on the stream. This is otherwise a no-op through2 object stream. The second version is analogous to `envs.restore(true)` | ||
```js | ||
envs.reset => stream.Readable, stream.Writable | ||
envs.reset.force => stream.Readable, stream.Writable | ||
``` | ||
Note that such environments can be nested. For example, the following will work: | ||
```js | ||
process.env.NODE_ENV // undefined | ||
var env1 = env.set({NODE_ENV: "whatever"}); | ||
process.env.NODE_ENV // "whatever" | ||
var env2 = env.set({NODE_ENV: "something else"}); | ||
process.env.NODE_ENV // "something else" | ||
env2.restore(); | ||
process.env.NODE_ENV // "whatever" | ||
env1.restore(); | ||
process.env.NODE_ENV // undefined | ||
``` | ||
Now, if two settings are restored out of order, conflicting keys (where the currently set value is not the same as the originally set for that version) are simply left as-is. This is the same with externally changed environment variables. | ||
```js | ||
// unbalanced modifications | ||
process.env.NODE_ENV // undefined | ||
var env1 = env.set({NODE_ENV: "whatever"}); | ||
process.env.NODE_ENV // "whatever" | ||
var env2 = env.set({NODE_ENV: "something else"}); | ||
process.env.NODE_ENV // "something else" | ||
env1.restore(); | ||
process.env.NODE_ENV // "something else" | ||
env2.restore(); | ||
process.env.NODE_ENV // "whatever" | ||
// external modifications | ||
process.env.NODE_ENV // undefined | ||
var env1 = env.set({NODE_ENV: "whatever"}); | ||
process.env.NODE_ENV // "whatever" | ||
process.env.NODE_ENV = "something else"; | ||
env1.restore(); | ||
process.env.NODE_ENV // "something else" | ||
``` | ||
Issues | ||
======= | ||
Submit a new issue here in the [issue tracker](https://github.com/moveline/gulp-env/issues/new) | ||
Contributing | ||
============= | ||
This aims for full test coverage. If you see something missing, please, by all means, [send a PR](https://github.com/moveline/gulp-env/compare). | ||
To run the tests, run `npm test`. The tests and their dependencies are written in `test/**`. |
{ | ||
"STARK": "direwolf", | ||
"BARATHEON": "stag", | ||
"LANNISTER": "lion" | ||
"STARK": "direwolf", | ||
"BARATHEON": "stag", | ||
"LANNISTER": "lion" | ||
} |
@@ -1,5 +0,17 @@ | ||
var env = require('../'), | ||
expect = require('chai').expect; | ||
'use strict'; | ||
var env = require('../'); | ||
var expect = require('chai').expect; | ||
var fs = require('fs'); | ||
var resolve = require('path').resolve; | ||
var gulp = require('gulp'); | ||
var through2 = require('through2'); | ||
describe('gulp-env', function() { | ||
function prepVars() { | ||
delete process.env.STARK; | ||
delete process.env.BARATHEON; | ||
delete process.env.LANNISTER; | ||
} | ||
it('should exist', function() { | ||
@@ -10,7 +22,4 @@ expect(env).to.exist; | ||
describe('reads properties from files', function() { | ||
afterEach(function() { | ||
delete process.env.STARK; | ||
delete process.env.BARATHEON; | ||
delete process.env.LANNISTER; | ||
}); | ||
beforeEach(prepVars); | ||
afterEach(prepVars); | ||
@@ -29,2 +38,14 @@ it('should add process.env vars from a local module', function() { | ||
it('should take the file as the sole argument as a string', function() { | ||
expect(process.env.STARK).not.to.exist | ||
expect(process.env.BARATHEON).not.to.exist | ||
expect(process.env.LANNISTER).not.to.exist | ||
env("test/mock-env-module") | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
}); | ||
it('should add process.env vars from a local json file', function() { | ||
@@ -41,2 +62,50 @@ expect(process.env.STARK).not.to.exist | ||
}); | ||
it('should add process.env vars from a local ini file', function() { | ||
expect(process.env.STARK).not.to.exist | ||
expect(process.env.BARATHEON).not.to.exist | ||
expect(process.env.LANNISTER).not.to.exist | ||
env({file: "test/mock-env-ini.ini"}) | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
}); | ||
it('should treat a file as a different type when given a type', function() { | ||
expect(process.env.STARK).not.to.exist | ||
expect(process.env.BARATHEON).not.to.exist | ||
expect(process.env.LANNISTER).not.to.exist | ||
env({file: "test/mock-env-json.txt", type: '.json'}) | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
}); | ||
it('should throw if the given type is unsupported', function() { | ||
expect(function() { | ||
env({file: "test/mock-env-json.txt", type: '.blarg'}) | ||
}).to.throw(); | ||
}); | ||
it('should add a missing dot to the type if a type is given', function() { | ||
expect(process.env.STARK).not.to.exist | ||
expect(process.env.BARATHEON).not.to.exist | ||
expect(process.env.LANNISTER).not.to.exist | ||
env({file: "test/mock-env-json.txt", type: 'json'}) | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
}); | ||
it('should throw if the file doesn\'t exist', function() { | ||
expect(function() { | ||
env("test/mock-env-blarg") | ||
}).to.throw(); | ||
}); | ||
}); | ||
@@ -66,10 +135,23 @@ | ||
}); | ||
it('should add process.env vars in env.set', function() { | ||
expect(process.env.NED).not.to.exist | ||
expect(process.env.ROBERT).not.to.exist | ||
expect(process.env.TYWIN).not.to.exist | ||
env.set({ | ||
NED: true, | ||
ROBERT: 'fat', | ||
TYWIN: 9001 | ||
}); | ||
expect(process.env.NED).to.equal('true'); | ||
expect(process.env.ROBERT).to.equal('fat'); | ||
expect(process.env.TYWIN).to.equal('9001'); | ||
}); | ||
}); | ||
describe('reads properties from files and vars object', function() { | ||
afterEach(function() { | ||
delete process.env.STARK; | ||
delete process.env.BARATHEON; | ||
delete process.env.LANNISTER; | ||
}); | ||
beforeEach(prepVars); | ||
afterEach(prepVars); | ||
@@ -92,2 +174,385 @@ it('should overwrite files with inline-vars by default', function() { | ||
}) | ||
describe('calls and reads the result of handlers', function() { | ||
beforeEach(prepVars); | ||
afterEach(prepVars); | ||
it('should call the handler with exactly two arguments', function() { | ||
var called = false; | ||
var args; | ||
env({file: "test/mock-env-txt.txt", handler: function() { | ||
called = true; | ||
args = [].slice.call(arguments); | ||
}}); | ||
expect(called).to.be.true | ||
expect(args).to.have.length(1); | ||
}); | ||
it('should pass the contents first', function() { | ||
var expected = fs.readFileSync('test/mock-env-txt.txt', 'utf8'); | ||
env({file: "test/mock-env-txt.txt", handler: function(found) { | ||
expect(found).to.equal(expected); | ||
}}); | ||
}); | ||
it('should not be called if the file doesn\'t exist', function() { | ||
var called = false; | ||
try { | ||
env({file: "test/mock-env-blarg", handler: function() { | ||
called = true | ||
}}); | ||
} catch (e) {} | ||
expect(called).to.be.false | ||
}); | ||
it('should add process.env vars from the result of a handler', function() { | ||
expect(process.env.STARK).not.to.exist | ||
expect(process.env.BARATHEON).not.to.exist | ||
expect(process.env.LANNISTER).not.to.exist | ||
env({file: "test/mock-env-txt.txt", handler: function() { | ||
return { | ||
STARK: "direwolf", | ||
BARATHEON: "stag", | ||
LANNISTER: "lion", | ||
}; | ||
}}); | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
}); | ||
it('should be overwritten by inline-vars', function() { | ||
env({ | ||
file: "test/mock-env-txt.txt", | ||
handler: function() { | ||
return { | ||
STARK: "foo", | ||
BARATHEON: "bar", | ||
}; | ||
}, | ||
vars: {STARK: "bar"} | ||
}); | ||
expect(process.env.STARK).to.equal("bar"); | ||
expect(process.env.BARATHEON).to.equal("bar"); | ||
}); | ||
it('should return a value that has own property `.restore`', function() { | ||
expect(env.set({})).to.have.ownProperty('restore'); | ||
}); | ||
it('should return a value with a `.restore` method', function() { | ||
expect(env.set({}).restore).to.be.a('function'); | ||
}); | ||
}); | ||
describe('`.restore()` on return value', function() { | ||
beforeEach(prepVars); | ||
afterEach(prepVars); | ||
it('should be able to reset', function() { | ||
var envs = env.set({ | ||
STARK: "direwolf", | ||
BARATHEON: "stag", | ||
LANNISTER: "lion", | ||
}); | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
envs.restore(); | ||
expect(process.env.STARK).to.not.exist; | ||
expect(process.env.BARATHEON).to.not.exist; | ||
expect(process.env.LANNISTER).to.not.exist; | ||
}); | ||
it('should return true if any keys were restored', function() { | ||
process.env.STARK = "blarg"; | ||
var envs = env.set({ | ||
STARK: "direwolf", | ||
}); | ||
var result = envs.restore(); | ||
expect(process.env.STARK).to.equal("blarg"); | ||
expect(result).to.be.true; | ||
}); | ||
it('should return false if no keys were restored', function() { | ||
var envs = env.set({ | ||
STARK: "direwolf", | ||
}); | ||
var result = envs.restore(); | ||
expect(process.env.STARK).to.not.exist; | ||
expect(result).to.be.false; | ||
}); | ||
it('should not attempt to overwrite manually changed keys', function() { | ||
var envs = env.set({ | ||
STARK: "direwolf", | ||
BARATHEON: "stag", | ||
LANNISTER: "lion", | ||
}); | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
process.env.STARK = "nope"; | ||
envs.restore(); | ||
expect(process.env.STARK).to.equal("nope"); | ||
expect(process.env.BARATHEON).to.not.exist; | ||
expect(process.env.LANNISTER).to.not.exist; | ||
}); | ||
it('should be nestable in scope', function() { | ||
var envs = env.set({ | ||
STARK: "direwolf", | ||
BARATHEON: "stag", | ||
LANNISTER: "lion", | ||
}); | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
var next = env.set({ | ||
STARK: "spam", | ||
BARATHEON: "nope", | ||
LANNISTER: "hello", | ||
}); | ||
expect(process.env.STARK).to.equal("spam"); | ||
expect(process.env.BARATHEON).to.equal("nope"); | ||
expect(process.env.LANNISTER).to.equal("hello"); | ||
next.restore(); | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
envs.restore(); | ||
expect(process.env.STARK).to.not.exist; | ||
expect(process.env.BARATHEON).to.not.exist; | ||
expect(process.env.LANNISTER).to.not.exist; | ||
}); | ||
it('should not correct out-of-order restores', function() { | ||
var envs = env.set({ | ||
STARK: "direwolf", | ||
BARATHEON: "stag", | ||
LANNISTER: "lion", | ||
}); | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
var next = env.set({ | ||
STARK: "spam", | ||
BARATHEON: "nope", | ||
LANNISTER: "hello", | ||
}); | ||
expect(process.env.STARK).to.equal("spam"); | ||
expect(process.env.BARATHEON).to.equal("nope"); | ||
expect(process.env.LANNISTER).to.equal("hello"); | ||
envs.restore(); | ||
expect(process.env.STARK).to.equal("spam"); | ||
expect(process.env.BARATHEON).to.equal("nope"); | ||
expect(process.env.LANNISTER).to.equal("hello"); | ||
}); | ||
function testTruthy(item, string) { | ||
it('should ignore conflicts when passed a truthy argument (' + string + | ||
')', function() { | ||
var envs = env.set({ | ||
STARK: "direwolf", | ||
BARATHEON: "stag", | ||
LANNISTER: "lion", | ||
}); | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
process.env.STARK = "nope"; | ||
envs.restore(true); | ||
expect(process.env.STARK).to.not.exist; | ||
expect(process.env.BARATHEON).to.not.exist; | ||
expect(process.env.LANNISTER).to.not.exist; | ||
}); | ||
} | ||
testTruthy(1, '1'); | ||
testTruthy({}, '{}'); | ||
testTruthy([], '[]'); | ||
testTruthy(true, 'true'); | ||
}); | ||
describe('gulp plugin behavior', function() { | ||
beforeEach(prepVars); | ||
afterEach(prepVars); | ||
it('should work as a gulp plugin', function(done) { | ||
gulp.src('test/mock-env-json.txt') | ||
.pipe(env({ | ||
vars: { | ||
STARK: "direwolf", | ||
BARATHEON: "stag", | ||
LANNISTER: "lion", | ||
}, | ||
})) | ||
.on('end', done) | ||
.on('data', function() {}) | ||
.on('error', done); | ||
}); | ||
it('should work as a gulp plugin with `.set`', function(done) { | ||
gulp.src('test/mock-env-json.txt') | ||
.pipe(env.set({ | ||
STARK: "direwolf", | ||
BARATHEON: "stag", | ||
LANNISTER: "lion", | ||
})) | ||
.on('end', done) | ||
.on('data', function() {}) | ||
.on('error', done); | ||
}); | ||
it('should return a value that has own property `.reset`', function() { | ||
expect(env.set({})).to.have.ownProperty('reset'); | ||
}); | ||
it('should return a value with a `.reset` read/write stream', function() { | ||
var reset = env.set({}).reset; | ||
expect(reset._read).to.be.a('function'); | ||
expect(reset._write).to.be.a('function'); | ||
}); | ||
it('should be able to reset with `.reset`', function(done) { | ||
var envs = env.set({ | ||
STARK: "direwolf", | ||
BARATHEON: "stag", | ||
LANNISTER: "lion", | ||
}); | ||
gulp.src('test/mock-env-json.txt') | ||
.pipe(envs) | ||
.pipe(through2.obj(function(chunk, enc, callback) { | ||
// Pass through | ||
callback(null, chunk) | ||
}, function(callback) { | ||
try { | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
} catch (e) { | ||
return callback(e); | ||
} | ||
return callback(); | ||
})) | ||
.pipe(envs.reset) | ||
.pipe(through2.obj(function(chunk, enc, callback) { | ||
// Pass through | ||
callback(null, chunk) | ||
}, function(callback) { | ||
try { | ||
expect(process.env.STARK).to.not.exist; | ||
expect(process.env.BARATHEON).to.not.exist; | ||
expect(process.env.LANNISTER).to.not.exist; | ||
} catch (e) { | ||
return callback(e); | ||
} | ||
return callback(); | ||
})) | ||
.on('end', done) | ||
.on('data', function() {}) | ||
.on('error', done); | ||
}); | ||
it('should not resolve conflicting keys', function(done) { | ||
var envs = env.set({ | ||
STARK: "direwolf", | ||
BARATHEON: "stag", | ||
LANNISTER: "lion", | ||
}); | ||
gulp.src('test/mock-env-json.txt') | ||
.pipe(envs) | ||
.pipe(through2.obj(function(chunk, enc, callback) { | ||
// Pass through | ||
callback(null, chunk) | ||
}, function(callback) { | ||
try { | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
} catch (e) { | ||
return callback(e); | ||
} | ||
process.env.STARK = "blarg"; | ||
return callback(); | ||
})) | ||
.pipe(envs.reset) | ||
.pipe(through2.obj(function(chunk, enc, callback) { | ||
// Pass through | ||
callback(null, chunk) | ||
}, function(callback) { | ||
try { | ||
expect(process.env.STARK).to.equal("blarg"); | ||
expect(process.env.BARATHEON).to.not.exist; | ||
expect(process.env.LANNISTER).to.not.exist; | ||
} catch (e) { | ||
return callback(e); | ||
} | ||
return callback(); | ||
})) | ||
.on('end', done) | ||
.on('data', function() {}) | ||
.on('error', done); | ||
}); | ||
it('should ignore conflicts when passed as `.force`', function(done) { | ||
var envs = env.set({ | ||
STARK: "direwolf", | ||
BARATHEON: "stag", | ||
LANNISTER: "lion", | ||
}); | ||
gulp.src('test/mock-env-json.txt') | ||
.pipe(envs) | ||
.pipe(through2.obj(function(chunk, enc, callback) { | ||
// Pass through | ||
callback(null, chunk) | ||
}, function(callback) { | ||
try { | ||
expect(process.env.STARK).to.equal("direwolf"); | ||
expect(process.env.BARATHEON).to.equal("stag"); | ||
expect(process.env.LANNISTER).to.equal("lion"); | ||
} catch (e) { | ||
return callback(e); | ||
} | ||
process.env.STARK = "blarg"; | ||
return callback(); | ||
})) | ||
.pipe(envs.reset.force) | ||
.pipe(through2.obj(function(chunk, enc, callback) { | ||
// Pass through | ||
callback(null, chunk) | ||
}, function(callback) { | ||
try { | ||
expect(process.env.STARK).to.not.exist; | ||
expect(process.env.BARATHEON).to.not.exist; | ||
expect(process.env.LANNISTER).to.not.exist; | ||
} catch (e) { | ||
return callback(e); | ||
} | ||
return callback(); | ||
})) | ||
.on('end', done) | ||
.on('data', function() {}) | ||
.on('error', done); | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
108318
13
2327
337
2
3
142
1
+ Addedini@^1.3.4
+ Addedthrough2@^2.0.0
+ Addedcore-util-is@1.0.3(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedini@1.3.8(transitive)
+ Addedisarray@1.0.0(transitive)
+ Addedprocess-nextick-args@2.0.1(transitive)
+ Addedreadable-stream@2.3.8(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedstring_decoder@1.1.1(transitive)
+ Addedthrough2@2.0.5(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addedxtend@4.0.2(transitive)