diff --git a/CHANGELOG.md b/CHANGELOG.md index f7ee050..08b6d16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,13 @@ All notable changes to this project are documented in this file. -## [Unreleased](https://github.com/dotenvx/react-native-dotenv/compare/v4.1.0...main) +## [Unreleased](https://github.com/dotenvx/react-native-dotenv/compare/v4.1.1...main) + +## [4.1.1](https://github.com/dotenvx/react-native-dotenv/compare/v4.1.0...v4.1.1) (2026-07-28) + +### Changed + +- Log `◇ injected env` once per process so Metro does not spam it on every file when `api.cache(false)`. ## [4.1.0](https://github.com/dotenvx/react-native-dotenv/compare/v4.0.0...v4.1.0) (2026-07-28) diff --git a/README.md b/README.md index 1e79b47..b414dd1 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,9 @@ On transform you'll see a message on stderr (same style as dotenv): ◇ injected env (2) from .env ``` -Set `quiet: true` in the plugin options to suppress it. +Metro may prefix worker logs with `|`. Expo also prints its own `env: load .env` line — that is Expo's built-in loader, not this plugin. + +Set `quiet: true` in the plugin options to suppress the `◇ injected env` message.   diff --git a/index.js b/index.js index 953c0c4..333cfe6 100644 --- a/index.js +++ b/index.js @@ -16,13 +16,22 @@ function parseDotenvFile (filepath, verbose = false) { } } +// Babel may re-instantiate this plugin per file (e.g. api.cache(false)). Log once +// per process for the same message so Metro workers do not spam stderr. +const loggedInjectMessages = new Set() + function logInjectedEnv (fileEnv, loadedPaths) { const keysCount = Object.keys(fileEnv).length - if (loadedPaths.length > 0) { - console.error(`◇ injected env (${keysCount}) from ${loadedPaths.join(', ')}`) - } else { - console.error(`◇ injected env (${keysCount})`) + const message = loadedPaths.length > 0 + ? `◇ injected env (${keysCount}) from ${loadedPaths.join(', ')}` + : `◇ injected env (${keysCount})` + + if (loggedInjectMessages.has(message)) { + return } + + loggedInjectMessages.add(message) + console.error(message) } function undefObjectAssign (targetObject, sourceObject) { diff --git a/tests/index.test.js b/tests/index.test.js index 55f75c6..c9ea336 100644 --- a/tests/index.test.js +++ b/tests/index.test.js @@ -50,6 +50,20 @@ describe('react-native-dotenv', () => { expect(console.error.mock.calls.some(call => /^◇ injected env \(\d+\) from /.test(String(call[0])))).toBe(true) }) + it('should log injected env only once per process', () => { + jest.resetModules() + const plugin = require('../index.js') + const babelOpts = { + configFile: false, + babelrc: false, + plugins: [[plugin, { path: FIXTURES + 'default/.env' }]] + } + transformSync('import { API_KEY } from "@env"', babelOpts) + transformSync('import { API_KEY } from "@env"', babelOpts) + const injectLogs = console.error.mock.calls.filter(call => String(call[0]).includes('injected env')) + expect(injectLogs).toHaveLength(1) + }) + it('should not log injected env when quiet', () => { jest.resetModules() transformSync('import { API_KEY } from "@env"', {