Skip to content

Commit

Permalink
Merge pull request #22 from Platane/master
Browse files Browse the repository at this point in the history
add option on how to merge env var from system
  • Loading branch information
brysgo authored Mar 30, 2019
2 parents 41c18bd + b0b3bda commit 480db73
Show file tree
Hide file tree
Showing 16 changed files with 976 additions and 11 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
EXAMPLE_ENV_VAR="simple example"
EXAMPLE_ENV_VAR_SYSTEM="default"
EXAMPLE_ENV_VAR_EXPAND=$EXAMPLE_ENV_VAR-expand
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ To replace with env value without `process && process.env && process.env.MY_VARI
}
```

The plugin support 3 mode to read the env var from the system :

```js
{
"plugins": [["inline-dotenv",{
systemVar: 'all' | 'overwrite' | 'disable'
}]]
}
```

- `all` _default_, every env var found in process.env will be used
> ⚠️ This could leak super secret stuffs !
- `overwrite`, the value in process.env will overwrite the one present in .env only. Your .env file act as a whitelist

- `disable`, the process.env will not be used at all

### Via CLI

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Load your `.env` file and replace `process.env.MY_VARIABLE` with the value you set.",
"main": "src/index.js",
"scripts": {
"test": "mocha --require babel-core/register",
"test": "EXAMPLE_ENV_VAR_SYSTEM=system EXAMPLE_ENV_VAR_SECRET=secret mocha --require babel-core/register",
"test:watch": "npm run test -- --watch"
},
"repository": {
Expand All @@ -31,7 +31,7 @@
"babel-eslint": "^9.0.0",
"babel-preset-es2015": "^6.1.18",
"babel-register": "^6.2.0",
"dotenv-expand": "^5.0.0",
"dotenv-expand": "^5.1.0",
"mocha": "^6.0.0"
}
}
45 changes: 40 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
"use strict";

var dotenv;
var fs = require('fs');
var pathResolve = require('path').resolve;

var dotenvContent;

function getValue(dotenvContent, systemContent, opts, name) {
if (opts.env && name in opts.env) return opts.env[name];

switch (opts.systemVar) {
case "overwrite":
if (name in dotenvContent && name in systemContent)
return systemContent[name];
if (name in dotenvContent) return dotenvContent[name];
return;
case "disable":
if (name in dotenvContent) return dotenvContent[name];
return;
case "all":
default:
if (name in systemContent) return systemContent[name];
if (name in dotenvContent) return dotenvContent[name];
return;
}
}

module.exports = function (options) {
var t = options.types;
Expand All @@ -10,17 +33,29 @@ module.exports = function (options) {
MemberExpression: function MemberExpression(path, state) {
if(t.isAssignmentExpression(path.parent) && path.parent.left == path.node) return;
if (path.get("object").matchesPattern("process.env")) {
if (!dotenv) {
dotenv = require('dotenv').config(state.opts);
if (!dotenvContent) {
var dotenvPath = pathResolve(process.cwd(), '.env')
var encoding = 'utf8'
var debug = false
if (state.opts.path != null) {
dotenvPath = state.opts.path
}
if (state.opts.encoding != null) {
encoding = state.opts.encoding
}
if (state.opts.debug != null) {
debug = true
}
dotenvContent = require('dotenv').parse(fs.readFileSync(dotenvPath, {encoding:encoding}), {debug:debug});
var dotenvExpand;
try { dotenvExpand = require('dotenv-expand'); } catch(e) {}
if (dotenvExpand)
dotenvExpand(dotenv);
dotenvContent = dotenvExpand({parsed:dotenvContent, ignoreProcessEnv:true}).parsed;
}
var key = path.toComputedKey();
if (t.isStringLiteral(key)) {
var name = key.value;
var value = state.opts.env && name in state.opts.env ? state.opts.env[name] : process.env[name];
var value = getValue(dotenvContent, process.env, state.opts, name)
var me = t.memberExpression;
var i = t.identifier;
var le = t.logicalExpression;
Expand Down
10 changes: 10 additions & 0 deletions test/fixtures/code-simple-env-variable-no-systemVar/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"plugins": [
["../../../src", {
"systemVar" : "disable",
"transforms": [{
"transform": "transform-lib"
}]
}]
]
}
221 changes: 221 additions & 0 deletions test/fixtures/code-simple-env-variable-no-systemVar/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
"use strict";

// Example 1: Creating a new class (declaration-form)
// ===============================================================

// A base class is defined using the new reserved 'class' keyword

const EXAMPLE_ENV_VAR = process.env.EXAMPLE_ENV_VAR;
const EXAMPLE_ENV_VAR_EXPAND = process.env.EXAMPLE_ENV_VAR_EXPAND;
const EXAMPLE_ENV_VAR_SECRET = process.env.EXAMPLE_ENV_VAR_SECRET;
const EXAMPLE_ENV_VAR_SYSTEM = process.env.EXAMPLE_ENV_VAR_SYSTEM;

class Polygon {
// ..and an (optional) custom class constructor. If one is
// not supplied, a default constructor is used instead:
// constructor() { }
constructor(height, width) {
this.name = "Polygon";
this.height = height;
this.width = width;
}

// Simple class instance methods using short-hand method
// declaration
sayName() {
console.log("Hi, I am a ", this.name + ".");
}

sayHistory() {
console.log(`
"Polygon" is derived from the Greek polus (many) and gonia (angle).
`);
}

// We will look at static and subclassed methods shortly
}

// Classes are used just like ES5 constructor functions:
let p = new Polygon(300, 400);
p.sayName();
console.log("The width of this polygon is " + p.width);

// Example 2: Creating a new class (expression-form)
// ===============================================================

// Our Polygon class above is an example of a Class declaration.
// ES6 classes also support Class expressions - just another way
// of defining a new class. For example:
const MyPoly = class Poly {
getPolyName() {
console.log(`
Hi. I was created with a Class expression. My name is ${Poly.name}
`);
}
};

let inst = new MyPoly();
inst.getPolyName();

// Example 3: Extending an existing class
// ===============================================================

// Classes support extending other classes, but can also extend
// other objects. Whatever you extend must be a constructor.
//
// Let's extend the Polygon class to create a new derived class
// called Square.
class Square extends Polygon {
constructor(length) {
// The reserved 'super' keyword is for making super-constructor
// calls and allows access to parent methods.
//
// Here, it will call the parent class' constructor with lengths
// provided for the Polygon's width and height
super(length, length);
// Note: In derived classes, super() must be called before you
// can use 'this'. Leaving this out will cause a reference error.
this.name = "Square";
}

// Getter/setter methods are supported in classes,
// similar to their ES5 equivalents
get area() {
return this.height * this.width;
}

set area(value) {
this.area = value;
}
}

let s = new Square(5);

s.sayName();
console.log("The area of this square is " + s.area);

// Example 4: Subclassing methods of a parent class
// ===============================================================

class Rectangle extends Polygon {
constructor(height, width) {
super(height, width);
this.name = "Rectangle";
}
// Here, sayName() is a subclassed method which
// overrides their superclass method of the same name.
sayName() {
console.log("Sup! My name is ", this.name + ".");
super.sayHistory();
}
}

let r = new Rectangle(50, 60);
r.sayName();

// Example 5: Defining static methods
// ===============================================================

// Classes support static members which can be accessed without an
// instance being present.
class Triple {
// Using the 'static' keyword creates a method which is associated
// with a class, but not with an instance of the class.
static triple(n) {
n = n || 1;
return n * 3;
}
}

// super.prop in this example is used for accessing super-properties from
// a parent class. This works fine in static methods too:
class BiggerTriple extends Triple {
static triple(n) {
return super.triple(n) * super.triple(n);
}
}

console.log(Triple.triple());
console.log(Triple.triple(6));
console.log(BiggerTriple.triple(3));
// var tp = new Triple();
// console.log(tp.triple()); tp.triple is not a function

// Example 6: Subclassing built-in classes and DOM
// ===============================================================

// Extend Date built-in
class MyDate extends Date {
constructor() {
super();
}

getFormattedDate() {
const m1 = ["Jan", "Feb", "Mar"];
const m2 = ["Apr", "May", "Jun"];
const m3 = ["Jul", "Aug", "Sep"];
const m4 = ["Oct", "Nov", "Dec"];
var months = [...m1, ...m2, ...m3, ...m4];
const month = months.getMonth();
const date = this.getDate();
const year = this.getFullYear();
return `${date}-${month}-${year}`;
}
}

var aDate = new MyDate();
console.log(aDate.getTime());
console.log(aDate.getFormattedDate());

// Extend Uint8Array
class ExtendedUint8Array extends Uint8Array {
constructor() {
super(10);
this[0] = 255;
this[1] = 0xffa;
}
}

var eua = new ExtendedUint8Array();
console.log(eua.byteLength);

// Extend DOM Audio element
class MyAudio extends Audio {
constructor() {
super();
this._lyrics = "";
}

get lyrics() {
return this._lyrics;
}

set lyrics(str) {
this._lyrics = str;
}
}

var player = new MyAudio();
player.controls = true;
player.lyrics = "Never gonna give you up";
document.querySelector("body").appendChild(player);
console.log(player.lyrics);

// Note: The V8 in Chrome 42 supports subclassing built-ins but Arrays.
// Subclassing arrays supported in Chrome 43.

class Stack extends Array {
constructor() {
super();
}

top() {
return this[this.length - 1];
}
}

var stack = new Stack();
stack.push("world");
stack.push("hello");
console.log(stack.top());
console.log(stack.length);
Loading

0 comments on commit 480db73

Please sign in to comment.