Skip to content

feat(nuxt): build-time validation & dynamic runtime proxy#1256

Open
yamcodes wants to merge 22 commits into
devfrom
1243-featnuxt-build-time-validation-codegen
Open

feat(nuxt): build-time validation & dynamic runtime proxy#1256
yamcodes wants to merge 22 commits into
devfrom
1243-featnuxt-build-time-validation-codegen

Conversation

@yamcodes

@yamcodes yamcodes commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Summary

Resolves #1246 (and supersedes the original codegen approach for Nuxt).

What changed

The @arkenv/nuxt module has been completely refactored away from static code generation toward a dynamic runtime proxy that reads environment variables natively from Nuxt's useRuntimeConfig().

Removed

  • runCodegen / generateFactoryCode / generateRuntimeEnvLines — no more env.gen.ts file writes
  • watchSchema / chokidar dependency — replaced by pushing schema paths into nuxt.options.watch (Nuxt's own native watcher)
  • outputPath and codegen options from ModuleOptions / ArkEnvConfigOptions

Added / changed

  • mock-imports.ts — a lightweight useRuntimeConfig() stub (returns { public: process.env, ...process.env }) used by Jiti during build-time schema evaluation and by Vitest tests
  • create-env.tscreateSecurityProxy now imports useRuntimeConfig from #imports and calls it lazily (inside the getter) so the Nuxt instance is always hydrated before access; client keys are read from runtimeConfig.public, server keys from the top-level runtimeConfig
  • tsdown.config.ts#imports and nuxt/app added to neverBundle so the bundler externalises the virtual Nuxt alias
  • config.ts"#imports": mockImportsPath added to Jiti aliases in validateSchema so build-time validation can safely call through to useRuntimeConfig()
  • module.ts — schema files pushed into nuxt.options.watch; validate-only flow at startup, no file writes

Why no codegen in Nuxt

Next.js requires codegen because webpack needs to physically see process.env.NEXT_PUBLIC_X in source at bundle time to inline it. Nuxt resolves public variables dynamically at runtime via its useRuntimeConfig() payload — there is nothing to statically compile. The entire generated runtimeEnv block was pure boilerplate; replacing it with a runtime proxy is both architecturally cleaner and eliminates a class of stale-file bugs.

Docs

  • faq.mdx — new Q: "Does @arkenv/nuxt generate any files?" (answer: no)
  • flat.mdx / strict.mdx — "Register module" step updated to reflect dynamic resolution
  • comparison.mdx — T3 Env comparison updated to distinguish Next.js (codegen) from Nuxt (dynamic)

Tests

All 24 @arkenv/nuxt tests pass (src/module.test.ts, src/config.test.ts, src/index.test.ts, src/validation.test.ts).

@yamcodes yamcodes linked an issue Jun 29, 2026 that may be closed by this pull request
7 tasks
@changeset-bot

changeset-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8f15234

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@arkenv/nuxt Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added docs Adds or changes documentation, or acts as documentation in and of itself example Issues or Pull Requests concerning at least one ArkEnv example. (Found in the `examples/` directory) tests This issue or PR is about adding, removing or changing tests @arkenv/nuxt Issues or Pull Requests involving the Nuxt integration for ArkEnv labels Jun 29, 2026
@pkg-pr-new

pkg-pr-new Bot commented Jun 29, 2026

Copy link
Copy Markdown

Open in StackBlitz

arkenv

npm i https://pkg.pr.new/arkenv@1256

@arkenv/build

npm i https://pkg.pr.new/@arkenv/build@1256

@arkenv/bun-plugin

npm i https://pkg.pr.new/@arkenv/bun-plugin@1256

@arkenv/cli

npm i https://pkg.pr.new/@arkenv/cli@1256

@arkenv/fumadocs-ui

npm i https://pkg.pr.new/@arkenv/fumadocs-ui@1256

@arkenv/nextjs

npm i https://pkg.pr.new/@arkenv/nextjs@1256

@arkenv/nuxt

npm i https://pkg.pr.new/@arkenv/nuxt@1256

@arkenv/vite-plugin

npm i https://pkg.pr.new/@arkenv/vite-plugin@1256

commit: 8f15234

@arkenv-bot

arkenv-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

No results found

All size limits passed!

@arkenv-bot

arkenv-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (Asia/Almaty)
arkenv Ready Ready Preview, Comment Jul 1 2026, 12:53 AM (Asia/Almaty)

@yamcodes yamcodes changed the title fix: feat(nuxt): build-time validation & codegen feat(nuxt): build-time validation & codegen Jun 29, 2026
@github-actions github-actions Bot added the playground Issues or Pull Requests concerning a playground. (Found in the `apps/playgrounds/` directory) label Jun 29, 2026
@yamcodes

Copy link
Copy Markdown
Owner Author

not sure the nuxt integration needs codegen

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

The changeset examples do not match the actual config API, and two runtime issues (an un-catchable process.exit and a global flag race) should be addressed before merge.

Reviewed changes — Adds build-time validation and env.gen.ts codegen to the @arkenv/nuxt module, closely mirroring the existing Next.js integration.

  • Adds setupArkEnv, runCodegen, and validateSchema public helpers in packages/nuxt/src/config.ts.
  • Wires validate and codegen module options (both default true) into the Nuxt module lifecycle.
  • Adds generated env.gen.ts factories for flat, legacy, and strict layouts with Nuxt-specific runtimeEnv (window.__NUXT__.config.public).
  • Updates examples/with-nuxt to the flat-layout generated-factory pattern.
  • Adds test coverage for codegen, validation, and dev file-watching.

⚠️ Changeset examples use incorrect option names and prefix

The changeset's usage examples do not match the actual ArkEnvConfigOptions API. Readers will copy-paste invalid config.

  • The example uses schema, but the option is schemaPath.
  • codegen is shown as { enabled, path, layout }, but the code expects a boolean; path is outputPath and layout is a top-level option.
  • The env.ts example declares NEXT_PUBLIC_API_URL instead of NUXT_PUBLIC_API_URL.

⚠️ setupArkEnv exits the process on validation failure

packages/nuxt/src/config.ts catches validation errors and calls process.exit(1). The Nuxt module path (packages/nuxt/src/module.ts) rethrows the same error instead. A public helper that unconditionally terminates the process is hard to use in tests, scripts, or programmatic integrations.

⚠️ __arkenv_force_server__ global flag is racy for a public helper

validateSchema sets and deletes a global boolean. Because the helper is now exported and can be called concurrently, one call's finally block can clear the flag while another call is still evaluating the schema. Consider a reference counter or scoping the force-server state to the call context.

ℹ️ Nitpicks

  • validateSchema hardcodes jiti aliases for every @arkenv/nuxt/* subpath by probing for .ts/.js files relative to import.meta.url. This is fragile if package exports or build output layouts change.
  • The watcher test sleeps for 100 ms and 300 ms; real timers make it flaky in CI.
  • Nuxt docs under apps/www/content/docs/nuxt/ should cover the new validate and codegen options.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

Comment thread .changeset/nuxt-validation-codegen.md Outdated
Comment thread .changeset/nuxt-validation-codegen.md Outdated
Comment thread .changeset/nuxt-validation-codegen.md Outdated
Comment thread packages/nuxt/src/config.ts Outdated
Comment thread packages/nuxt/src/config.ts Outdated
Comment thread packages/nuxt/src/config.ts
@pullfrog

pullfrog Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Run failed. View the logs →

Pullfrog  | Rerun failed job ➔View workflow run | via Pullfrog | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

The changeset example registers the wrong module entry, and the generated runtimeEnv code can break for valid environment-variable names that aren't JavaScript identifiers.

Reviewed changes — Re-reviewed the commits pushed since the last Pullfrog review. The prior feedback has been addressed: changeset examples now match the config API, setupArkEnv throws instead of calling process.exit, and validateSchema uses a reference counter for the force-server flag. Alias resolution was also moved from hardcoded file probing to reading package.json exports.

  • Fixed .changeset/nuxt-validation-codegen.md usage example to use schemaPath, outputPath, top-level layout, and NUXT_PUBLIC_ prefix.
  • Replaced unconditional process.exit(1) in setupArkEnv with thrown errors.
  • Made __arkenv_force_server__ re-entrant by tracking a global reference count.
  • Replaced hardcoded jiti alias file probes with dynamic resolution from @arkenv/nuxt/package.json exports.
  • Added Nuxt module tests for codegen and validation in packages/nuxt/src/module.test.ts.

ℹ️ Nitpicks

  • The watcher test in packages/nuxt/src/config.test.ts still sleeps for 100 ms and 300 ms with real timers; using fake timers or awaiting watcher readiness would make it less flaky.
  • The Nuxt docs under apps/www/content/docs/nuxt/ should cover the new validate and codegen options.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

Comment thread .changeset/nuxt-validation-codegen.md Outdated
Comment thread packages/nuxt/src/config.ts Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No new issues in this docs-only delta.

Reviewed changes — Merged docs updates from dev that rename the Nuxt "simple" layout to "flat" and refresh the examples to match the flat API.

  • Renamed simple.mdx to flat.mdx and rewrote code samples to use the flat schema object with NUXT_PUBLIC_ prefixes and an exposeToClient example.
  • Updated Nuxt docs index and layouts meta to link to the new flat layout page.
  • Updated using-other-validators.mdx to show flat-layout Zod/Valibot examples.
  • Added a permanent redirect from /docs/nuxt/layouts/simple to /docs/nuxt/layouts/flat in apps/www/next.config.ts.

Pullfrog  | Fix it ➔View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes — Addressed the remaining review feedback by fixing the changeset module entry and making generated runtimeEnv keys safe for env var names that are not valid JavaScript identifiers.

  • Fixed .changeset/nuxt-validation-codegen.md module import — changed the registered module from @arkenv/nuxt to @arkenv/nuxt/module so the usage snippet actually boots.
  • Made generated runtimeEnv use JSON.stringify and bracket accessgenerateRuntimeEnvLines now emits "KEY": ... public?.["KEY"] ?? process.env["KEY"] ..., so valid env var names such as NUXT_PUBLIC_MY-KEY produce valid TypeScript and runtime lookups.
  • Updated generated examples and test assertions — refreshed apps/playgrounds/nuxt/generated/env.gen.ts, examples/with-nuxt/generated/env.gen.ts, and packages/nuxt/src/config.test.ts expectations to match the bracketed output.

Pullfrog  | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

…me-validation-codegen

# Conflicts:
#	packages/nuxt/src/module.test.ts
#	packages/nuxt/src/module.ts

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

packages/nuxt/src/module.ts has a duplicate normalizeLayout declaration that breaks tsc and Biome. Remove the local redeclaration (and the now-unused hasWarnedSimpleLayout) and use the import from ./config.

Reviewed changes — Re-reviewed the merge from dev since the last approval, which pulled a stricter client-side security guard into the branch.

  • Added strict-layout client security blocking in packages/nuxt/src/module.ts — the Vite resolveId plugin now resolves Nuxt aliases (~/, ~~/, @/) and blocks userland env/server.ts imports on the client when using the strict layout.
  • Added a module integration test in packages/nuxt/src/module.test.ts covering alias and relative imports that should be blocked or allowed.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

Comment thread packages/nuxt/src/module.ts

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes — Re-reviewed the fixes pushed since the last review. The duplicate normalizeLayout redeclaration in packages/nuxt/src/module.ts was removed, resolving the TypeScript and Biome errors. The playground/example generated env.gen.ts files were also refreshed to the bracketed property access format.

  • Removed duplicate normalizeLayout from packages/nuxt/src/module.ts and kept the import from ./config.
  • Updated generated examples in apps/playgrounds/nuxt/generated/env.gen.ts and examples/with-nuxt/generated/env.gen.ts to match the bracketed runtime lookups.

Type-checking and the @arkenv/nuxt test suite now pass.

Pullfrog  | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

@yamcodes yamcodes changed the title feat(nuxt): build-time validation & codegen feat(nuxt): build-time validation & dynamic runtime proxy Jun 30, 2026
@github-actions github-actions Bot added the www Improvements or additions to arkenv.js.org label Jun 30, 2026
@github-actions github-actions Bot removed the playground Issues or Pull Requests concerning a playground. (Found in the `apps/playgrounds/` directory) label Jun 30, 2026
@yamcodes

Copy link
Copy Markdown
Owner Author

LGTM

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

The no-codegen refactor is solid, but two cleanup items need to land before merge: the public outputPath option is now dead, and stale generated/env.gen.ts files are still committed.

Reviewed changes — Re-reviewed the commits that removed codegen in favor of a dynamic useRuntimeConfig() proxy.

  • Removed runCodegen, watchSchema, and the codegen/outputPath options from the Nuxt module and config.ts.
  • Added a mock-imports.ts stub aliased to #imports so build-time validation can safely evaluate schemas that call useRuntimeConfig().
  • Updated create-env.ts to resolve client values from runtimeConfig.public and server values from top-level runtimeConfig, with process.env fallbacks.
  • Switched dev watching to nuxt.options.watch and removed the chokidar dependency.
  • Updated docs (faq.mdx, flat.mdx, strict.mdx, comparison.mdx) and the with-nuxt example dependency.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

Comment thread packages/nuxt/src/config.ts Outdated
* });
* ```
*/
outputPath?: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Remove the stale outputPath option from ArkEnvConfigOptions. Codegen was removed, so setupArkEnv never reads this option; leaving it typed and documented will mislead users and break copy-pasted configs.

Technical details
## Affected sites
- `packages/nuxt/src/config.ts:71-85``outputPath` JSDoc and type describe a generated file that is no longer written.
- `packages/nuxt/src/config.ts:109-115``setupArkEnv` doc comment still refers to "schema and output files".

## Required outcome
- Delete the `outputPath` property from `ArkEnvConfigOptions`.
- Update the `setupArkEnv` JSDoc to describe only schema-path and validation options.

@@ -0,0 +1,29 @@
/* eslint-disable */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This file is now stale. The Nuxt integration no longer generates env.gen.ts, and the docs/changeset explicitly say zero files are created. Remove it from the playground and run pnpm sync:examples so the example stays consistent.

Comment thread examples/with-nuxt/generated/env.gen.ts Outdated
@@ -0,0 +1,29 @@
/* eslint-disable */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This file is now stale. The Nuxt integration no longer generates env.gen.ts, and the docs/changeset explicitly say zero files are created. Remove it (it will be removed from the example when the playground is re-synced).

@@ -0,0 +1,6 @@
export function useRuntimeConfig(): any {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The validation stub returns process.env both as public and top-level. Since mock-imports.ts is also built into dist, tighten it to return only what build-time validation needs — e.g. { public: {} } — so it does not double as a full runtime config if the built file is ever resolved directly.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes — Re-reviewed the follow-up commits that addressed the prior feedback.

  • Removed the stale outputPath option from ArkEnvConfigOptions and its JSDoc example.
  • Deleted the unused generated/env.gen.ts files from the Nuxt playground and example.
  • Added module tests for the validate: true success path and the validate: false skip path.
  • Updated the strict-layout config-test fixture to import from @arkenv/nuxt/client instead of the removed generated factory.

All 26 @arkenv/nuxt tests and the package typecheck pass.

Pullfrog  | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

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

Labels

@arkenv/nuxt Issues or Pull Requests involving the Nuxt integration for ArkEnv docs Adds or changes documentation, or acts as documentation in and of itself example Issues or Pull Requests concerning at least one ArkEnv example. (Found in the `examples/` directory) tests This issue or PR is about adding, removing or changing tests www Improvements or additions to arkenv.js.org

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(nuxt): build-time validation & dynamic runtime proxy (v1) feat(nuxt): add flat-layout overload to @arkenv/nuxt/standard

1 participant