react-native-dotenv
Advanced tools
Comparing version 0.2.0 to 2.2.0
93
index.js
@@ -1,10 +0,85 @@ | ||
var path = require('path'); | ||
const {readFileSync} = require('fs') | ||
const dotenv = require('dotenv') | ||
module.exports = () => ({ | ||
plugins: [ | ||
[require('babel-plugin-dotenv'), { | ||
replacedModuleName: 'react-native-dotenv', | ||
configDir: path.resolve(__dirname, "../../") | ||
}], | ||
], | ||
}); | ||
function parseDotenvFile(path) { | ||
let content | ||
try { | ||
content = readFileSync(path) | ||
} catch { | ||
// The env file does not exist. | ||
return {} | ||
} | ||
return dotenv.parse(content) | ||
} | ||
module.exports = ({types: t}) => ({ | ||
name: 'dotenv-import', | ||
pre() { | ||
this.opts = { | ||
moduleName: '@env', | ||
path: '.env', | ||
whitelist: null, | ||
blacklist: null, | ||
safe: false, | ||
allowUndefined: false, | ||
...this.opts | ||
} | ||
const babelMode = process.env.BABEL_ENV || 'development' | ||
if (this.opts.safe) { | ||
const parsed = parseDotenvFile(this.opts.path) | ||
const modeParsed = parseDotenvFile(this.opts.path + '.' + babelMode) | ||
this.env = Object.assign(parsed, modeParsed) | ||
} else { | ||
dotenv.config({ | ||
path: this.opts.path | ||
}) | ||
dotenv.config({ | ||
path: this.opts.path + '.' + babelMode, | ||
silent: true | ||
}) | ||
this.env = process.env | ||
} | ||
}, | ||
visitor: { | ||
ImportDeclaration(path, {opts}) { | ||
if (path.node.source.value === opts.moduleName) { | ||
path.node.specifiers.forEach((specifier, idx) => { | ||
if (specifier.type === 'ImportDefaultSpecifier') { | ||
throw path.get('specifiers')[idx].buildCodeFrameError('Default import is not supported') | ||
} | ||
if (specifier.type === 'ImportNamespaceSpecifier') { | ||
throw path.get('specifiers')[idx].buildCodeFrameError('Wildcard import is not supported') | ||
} | ||
const importedId = specifier.imported.name | ||
const localId = specifier.local.name | ||
if (Array.isArray(opts.whitelist) && !opts.whitelist.includes(importedId)) { | ||
throw path.get('specifiers')[idx].buildCodeFrameError(`"${importedId}" was not whitelisted`) | ||
} | ||
if (Array.isArray(opts.blacklist) && opts.blacklist.includes(importedId)) { | ||
throw path.get('specifiers')[idx].buildCodeFrameError(`"${importedId}" was blacklisted`) | ||
} | ||
if (!opts.allowUndefined && !Object.prototype.hasOwnProperty.call(this.env, importedId)) { | ||
throw path.get('specifiers')[idx].buildCodeFrameError(`"${importedId}" is not defined in ${opts.path}`) | ||
} | ||
const binding = path.scope.getBinding(localId) | ||
binding.referencePaths.forEach(refPath => { | ||
refPath.replaceWith(t.valueToNode(this.env[importedId])) | ||
}) | ||
}) | ||
path.remove() | ||
} | ||
} | ||
} | ||
}) |
{ | ||
"name": "react-native-dotenv", | ||
"version": "0.2.0", | ||
"description": "A Babel preset let you `import` application configs from **.env** file (zero runtime dependency)", | ||
"version": "2.2.0", | ||
"description": "Load environment variables using import statements.", | ||
"repository": "github:goatandsheep/react-native-dotenv", | ||
"homepage": "https://github.com/goatandsheep/react-native-dotenv", | ||
"bugs": "https://github.com/goatandsheep/react-native-dotenv/issues", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "cd babel-plugin-dotenv && npm install && npm test" | ||
"lint": "xo", | ||
"lint:fix": "xo --fix", | ||
"test": "jest" | ||
}, | ||
"keywords": [ | ||
"dotenv", | ||
"babel-plugin", | ||
"react", | ||
"react-native" | ||
], | ||
"author": "David Chang", | ||
"dependencies": { | ||
"dotenv": "^8.0.0" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.7.7", | ||
"codecov": "^3.6.1", | ||
"jest": "^26.0.1", | ||
"jest-junit": "^11.0.1", | ||
"xo": "^0.32.1" | ||
}, | ||
"author": "Kemal Ahmed", | ||
"license": "MIT", | ||
"dependencies": { | ||
"babel-plugin-dotenv": "0.1.1" | ||
"jest": { | ||
"testEnvironment": "node", | ||
"testPathIgnorePatterns": [ | ||
"/node_modules/", | ||
"/__fixtures__/" | ||
], | ||
"reporters": [ | ||
"default", | ||
[ | ||
"jest-junit", | ||
{ | ||
"outputDirectory": "reports/tests" | ||
} | ||
] | ||
], | ||
"collectCoverage": true, | ||
"collectCoverageFrom": [ | ||
"index.js" | ||
], | ||
"coverageReporters": [ | ||
"lcov", | ||
"text-summary" | ||
] | ||
}, | ||
"xo": { | ||
"semicolon": false, | ||
"space": 2, | ||
"overrides": [ | ||
{ | ||
"files": "__tests__/**/*.js", | ||
"env": [ | ||
"jest" | ||
] | ||
}, | ||
{ | ||
"files": "__tests__/__fixtures__/**/*.js", | ||
"rules": { | ||
"import/no-unresolved": [ | ||
"error", | ||
{ | ||
"ignore": [ | ||
"@env", | ||
"foo" | ||
] | ||
} | ||
], | ||
"no-unused-vars": "off" | ||
} | ||
} | ||
] | ||
} | ||
} |
160
README.md
@@ -1,99 +0,151 @@ | ||
# react-native-dotenv | ||
# react-native-dotenv [![CircleCI](https://circleci.com/gh/goatandsheep/react-native-dotenv.svg?style=svg)](https://circleci.com/gh/goatandsheep/react-native-dotenv) | ||
Let you `import` environment variables from a **.env** file in React Native, **don't** need any native code integration. | ||
> Load environment variables using `import` statements. | ||
[![CircleCI](https://circleci.com/gh/zetachang/react-native-dotenv.svg?style=svg)](https://circleci.com/gh/zetachang/react-native-dotenv) | ||
[![npm version](https://img.shields.io/npm/v/react-native-dotenv.svg?style=flat-square)](https://www.npmjs.com/package/react-native-dotenv) | ||
[![npm downloads](https://img.shields.io/npm/dt/react-native-dotenv.svg?style=flat-square)](https://www.npmjs.com/package/react-native-dotenv) | ||
[![npm version](https://badgen.net/npm/v/react-native-dotenv)](https://www.npmjs.com/package/react-native-dotenv) | ||
[![dependencies Status](https://badgen.net/david/dep/goatandsheep/react-native-dotenv)](https://david-dm.org/goatandsheep/react-native-dotenv) | ||
[![codecov](https://badgen.net/codecov/c/github/goatandsheep/react-native-dotenv)](https://codecov.io/gh/goatandsheep/react-native-dotenv) | ||
[![XO code style](https://badgen.net/badge/code%20style/XO/cyan)](https://github.com/xojs/xo) | ||
## Install | ||
## Installation | ||
```sh | ||
$ npm install react-native-dotenv --save-dev | ||
$ npm install react-native-dotenv | ||
``` | ||
Add the `react-native-dotenv` preset to your **.babelrc** file at the project root. | ||
## Usage | ||
### RN (0.56+) (Babel 7) | ||
**.babelrc** | ||
```json | ||
{ | ||
"presets": ["react-native", "module:react-native-dotenv"] | ||
"plugins": [ | ||
["dotenv-import", { | ||
"moduleName": "@env", | ||
"path": ".env", | ||
"blacklist": null, | ||
"whitelist": null, | ||
"safe": false, | ||
"allowUndefined": false | ||
}] | ||
] | ||
} | ||
``` | ||
### RN (<0.56) | ||
```json | ||
{ | ||
"presets": ["react-native", "react-native-dotenv"] | ||
} | ||
**.env** | ||
```dosini | ||
API_URL=https://api.example.org | ||
API_TOKEN= | ||
``` | ||
If you haven't got **.babelrc** set up for React Native, remember to install `babel-preset-react-native` first. | ||
In **users.js** | ||
```sh | ||
$ npm install babel-preset-react-native --save-dev | ||
```js | ||
import {API_URL, API_TOKEN} from "@env" | ||
fetch(`${API_URL}/users`, { | ||
headers: { | ||
'Authorization': `Bearer ${API_TOKEN}` | ||
} | ||
}) | ||
``` | ||
## Usage | ||
## White and black lists | ||
Add your app configuration in an **.env** file. | ||
It is possible to limit the scope of env variables that will be imported by specifying a `whitelist` and/or a `blacklist` as an array of strings. | ||
```json | ||
{ | ||
"plugins": [ | ||
["dotenv-import", { | ||
"blacklist": [ | ||
"GITHUB_TOKEN" | ||
] | ||
}] | ||
] | ||
} | ||
``` | ||
API_KEY=lorem | ||
ANOTHER_CONFIG=foobar | ||
```json | ||
{ | ||
"plugins": [ | ||
["dotenv-import", { | ||
"whitelist": [ | ||
"API_URL", | ||
"API_TOKEN" | ||
] | ||
}] | ||
] | ||
} | ||
``` | ||
Now you can import it in your **.js** file. | ||
## Safe mode | ||
```js | ||
import { API_KEY, ANOTHER_CONFIG } from 'react-native-dotenv' | ||
Enable safe mode to only allow environment variables defined in the `.env` file. This will completely ignore everything that is already defined in the environment. | ||
ApiClient.init(API_KEY, ANOTHER_CONFIG) | ||
The `.env` file has to exist. | ||
```json | ||
{ | ||
"plugins": [ | ||
["dotenv-import", { | ||
"safe": true | ||
}] | ||
] | ||
} | ||
``` | ||
## How does it work? | ||
## Allow undefined | ||
As you can see, it's implemented as a babel plugin. All referenced imported members are replaced as the values specified in the **.env** file. | ||
Allow importing undefined variables, their value will be `undefined`. | ||
The example above will get compiled as below. | ||
```json | ||
{ | ||
"plugins": [ | ||
["dotenv-import", { | ||
"allowUndefined": true | ||
}] | ||
] | ||
} | ||
``` | ||
```js | ||
import {UNDEFINED_VAR} from '@env' | ||
ApiClient.init('lorem', 'foobar') | ||
console.log(UNDEFINED_VAR === undefined) // true | ||
``` | ||
## FAQ | ||
When `false` (default behavior), an error will be thrown. | ||
### Changes to .env file is not updated | ||
## Caveats | ||
Manually edit the file importing `react-native-dotenv` by either adding an empty line or whitespace will work. | ||
When using with [`babel-loader`](https://github.com/babel/babel-loader) with caching enabled you will run into issues where environment changes wonβt be picked up. | ||
This is due to the fact that `babel-loader` computes a `cacheIdentifier` that does not take your environment into account. | ||
### Can I use different **.env** settings for production ? | ||
You can easily clear the cache: | ||
Yes, simply create a separate **.env.production** file and the default release process of react-native will pickup the right config. | ||
#### iOS | ||
You can use the **Release** configuration to launch the Simulator. (Only supported in RN v0.39+) | ||
```shell | ||
rm -rf node_modules/.cache/babel-loader/* | ||
``` | ||
react-native run-ios --configuration Release | ||
``` | ||
#### Android | ||
1. `Commandβ` + `M` to launch the developer menu in Android emulator. | ||
2. Tap **DevSettings**. | ||
3. Toggle **JS Dev Mode**. | ||
Or you can override the default `cacheIdentifier` to include some of your environment variables. | ||
### Can I have more than `production` & `development` environment configs? | ||
Multi-environment is still a work in progress. | ||
Sadly, it's not available so far. One of the workaround is generating **.env** file before triggering RN's bundle script automatically using either shell script or your own custom build pipeline. | ||
## Credits | ||
## Contact | ||
* Based on [David Chang](https://github.com/zetachang)βs works on [babel-plugin-dotenv](https://github.com/zetachang/react-native-dotenv/tree/master/babel-plugin-dotenv). | ||
* Also based on [Bertrand Marron](https://github.com/tusbar)'s works on [babel-plugin-dotenv-import](https://github.com/tusbar/babel-plugin-dotenv-import). | ||
[David Chang](http://github.com/zetachang) | ||
[@zetachang](https://twitter.com/zetachang) | ||
## Miscellaneous | ||
## LICENSE | ||
MIT License, see LICENSE file for detail. | ||
``` | ||
ββ ββ | ||
ββ(βββ)ββ | ||
ββ(βββ)ββ | ||
ββ(βββ)ββ | ||
ββ(βββ)ββ | ||
ββ(βββ)ββ | ||
ββ(βββ)ββ | ||
``` |
Sorry, the diff of this file is not supported yet
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
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 4 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
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Trivial Package
Supply chain riskPackages less than 10 lines of code are easily copied into your own project and may not warrant the additional supply chain risk of an external dependency.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
18821
51
188
0
0
152
5
9
2
+ Addeddotenv@^8.0.0
+ Addeddotenv@8.6.0(transitive)
- Removedbabel-plugin-dotenv@0.1.1
- Removedbabel-plugin-dotenv@0.1.1(transitive)
- Removeddotenv@2.0.0(transitive)