Skip to content

Conversation

@hyungwookchoi
Copy link
Contributor

@hyungwookchoi hyungwookchoi commented Dec 23, 2025

fixes #6052

Summary by CodeRabbit

Release Notes

  • New Features

    • Environment variables are now dynamically loaded and injected as define values based on build mode
    • Automatic define generation for environment variables with fallback support
  • Tests

    • Added comprehensive test coverage for environment loading functionality across different modes and configurations

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 23, 2025

Walkthrough

Modified the load-env-plugin to use the config hook instead of configResolved, enabling dynamic environment variable loading based on build mode. The plugin now loads env files with loadEnv(), generates define mappings for process.env variables, and merges them with user-provided defines. Comprehensive test suite added to validate behavior across modes and file precedence.

Changes

Cohort / File(s) Summary
Plugin Implementation
packages/start-plugin-core/src/load-env-plugin/plugin.ts
Changed hook from configResolved to config(userConfig, { mode }) to enable dynamic env loading. Determines root from userConfig.root or process.cwd(), loads environment using loadEnv(mode, root, ''), builds a define map from process.env entries, and returns merged define object combining user-provided and env-derived values.
Test Suite
packages/start-plugin-core/tests/load-env/load-env.test.ts
New comprehensive test suite covering basic .env loading into process.env and define mapping, file merging with correct precedence per mode, mode-specific file loading (.env.development, .env.production), define object generation with string literals, preservation of existing user-provided defines, and fallback behavior when root is unspecified. Tests use dynamic test directories with cleanup.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

package: start-plugin-core

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The code changes directly implement the solution for issue #6052 by loading env files in the config hook with mode-specific merging and adding comprehensive tests to validate the fix.
Out of Scope Changes check ✅ Passed All changes are tightly focused on fixing environment variable loading and adding related tests; no unrelated modifications detected.
Title check ✅ Passed The title accurately describes the main changes: enhancing environment variable loading in the load-env-plugin and adding comprehensive test coverage for it.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Dec 23, 2025

View your CI Pipeline Execution ↗ for commit 6e1159b

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 9m 55s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 42s View ↗

☁️ Nx Cloud last updated this comment at 2025-12-23 12:51:10 UTC

@hyungwookchoi hyungwookchoi changed the title feat(load-env-plugin): enhance environment variable loading and add tests fix(start-plugin-core): load env files in config hook to ensure mode-specific files are merged Dec 23, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/start-plugin-core/src/load-env-plugin/plugin.ts (1)

20-23: Consider documenting the merge order semantics.

The spread order ...userConfig.define, ...define means environment-loaded defines will override user-provided defines if they share the same keys. While unlikely (user defines and env var keys rarely conflict), this behavior could be surprising.

Consider adding a comment to clarify the intended precedence:

🔎 Suggested documentation
       return {
         define: {
+          // User-provided defines are applied first, then env-based defines override.
+          // This ensures environment variables take precedence as expected.
           ...userConfig.define,
           ...define,
         },
       }
packages/start-plugin-core/tests/load-env/load-env.test.ts (1)

27-128: Consider adding edge case tests for robustness.

While the current test coverage is solid, consider adding tests for these edge cases:

  1. Missing .env files: Verify graceful handling when no env files exist
  2. Empty .env files: Ensure empty files don't cause issues
  3. Special characters in values: Test env values containing quotes, newlines, or other special characters
  4. Invalid .env syntax: Verify behavior with malformed env files

These tests would increase confidence in the plugin's robustness, especially since loadEnv from Vite handles these scenarios internally.

🔎 Example edge case tests
test('should handle missing .env files gracefully', () => {
  // No .env files created
  const plugin = loadEnvPlugin()
  const configHook = (plugin as any).config
  
  const result = configHook({ root: testDir }, { mode: 'development' })
  
  expect(result).toHaveProperty('define')
  expect(Object.keys(result.define).length).toBe(0)
})

test('should handle env values with quotes', () => {
  writeFileSync(join(testDir, '.env'), 'TEST_QUOTED="value with \\"quotes\\""')
  
  const plugin = loadEnvPlugin()
  const configHook = (plugin as any).config
  
  const result = configHook({ root: testDir }, { mode: 'development' })
  
  expect(process.env.TEST_QUOTED).toBeDefined()
  expect(result.define['process.env.TEST_QUOTED']).toContain('quotes')
})
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 73315f1 and 6e1159b.

📒 Files selected for processing (2)
  • packages/start-plugin-core/src/load-env-plugin/plugin.ts
  • packages/start-plugin-core/tests/load-env/load-env.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • packages/start-plugin-core/tests/load-env/load-env.test.ts
  • packages/start-plugin-core/src/load-env-plugin/plugin.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Implement ESLint rules for router best practices using the ESLint plugin router

