Skip to content

Optional QuickJS / non-Node host entrypoint for console + URL (+ Error.captureStackTrace) #253

Description

@svr93

Summary

We use envalid under QuickJS (qjs) in a Node-free container image to validate env once at docker entrypoint (before the process becomes ready). The browser consumes a generated runtime-env module and does not run envalid. That setup works well, but only after a small must-run-before-import host shim.

It would help if envalid either:

  1. shipped an official envalid/quickjs (or similar) entry that applies safe host patches, or
  2. documented host prerequisites and offered optional adapters so consumers don’t reverse-engineer load-time assumptions.

Environment

  • envalid 8.x
  • QuickJS (qjs), no Node in the final image
  • Bundled ESM validator (esbuild) run from the container entrypoint
  • Shared env schema / types with the browser app; validation only in entrypoint

Problems we hit

  1. console at import time. Default reporter does something like console.error.bind(console) when the module loads. QuickJS hosts often only expose console.log (or incomplete console). Import crashes before any cleanEnv / custom reporter runs.
  2. url() needs URL. url() uses new URL(x) (then returns the original string). Host QuickJS may have no URL, or only a partial one.
  3. Error.captureStackTrace. EnvError / EnvMissingError call V8’s Error.captureStackTrace. QuickJS doesn’t have it → throw during error construction unless stubbed.

Because (1) happens at import, shims must load before import 'envalid'. That forces awkward import-order rules in consumer code.

What we shim today (minimal)

  • Ensure console.error / warn / info / log exist and are bindable
  • Stub Error.captureStackTrace as no-op
  • Provide a minimal URL for absolute scheme://… (enough for url(), not full WHATWG)

Proposal

Option A (preferred): import 'envalid/quickjs' (side-effect or explicit installQuickJsHost()), then normal envalid API.

Option B: Keep core unchanged; export something like:

import { ensureHostForEnvalid } from 'envalid/host'
ensureHostForEnvalid({ console, URL, captureStackTrace: 'noop' })

Option C (docs-only): Document that non-Node hosts must provide bindable console.*, URL for url(), and optionally Error.captureStackTrace before importing envalid.

Also useful: delay console.error.bind(console) until first report / first cleanEnv, so a custom reporter can be set without a complete console.

Why this fits envalid

README already targets “Node, Bun, and other compatible JS runtimes.” Tiny QuickJS runtimes are a real pattern for validate env before the process becomes ready, without shipping Node. Official host support (or clear docs) beats every consumer reinventing the same shim.

Non-goals

  • Full WHATWG URL inside envalid
  • QuickJS stdlib (std / os) integration
  • Replacing custom reporters

Happy to PR a tiny envalid/quickjs install helper + a short “non-Node hosts” doc section if that direction works for you.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions