# `env.ts` ## Purpose Provides the single environment-detection helper the React surface uses to switch between dev-mode loud-failure and prod-mode soft-fail behaviour. The helper reads at call time (not at module-load time) so test suites that swap `process.env.NODE_ENV` between cases observe the swap without module-cache busting, and edge runtimes without a full Node `process` shim still resolve to a safe default. The package exposes only one helper here intentionally — every other environment check (browser vs server, hydration vs second render, RSC vs client) is a React lifecycle question answered by `useSyncExternalStore` or `useEffect`, not an environment question. ## Features - Call-time `process.env.NODE_ENV` lookup with optional-chain reads so bundlers that statically replace `process.env.NODE_ENV === "production"` with a literal still get the right answer. - Safe fallback: returns `false` (dev mode) when `process` or `process.env` is missing. Loud failure beats silent swallow when the environment is misconfigured. - Zero allocations on the hot path — direct property reads, no string concatenation, no regex. ## Usage: Basic Example ```ts import { isProductionEnv } from "@suaveplan/react-i18n/utils/env"; if (isProductionEnv()) { // soft-fail path } else { throw new ReactI18nError( REACT_I18N_CODES.NO_PROVIDER, "react-i18n.no_provider" ); } ``` ## Usage: Advanced Example ```ts import { isProductionEnv } from "@suaveplan/react-i18n/utils/env"; function recoverableLogOrThrow(err: Error): void { if (isProductionEnv()) { // Soft-fail in production — log via the structured sink so the // failure shows up in dashboards but the user-facing render // continues. log.warn("react-i18n.recoverable_failure", { err }); return; } // Dev: surface the error so the developer sees it immediately. throw err; } ``` ## API Reference ### `isProductionEnv(): boolean` Returns `true` iff `globalThis.process?.env?.NODE_ENV === "production"`. Returns `false` when: - `globalThis.process` is `undefined` (browser without bundler env shim, Deno without a `process` polyfill). - `process.env` is `undefined`. - `process.env.NODE_ENV` is `undefined` or any value other than the exact string `"production"`. ## Implementation Notes - The lookup is intentionally optional-chained on every step rather than guarded by a try/catch. Optional chains evaluate at zero cost on the hot path; try/catch incurs an unwind table. - The function reads `globalThis.process`, not bare `process`. Bare `process` would error under strict-mode ESM in environments that do not synthesise the binding; the global lookup degrades cleanly instead. - The check is deliberately `=== "production"` (case-sensitive, exact match). Webpack/Vite stamp the literal with that exact casing; any other value (including `"PRODUCTION"`, `"prod"`, undefined) means "not production" and the dev-mode branch fires. - The function lives in `utils/` rather than `config/` because it is not configuration — it is environment introspection. Configuration is what the consumer passes to `createI18nConfig(...)`.