Files:

  • packages/start-plugin-core/tests/load-env/load-env.test.ts
  • packages/start-plugin-core/src/load-env-plugin/plugin.ts
🧬 Code graph analysis (2)
packages/start-plugin-core/tests/load-env/load-env.test.ts (1)
packages/start-plugin-core/src/load-env-plugin/plugin.ts (1)
  • loadEnvPlugin (4-27)
packages/start-plugin-core/src/load-env-plugin/plugin.ts (1)
packages/start-plugin-core/src/create-server-fn-plugin/compiler.ts (1)
  • mode (313-315)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Preview
  • GitHub Check: Test
🔇 Additional comments (5)
packages/start-plugin-core/src/load-env-plugin/plugin.ts (2)

8-24: Implementation correctly addresses the environment loading issue, but consider type safety.

The new config hook implementation properly loads environment variables based on mode and generates the necessary define mappings. The approach of using loadEnv(mode, root, '') with an empty prefix ensures all environment variables are loaded, which aligns with the PR objectives to fix issue #6052.

However, there's a type safety concern with the define variable on line 14.

Type safety issue:

Line 14 declares define as Record<string, string>, but userConfig.define can contain values of type any according to Vite's configuration types. This could lead to type inconsistencies when merging.

🔎 Suggested fix for type safety
-      const define: Record<string, string> = {}
+      const define: Record<string, any> = {}
       for (const [key, value] of Object.entries(env)) {
         define[`process.env.${key}`] = JSON.stringify(value)
       }

As per coding guidelines, TypeScript strict mode requires extensive type safety for all code.


12-12: Verify the implications of mutating global process.env.

The plugin mutates process.env globally with Object.assign(process.env, env). While this is likely intentional to make environment variables accessible throughout the Node.js process, it could have side effects:

  1. Multiple plugin instances or repeated calls could cause unexpected env var accumulation
  2. Tests or other plugins may be affected by this global state mutation
  3. In watch mode, env vars may persist across rebuilds when they shouldn't

Please verify:

  • Is the global mutation of process.env necessary, or should env vars be exposed only through the define config?
  • Should the plugin track which env vars it added to enable cleanup?
  • Are there any scenarios where this could cause issues in development/watch mode?
packages/start-plugin-core/tests/load-env/load-env.test.ts (3)

8-25: Excellent test setup with thorough environment cleanup.

The beforeEach and afterEach hooks properly isolate tests by:

  1. Creating unique temporary directories per test
  2. Cleaning up filesystem changes
  3. Restoring process.env to its original state by removing added keys and reassigning original values

This prevents test pollution and ensures reliable test execution.


27-128: Comprehensive test coverage validates the plugin behavior.

The test suite thoroughly validates:

  • Base .env file loading and define generation (lines 27-37)
  • Correct precedence of mode-specific files over base files (lines 39-57, 59-89)
  • Mode-aware loading for both development and production (lines 59-89)
  • Define config generation with proper JSON stringification (lines 91-100)
  • Preservation of user-provided define mappings (lines 102-118)
  • Fallback behavior when root is unspecified (lines 120-127)

These tests validate the fix for issue #6052 where environment variables weren't being merged correctly.


31-31: Type assertion is necessary for testing internal plugin hooks.

The pattern (plugin as any).config is used throughout to access the internal config hook for testing. This is acceptable for test code since:

  1. Vite plugins don't expose their hooks as part of the public API
  2. Direct hook testing provides more granular verification than integration tests
  3. The tests validate both side effects (process.env) and return values (define)

No changes needed, but be aware this creates coupling to the plugin's internal structure.

Also applies to: 50-50, 68-68, 84-84, 95-95, 106-106, 122-122

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 23, 2025

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@6202

@tanstack/directive-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/directive-functions-plugin@6202

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@6202

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@6202

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/nitro-v2-vite-plugin@6202

@tanstack/react-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@6202

@tanstack/react-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@6202

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-ssr-query@6202

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@6202

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@6202

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@6202

@tanstack/router-cli

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@6202

@tanstack/router-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@6202

@tanstack/router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@6202

@tanstack/router-devtools-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@6202

@tanstack/router-generator

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@6202

@tanstack/router-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@6202

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-ssr-query-core@6202

@tanstack/router-utils

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@6202

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@6202

@tanstack/server-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/server-functions-plugin@6202

@tanstack/solid-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@6202

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@6202

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-ssr-query@6202

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@6202

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@6202

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@6202

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@6202

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-fn-stubs@6202

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@6202

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@6202

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-static-server-functions@6202

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@6202

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@6202

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@6202

@tanstack/vue-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router@6202

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-devtools@6202

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-ssr-query@6202

@tanstack/vue-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start@6202

@tanstack/vue-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-client@6202

@tanstack/vue-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-server@6202

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@6202

commit: 6e1159b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Start not loading environment variables from .env.*

1 participant