Skip to content

fix(config): apply $production/$development layers when NODE_ENV is unset#4066

Open
jlgrimes wants to merge 3 commits intonitrojs:mainfrom
jlgrimes:fix/issue-3052-env-layer-default
Open

fix(config): apply $production/$development layers when NODE_ENV is unset#4066
jlgrimes wants to merge 3 commits intonitrojs:mainfrom
jlgrimes:fix/issue-3052-env-layer-default

Conversation

@jlgrimes
Copy link

@jlgrimes jlgrimes commented Mar 2, 2026

🔗 Linked issue

Resolves #3052

❓ Type of change

  • 🐞 Bug fix (a non-breaking change that fixes an issue)

📚 Description

Nitro uses c12 for config loading, but when NODE_ENV is unset it currently forwards no envName, so c12 skips $production and $development layers entirely.

This causes production deployments (e.g. Cloudflare Pages) to ignore $production config blocks unless NODE_ENV is manually set.

What changed

  • Default c12 envName from configOverrides.dev:
    • development when dev: true
    • production when dev: false
  • Keep opts.c12.envName override support intact (explicit override still wins).
  • Added regression tests that verify both $production and $development layers are applied correctly when NODE_ENV is unset.

Validation

  • pnpm vitest test/unit/config-loader-env.test.ts

@jlgrimes jlgrimes requested a review from pi0 as a code owner March 2, 2026 03:32
@vercel
Copy link

vercel bot commented Mar 2, 2026

@jlgrimes is attempting to deploy a commit to the Nitro Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Mar 2, 2026

📝 Walkthrough

Walkthrough

Adds an envName computed from opts.c12?.envName (or "development" when dev is true, otherwise "production") and passes it into config loading; adds unit tests asserting environment-layered config resolution based on NODE_ENV and the dev flag.

Changes

Cohort / File(s) Summary
Configuration loader
src/config/loader.ts
Compute envName from opts.c12?.envName or fallback to "development" (if dev) / "production", and pass it to loadConfig.
Environment-layer tests
test/unit/config-loader-env.test.ts
Add tests that write a fixture nitro.config.ts with base, $production, and $development routeRules; mock nitro/meta; assert correct routeRules selection for combinations of NODE_ENV and dev; clean up temp dirs and restore env.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'fix(config): apply $production/$development layers when NODE_ENV is unset' follows conventional commits format with appropriate fix type and clear, descriptive message.
Description check ✅ Passed The PR description is directly related to the changeset, clearly explaining the bug fix, changes made, and validation approach for applying environment-specific config layers.
Linked Issues check ✅ Passed The PR successfully addresses issue #3052 by implementing logic to derive envName from dev flag when NODE_ENV is unset, ensuring $production/$development layers are applied correctly in production deployments.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked issue: the loader modification implements the fix and tests validate the correct layer application behavior for both development and production scenarios.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

@jlgrimes jlgrimes changed the title fix(config): apply / layers when NODE_ENV is unset fix(config): apply $production/$development layers when NODE_ENV is unset Mar 2, 2026
Copy link

@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.

🧹 Nitpick comments (1)
test/unit/config-loader-env.test.ts (1)

60-61: Consider verifying base layer is preserved alongside env layer.

The fixture defines a base /base route. Adding an assertion for it would confirm that env-specific layers are merged correctly without losing base configuration.

💡 Optional enhancement
     expect(options.routeRules["/prod"]?.headers?.["x-env"]).toBe("production");
     expect(options.routeRules["/dev"]).toBeUndefined();
+    expect(options.routeRules["/base"]?.headers?.["x-env"]).toBe("base");
   });

   it("applies $development when NODE_ENV is unset and dev=true", async () => {
     // ...
     expect(options.routeRules["/dev"]?.headers?.["x-env"]).toBe("development");
     expect(options.routeRules["/prod"]).toBeUndefined();
+    expect(options.routeRules["/base"]?.headers?.["x-env"]).toBe("base");
   });

Also applies to: 71-72

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/unit/config-loader-env.test.ts` around lines 60 - 61, Add assertions
that the base route from the fixture is still present after env layering: check
options.routeRules["/base"] exists and its original properties (e.g., headers,
upstreams, or whatever the fixture defines) match expected values to ensure the
env layer merged rather than replaced the base layer; update both places where
routeRules for env tests are asserted (the blocks that currently check
"/prod"/"/dev") to include these "/base" assertions referencing
options.routeRules.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@test/unit/config-loader-env.test.ts`:
- Around line 60-61: Add assertions that the base route from the fixture is
still present after env layering: check options.routeRules["/base"] exists and
its original properties (e.g., headers, upstreams, or whatever the fixture
defines) match expected values to ensure the env layer merged rather than
replaced the base layer; update both places where routeRules for env tests are
asserted (the blocks that currently check "/prod"/"/dev") to include these
"/base" assertions referencing options.routeRules.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfbb207 and 395a111.

📒 Files selected for processing (2)
  • src/config/loader.ts
  • test/unit/config-loader-env.test.ts

@jlgrimes
Copy link
Author

jlgrimes commented Mar 3, 2026

Added the follow-up test assertions suggested in review:

  • assert /base route remains present in both NODE_ENV-unset paths (dev=false and dev=true)

Commit: 1940d6b

Copy link

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/unit/config-loader-env.test.ts`:
- Around line 45-46: The afterEach cleanup currently does "process.env.NODE_ENV
= originalNodeEnv" which coerces undefined into the string "undefined"; change
the teardown (the afterEach that references originalNodeEnv and
process.env.NODE_ENV) to conditionally restore or remove NODE_ENV: if
originalNodeEnv is defined set process.env.NODE_ENV back to it, otherwise delete
process.env.NODE_ENV so the environment variable is truly unset for subsequent
tests.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 395a111 and 1940d6b.

📒 Files selected for processing (1)
  • test/unit/config-loader-env.test.ts

Copy link

@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.

🧹 Nitpick comments (1)
test/unit/config-loader-env.test.ts (1)

57-81: Consider adding one test for explicit opts.c12.envName override precedence.

Since this PR also preserves explicit override behavior, a focused case (e.g., dev: false + c12.envName: "development") would lock in that contract.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/unit/config-loader-env.test.ts` around lines 57 - 81, Add a test that
asserts explicit opts.c12.envName takes precedence over inferred NODE_ENV/dev
logic: in the same suite call loadOptions({ rootDir: await
createFixtureConfig(), dev: false, c12: { envName: "development" } }) (or
similar shape used by loadOptions) and assert that options.routeRules["/dev"]
has x-env "development", options.routeRules["/prod"] is undefined, and base
still applies; place this alongside the existing tests so it exercises the
loadOptions function and the explicit c12.envName override path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@test/unit/config-loader-env.test.ts`:
- Around line 57-81: Add a test that asserts explicit opts.c12.envName takes
precedence over inferred NODE_ENV/dev logic: in the same suite call
loadOptions({ rootDir: await createFixtureConfig(), dev: false, c12: { envName:
"development" } }) (or similar shape used by loadOptions) and assert that
options.routeRules["/dev"] has x-env "development", options.routeRules["/prod"]
is undefined, and base still applies; place this alongside the existing tests so
it exercises the loadOptions function and the explicit c12.envName override
path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8a5ad140-0e5b-4934-ac1f-283b41867a59

📥 Commits

Reviewing files that changed from the base of the PR and between 1940d6b and ef027e3.

📒 Files selected for processing (1)
  • test/unit/config-loader-env.test.ts

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

$development and $production config keys don't work without setting NODE_ENV

1 participant