@expo/env
Advanced tools
Comparing version 0.4.1-canary-20241211-61c49bd to 1.0.0
/// <reference types="node" /> | ||
/** Determine if the `.env` files are enabled or not, through `EXPO_NO_DOTENV` */ | ||
export declare function isEnabled(): boolean; | ||
/** All conventional modes that should not cause warnings */ | ||
export declare const KNOWN_MODES: string[]; | ||
/** The environment variable name to use when marking the environment as loaded */ | ||
export declare const LOADED_ENV_NAME = "__EXPO_ENV_LOADED"; | ||
/** | ||
* Copyright © 2023 650 Industries. | ||
* Get a list of all `.env*` files based on the `NODE_ENV` mode. | ||
* This returns a list of files, in order of highest priority to lowest priority. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* @see https://github.com/bkeepers/dotenv/tree/v3.1.4#customizing-rails | ||
*/ | ||
import { getFiles, isEnabled } from './env'; | ||
declare const get: (projectRoot: string, options?: { | ||
silent?: boolean | undefined; | ||
force?: boolean | undefined; | ||
}) => { | ||
env: Record<string, string | undefined>; | ||
export declare function getEnvFiles({ mode, silent, }?: { | ||
/** The mode to use when creating the list of `.env*` files, defaults to `NODE_ENV` */ | ||
mode?: string; | ||
/** If possible misconfiguration warnings should be logged, or only logged as debug log */ | ||
silent?: boolean; | ||
}): string[]; | ||
/** | ||
* Parse all environment variables using the list of `.env*` files, in order of higest priority to lowest priority. | ||
* This does not check for collisions of existing system environment variables, or mutates the system environment variables. | ||
*/ | ||
export declare function parseEnvFiles(envFiles: string[], { systemEnv, }?: { | ||
/** The system environment to use when expanding environment variables, defaults to `process.env` */ | ||
systemEnv?: NodeJS.ProcessEnv; | ||
}): { | ||
env: Record<string, string>; | ||
files: string[]; | ||
}, load: (projectRoot: string, options?: { | ||
silent?: boolean | undefined; | ||
force?: boolean | undefined; | ||
}) => NodeJS.ProcessEnv; | ||
export { getFiles, get, load, isEnabled }; | ||
}; | ||
/** | ||
* Parse all environment variables using the list of `.env*` files, and mutate the system environment with these variables. | ||
* This won't override existing environment variables defined in the system environment. | ||
* Once the mutations are done, this will also set a propert `__EXPO_ENV=true` on the system env to avoid multiple mutations. | ||
* This check can be disabled through `{ force: true }`. | ||
*/ | ||
export declare function loadEnvFiles(envFiles: string[], { force, silent, systemEnv, }?: Parameters<typeof parseEnvFiles>[1] & { | ||
/** If the environment variables should be applied to the system environment, regardless of previous mutations */ | ||
force?: boolean; | ||
/** If possible misconfiguration warnings should be logged, or only logged as debug log */ | ||
silent?: boolean; | ||
}): { | ||
result: "skipped"; | ||
loaded: any; | ||
} | { | ||
loaded: string[]; | ||
env: Record<string, string>; | ||
files: string[]; | ||
result: "loaded"; | ||
}; | ||
/** | ||
* Parse all environment variables using the detected list of `.env*` files from a project. | ||
* This does not check for collisions of existing system environment variables, or mutates the system environment variables. | ||
*/ | ||
export declare function parseProjectEnv(projectRoot: string, options?: Parameters<typeof getEnvFiles>[0] & Parameters<typeof parseEnvFiles>[1]): { | ||
env: Record<string, string>; | ||
files: string[]; | ||
}; | ||
/** | ||
* Parse all environment variables using the detected list of `.env*` files from a project. | ||
* This won't override existing environment variables defined in the system environment. | ||
* Once the mutations are done, this will also set a propert `__EXPO_ENV=true` on the system env to avoid multiple mutations. | ||
* This check can be disabled through `{ force: true }`. | ||
*/ | ||
export declare function loadProjectEnv(projectRoot: string, options?: Parameters<typeof getEnvFiles>[0] & Parameters<typeof loadEnvFiles>[1]): { | ||
result: "skipped"; | ||
loaded: any; | ||
} | { | ||
loaded: string[]; | ||
env: Record<string, string>; | ||
files: string[]; | ||
result: "loaded"; | ||
}; | ||
/** Log the loaded environment info from the loaded results */ | ||
export declare function logLoadedEnv(envInfo: ReturnType<typeof loadEnvFiles>, options?: Parameters<typeof loadEnvFiles>[1]): { | ||
result: "skipped"; | ||
loaded: any; | ||
} | { | ||
loaded: string[]; | ||
env: Record<string, string>; | ||
files: string[]; | ||
result: "loaded"; | ||
}; | ||
/** | ||
* Get the environment variables without mutating the environment. | ||
* This returns memoized values unless the `force` property is provided. | ||
* | ||
* @deprecated use {@link parseProjectEnv} instead | ||
*/ | ||
export declare function get(projectRoot: string, { force, silent, }?: { | ||
force?: boolean; | ||
silent?: boolean; | ||
}): { | ||
env: Record<string, string>; | ||
files: string[]; | ||
}; | ||
/** | ||
* Load environment variables from .env files and mutate the current `process.env` with the results. | ||
* | ||
* @deprecated use {@link loadProjectEnv} instead | ||
*/ | ||
export declare function load(projectRoot: string, options?: { | ||
force?: boolean; | ||
silent?: boolean; | ||
}): NodeJS.ProcessEnv; | ||
/** | ||
* Get a list of all `.env*` files based on the `NODE_ENV` mode. | ||
* This returns a list of files, in order of highest priority to lowest priority. | ||
* | ||
* @deprecated use {@link getEnvFiles} instead | ||
* @see https://github.com/bkeepers/dotenv/tree/v3.1.4#customizing-rails | ||
*/ | ||
export declare function getFiles(mode: string | undefined, { silent }?: { | ||
silent?: boolean; | ||
}): string[]; |
@@ -6,19 +6,16 @@ "use strict"; | ||
}); | ||
exports.get = void 0; | ||
Object.defineProperty(exports, "getFiles", { | ||
enumerable: true, | ||
get: function () { | ||
return _env().getFiles; | ||
} | ||
}); | ||
Object.defineProperty(exports, "isEnabled", { | ||
enumerable: true, | ||
get: function () { | ||
return _env().isEnabled; | ||
} | ||
}); | ||
exports.load = void 0; | ||
function _env() { | ||
const data = require("./env"); | ||
_env = function () { | ||
exports.LOADED_ENV_NAME = exports.KNOWN_MODES = void 0; | ||
exports.get = get; | ||
exports.getEnvFiles = getEnvFiles; | ||
exports.getFiles = getFiles; | ||
exports.isEnabled = isEnabled; | ||
exports.load = load; | ||
exports.loadEnvFiles = loadEnvFiles; | ||
exports.loadProjectEnv = loadProjectEnv; | ||
exports.logLoadedEnv = logLoadedEnv; | ||
exports.parseEnvFiles = parseEnvFiles; | ||
exports.parseProjectEnv = parseProjectEnv; | ||
function _chalk() { | ||
const data = _interopRequireDefault(require("chalk")); | ||
_chalk = function () { | ||
return data; | ||
@@ -28,15 +25,334 @@ }; | ||
} | ||
function dotenv() { | ||
const data = _interopRequireWildcard(require("dotenv")); | ||
dotenv = function () { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _dotenvExpand() { | ||
const data = require("dotenv-expand"); | ||
_dotenvExpand = function () { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _getenv() { | ||
const data = require("getenv"); | ||
_getenv = function () { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _nodeConsole() { | ||
const data = _interopRequireDefault(require("node:console")); | ||
_nodeConsole = function () { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _nodeFs() { | ||
const data = _interopRequireDefault(require("node:fs")); | ||
_nodeFs = function () { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _nodePath() { | ||
const data = _interopRequireDefault(require("node:path")); | ||
_nodePath = function () { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } | ||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } | ||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } | ||
const debug = require('debug')('expo:env'); | ||
/** Determine if the `.env` files are enabled or not, through `EXPO_NO_DOTENV` */ | ||
function isEnabled() { | ||
return !(0, _getenv().boolish)('EXPO_NO_DOTENV', false); | ||
} | ||
/** All conventional modes that should not cause warnings */ | ||
const KNOWN_MODES = exports.KNOWN_MODES = ['development', 'test', 'production']; | ||
/** The environment variable name to use when marking the environment as loaded */ | ||
const LOADED_ENV_NAME = exports.LOADED_ENV_NAME = '__EXPO_ENV_LOADED'; | ||
/** | ||
* Copyright © 2023 650 Industries. | ||
* Get a list of all `.env*` files based on the `NODE_ENV` mode. | ||
* This returns a list of files, in order of highest priority to lowest priority. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* @see https://github.com/bkeepers/dotenv/tree/v3.1.4#customizing-rails | ||
*/ | ||
function getEnvFiles({ | ||
mode = process.env.NODE_ENV, | ||
silent | ||
} = {}) { | ||
if (!isEnabled()) { | ||
debug(`Skipping .env files because EXPO_NO_DOTENV is defined`); | ||
return []; | ||
} | ||
const logError = silent ? debug : _nodeConsole().default.error; | ||
const logWarning = silent ? debug : _nodeConsole().default.warn; | ||
if (!mode) { | ||
logError(`The NODE_ENV environment variable is required but was not specified. Ensure the project is bundled with Expo CLI or NODE_ENV is set. Using only .env.local and .env`); | ||
return ['.env.local', '.env']; | ||
} | ||
if (!KNOWN_MODES.includes(mode)) { | ||
logWarning(`NODE_ENV="${mode}" is non-conventional and might cause development code to run in production. Use "development", "test", or "production" instead. Continuing with non-conventional mode`); | ||
} | ||
const { | ||
get, | ||
load | ||
} = (0, _env().createControlledEnvironment)(); | ||
exports.load = load; | ||
exports.get = get; | ||
// see: https://github.com/bkeepers/dotenv/tree/v3.1.4#customizing-rails | ||
return [`.env.${mode}.local`, | ||
// Don't include `.env.local` for `test` environment | ||
// since normally you expect tests to produce the same | ||
// results for everyone | ||
mode !== 'test' && `.env.local`, `.env.${mode}`, `.env`].filter(Boolean); | ||
} | ||
/** | ||
* Parse all environment variables using the list of `.env*` files, in order of higest priority to lowest priority. | ||
* This does not check for collisions of existing system environment variables, or mutates the system environment variables. | ||
*/ | ||
function parseEnvFiles(envFiles, { | ||
systemEnv = process.env | ||
} = {}) { | ||
if (!isEnabled()) { | ||
debug(`Skipping .env files because EXPO_NO_DOTENV is defined`); | ||
return { | ||
env: {}, | ||
files: [] | ||
}; | ||
} | ||
// Load environment variables from .env* files. Suppress warnings using silent | ||
// if this file is missing. Dotenv will only parse the environment variables, | ||
// `@expo/env` will set the resulting variables to the current process. | ||
// Variable expansion is supported in .env files, and executed as final step. | ||
// https://github.com/motdotla/dotenv | ||
// https://github.com/motdotla/dotenv-expand | ||
const loadedEnvVars = {}; | ||
const loadedEnvFiles = []; | ||
// Iterate over each dotenv file in lowest prio to highest prio order. | ||
// This step won't write to the process.env, but will overwrite the parsed envs. | ||
[...envFiles].reverse().forEach(envFile => { | ||
try { | ||
const envFileContent = _nodeFs().default.readFileSync(envFile, 'utf8'); | ||
const envFileParsed = dotenv().parse(envFileContent); | ||
// If there are parsing issues, mark the file as not-parsed | ||
if (!envFileParsed) { | ||
return debug(`Failed to load environment variables from: ${envFile}%s`); | ||
} | ||
loadedEnvFiles.push(envFile); | ||
debug(`Loaded environment variables from: ${envFile}`); | ||
for (const key of Object.keys(envFileParsed)) { | ||
if (typeof loadedEnvVars[key] !== 'undefined') { | ||
debug(`"${key}" is already defined and overwritten by: ${envFile}`); | ||
} | ||
loadedEnvVars[key] = envFileParsed[key]; | ||
} | ||
} catch (error) { | ||
if ('code' in error && error.code === 'ENOENT') { | ||
return debug(`${envFile} does not exist, skipping this env file`); | ||
} | ||
if ('code' in error && error.code === 'EISDIR') { | ||
return debug(`${envFile} is a directory, skipping this env file`); | ||
} | ||
if ('code' in error && error.code === 'EACCES') { | ||
return debug(`No permission to read ${envFile}, skipping this env file`); | ||
} | ||
throw error; | ||
} | ||
}); | ||
return { | ||
env: expandEnvFromSystem(loadedEnvVars, systemEnv), | ||
files: loadedEnvFiles.reverse() | ||
}; | ||
} | ||
/** | ||
* Parse all environment variables using the list of `.env*` files, and mutate the system environment with these variables. | ||
* This won't override existing environment variables defined in the system environment. | ||
* Once the mutations are done, this will also set a propert `__EXPO_ENV=true` on the system env to avoid multiple mutations. | ||
* This check can be disabled through `{ force: true }`. | ||
*/ | ||
function loadEnvFiles(envFiles, { | ||
force, | ||
silent = false, | ||
systemEnv = process.env | ||
} = {}) { | ||
if (!force && systemEnv[LOADED_ENV_NAME]) { | ||
return { | ||
result: 'skipped', | ||
loaded: JSON.parse(systemEnv[LOADED_ENV_NAME]) | ||
}; | ||
} | ||
const parsed = parseEnvFiles(envFiles, { | ||
systemEnv | ||
}); | ||
const loadedEnvKeys = []; | ||
for (const key in parsed.env) { | ||
if (typeof systemEnv[key] !== 'undefined') { | ||
debug(`"${key}" is already defined and IS NOT overwritten`); | ||
} else { | ||
systemEnv[key] = parsed.env[key]; | ||
loadedEnvKeys.push(key); | ||
} | ||
} | ||
// Mark the environment as loaded | ||
systemEnv[LOADED_ENV_NAME] = JSON.stringify(loadedEnvKeys); | ||
return { | ||
result: 'loaded', | ||
...parsed, | ||
loaded: loadedEnvKeys | ||
}; | ||
} | ||
/** | ||
* Expand the parsed environment variables using the existing system environment variables. | ||
* This does not mutate the existing system environment variables, and only returns the expanded variables. | ||
*/ | ||
function expandEnvFromSystem(parsedEnv, systemEnv = process.env) { | ||
const expandedEnv = {}; | ||
// Pass a clone of the system environment variables to avoid mutating the original environment. | ||
// When the expansion is done, we only store the environment variables that were initially parsed from `parsedEnv`. | ||
const allExpandedEnv = (0, _dotenvExpand().expand)({ | ||
parsed: parsedEnv, | ||
processEnv: { | ||
...systemEnv | ||
} | ||
}); | ||
if (allExpandedEnv.error) { | ||
_nodeConsole().default.error(`Failed to expand environment variables, using non-expanded environment variables: ${allExpandedEnv.error}`); | ||
return parsedEnv; | ||
} | ||
// Only store the values that were initially parsed, from `parsedEnv`. | ||
for (const key of Object.keys(parsedEnv)) { | ||
if (allExpandedEnv.parsed?.[key]) { | ||
expandedEnv[key] = allExpandedEnv.parsed[key]; | ||
} | ||
} | ||
return expandedEnv; | ||
} | ||
/** | ||
* Parse all environment variables using the detected list of `.env*` files from a project. | ||
* This does not check for collisions of existing system environment variables, or mutates the system environment variables. | ||
*/ | ||
function parseProjectEnv(projectRoot, options) { | ||
return parseEnvFiles(getEnvFiles(options).map(envFile => _nodePath().default.join(projectRoot, envFile)), options); | ||
} | ||
/** | ||
* Parse all environment variables using the detected list of `.env*` files from a project. | ||
* This won't override existing environment variables defined in the system environment. | ||
* Once the mutations are done, this will also set a propert `__EXPO_ENV=true` on the system env to avoid multiple mutations. | ||
* This check can be disabled through `{ force: true }`. | ||
*/ | ||
function loadProjectEnv(projectRoot, options) { | ||
return loadEnvFiles(getEnvFiles(options).map(envFile => _nodePath().default.join(projectRoot, envFile)), options); | ||
} | ||
/** Log the loaded environment info from the loaded results */ | ||
function logLoadedEnv(envInfo, options = {}) { | ||
// Skip when running in force mode, or no environment variables are loaded | ||
if (options.force || options.silent || !envInfo.loaded.length) return envInfo; | ||
// Log the loaded environment files, when not skipped | ||
if (envInfo.result === 'loaded') { | ||
_nodeConsole().default.log(_chalk().default.gray('env: load', envInfo.files.map(file => _nodePath().default.basename(file)).join(' '))); | ||
} | ||
// Log the loaded environment variables | ||
_nodeConsole().default.log(_chalk().default.gray('env: export', envInfo.loaded.join(' '))); | ||
return envInfo; | ||
} | ||
// Legacy API - for backwards compatibility | ||
let memo = null; | ||
/** | ||
* Get the environment variables without mutating the environment. | ||
* This returns memoized values unless the `force` property is provided. | ||
* | ||
* @deprecated use {@link parseProjectEnv} instead | ||
*/ | ||
function get(projectRoot, { | ||
force, | ||
silent | ||
} = {}) { | ||
if (!isEnabled()) { | ||
debug(`Skipping .env files because EXPO_NO_DOTENV is defined`); | ||
return { | ||
env: {}, | ||
files: [] | ||
}; | ||
} | ||
if (force || !memo) { | ||
memo = parseProjectEnv(projectRoot, { | ||
silent | ||
}); | ||
} | ||
return memo; | ||
} | ||
/** | ||
* Load environment variables from .env files and mutate the current `process.env` with the results. | ||
* | ||
* @deprecated use {@link loadProjectEnv} instead | ||
*/ | ||
function load(projectRoot, options = {}) { | ||
if (!isEnabled()) { | ||
debug(`Skipping .env files because EXPO_NO_DOTENV is defined`); | ||
return process.env; | ||
} | ||
const envInfo = get(projectRoot, options); | ||
const loadedEnvKeys = []; | ||
for (const key in envInfo.env) { | ||
if (typeof process.env[key] !== 'undefined') { | ||
debug(`"${key}" is already defined and IS NOT overwritten`); | ||
} else { | ||
// Avoid creating a new object, mutate it instead as this causes problems in Bun | ||
process.env[key] = envInfo.env[key]; | ||
loadedEnvKeys.push(key); | ||
} | ||
} | ||
// Port the result of `get` to the newer result object | ||
logLoadedEnv({ | ||
...envInfo, | ||
result: 'loaded', | ||
loaded: loadedEnvKeys | ||
}, options); | ||
return process.env; | ||
} | ||
/** | ||
* Get a list of all `.env*` files based on the `NODE_ENV` mode. | ||
* This returns a list of files, in order of highest priority to lowest priority. | ||
* | ||
* @deprecated use {@link getEnvFiles} instead | ||
* @see https://github.com/bkeepers/dotenv/tree/v3.1.4#customizing-rails | ||
*/ | ||
function getFiles(mode, { | ||
silent = false | ||
} = {}) { | ||
if (!isEnabled()) { | ||
debug(`Skipping .env files because EXPO_NO_DOTENV is defined`); | ||
return []; | ||
} | ||
return getEnvFiles({ | ||
mode, | ||
silent | ||
}); | ||
} | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@expo/env", | ||
"version": "0.4.1-canary-20241211-61c49bd", | ||
"version": "1.0.0", | ||
"description": "hydrate environment variables from .env files into process.env", | ||
@@ -39,7 +39,8 @@ "main": "build/index.js", | ||
"@types/getenv": "^1.0.0", | ||
"expo-module-scripts": "4.0.3-canary-20241211-61c49bd" | ||
"expo-module-scripts": "^4.0.0" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
}, | ||
"gitHead": "6b8febdc8075b9ea31120f02aca11595c116dc1d" | ||
} |
Sorry, the diff of this file is not supported yet
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
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
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
41312
445
0
6
8
2