tomato·bazeldocs v0 · latest
Docs/Reference/Modules/rules_vite

rules_vite

Bazel rules for Vitest under aspect_rules_js. Hermetic js_test wrapper for vitest.

Latest0.1.1
Versions2
CategoryBazel rules
Compat level1
MaintainersMatt Marshall
Registryhttps://registry.tbzl.dev/modules/rules_vite/
Sourcegithub.com/tomato-bazel/rules_vite
MODULE.bazelstarlark
bazel_dep(name = "rules_vite", version = "0.1.1")

View source & releases on GitHub ↗

Bazel rules for Vitest under aspect_rules_js. Wraps a vitest run as a hermetic js_test: the consumer’s package-local node_modules/vitest is resolved at runtime; the test sources are passed explicitly via argv; the launcher rewrites runfiles-relative paths so config and srcs survive chdir into the consumer’s package.

  • rules:
    • vitest_testbazel test //path:target → runs vitest in a hermetic sandbox with declared inputs only. See docs/defs.md.

The consumer brings its own vitest npm dep (so the version isn’t pinned by rules_vite). The macro doesn’t impose any project key or config shape — pass any vitest config file as config, or accept the minimal default.

Install

Add the registry to your .bazelrc:

common --registry=https://registry.fastverk.com/
common --registry=https://bcr.bazel.build/

In your MODULE.bazel:

bazel_dep(name = "rules_vite", version = "0.1.0")
bazel_dep(name = "aspect_rules_js", version = "3.1.2")
bazel_dep(name = "rules_nodejs", version = "6.7.4")

node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
node.toolchain(node_version = "22.11.0")

npm = use_extension("@aspect_rules_js//npm:extensions.bzl", "npm")
npm.npm_translate_lock(
    name = "npm",
    pnpm_lock = "//:pnpm-lock.yaml",  # must include vitest
)
use_repo(npm, "npm")

Quick start

In a BUILD.bazel:

load("@npm//:defs.bzl", "npm_link_all_packages")
load("@rules_vite//vite:defs.bzl", "vitest_test")

npm_link_all_packages(name = "node_modules")

vitest_test(
    name = "test_node",
    srcs = ["foo.test.ts", "bar.test.ts"],
    deps = [
        ":node_modules/vitest",
        # ...workspace deps the tests import...
    ],
)

The macro:

  • Sets chdir to the consumer’s package, so process.cwd() puts the test inside <consumer>/node_modules/... for module resolution.
  • Resolves vitest’s bin via vitest/package.json (vitest doesn’t expose the bin file in its exports map, so direct subpath resolution fails with ERR_PACKAGE_PATH_NOT_EXPORTED).
  • Rewrites VITEST_CONFIG and argv test-source paths to absolute paths anchored at $JS_BINARY__RUNFILES/_main, so they survive chdir.

Config

Pass config to override the default minimal config:

vitest_test(
    name = "test_with_setup",
    srcs = ["foo.test.ts"],
    config = "//:vitest.config.ts",
    deps = [
        ":node_modules/vitest",
        "//:vitest.config.ts.lib",  # js_library wrapping the config
        # plus any plugins the config imports
    ],
)

If config is omitted the macro injects a minimal config that:

  • Sets environment: 'node'
  • Disables globals, setupFiles, coverage, plugins
  • Lets testTimeout / hookTimeout default to vitest’s settings

Tests that need richer setup (browser env, plugins, globalSetup, etc.) provide their own config and materialize its transitive deps in runfiles via standard js_library wrappers.

Smoke test

bazel test @rules_vite//examples/smoke:...

Runs a real vitest invocation against a tiny pnpm workspace pinned in examples/smoke. Used as a release gate.

Usage#

Real usage, taken from the module’s examples/.

examples/smoke/BUILD.bazel

load("@rules_vite//vite:defs.bzl", "vitest_test")
load("@smoke_npm//:defs.bzl", "npm_link_all_packages")

package(default_visibility = ["//visibility:public"])

npm_link_all_packages(name = "node_modules")

exports_files(["pnpm-lock.yaml"])

# Smoke: a real `vitest_test` exercising the macro end-to-end against
# the pinned smoke npm workspace. Used as a release gate.
vitest_test(
    name = "smoke_test",
    srcs = ["sum.test.ts"],
    deps = [":node_modules/vitest"],
)

Rules & providers#

Generated with Stardoc from the module's .bzl sources.

from docs/defs.md

Public rules for rules_vite.

vitest_test

load("@rules_vite//vite:defs.bzl", "vitest_test")

vitest_test(name, srcs, config, deps, data, env, tags, timeout, **kwargs)

Run vitest against the given test sources under a hermetic Bazel sandbox.

The consumer must call npm_link_all_packages(name = "node_modules") at the top of its BUILD.bazel and include :node_modules/vitest in deps (plus any test-time npm packages the suite imports). The launcher resolves vitest via Node’s standard walk-up from chdir = package_name().

PARAMETERS

NameDescriptionDefault Value
nameTest target name.none
srcsTest source files (typically glob(["**/*.test.ts"])).none
configOptional vitest config file (a js_library target wrapping the .ts/.js config). If omitted, vitest runs with its default config — fine for simple test suites; richer suites pass a config and add its transitive deps to deps.None
depsRuntime deps the test sources need (their :lib, the npm-linked vitest binary :node_modules/vitest, any npm packages the tests import).None
dataExtra runtime files.None
envExtra env vars passed to vitest. VITEST_CONFIG is set automatically when config is non-empty.None
tagsBazel tags. The macro doesn’t add any tags of its own — consumers tag for their own CI matrix.None
timeoutBazel test timeout (default moderate = 5min)."moderate"
kwargsForwarded to js_test.none

Conformance#

No gate findings. 17 contested atoms. See how gating works or the full report.

Contested atoms

Third-party modules where this module resolves a different version than others do. Not a violation of anything this module did — it is the actionable form of a registry-level convergence finding, and the sentence a maintainer can act on.

AtomResolved hereElsewhere
apple_support 1.24.2 2.2.0 ×1
aspect_bazel_lib 2.22.5 2.8.1 ×1
aspect_rules_js 3.1.2 2.1.3 ×1
bazel_lib 3.2.2 3.0.0 ×12
bazel_skylib 1.8.2 1.9.0 ×2
gawk 5.3.2.bcr.3 5.3.2.bcr.1 ×12
jq.bzl 0.4.0 0.1.0 ×12
nlohmann_json 3.6.1 3.12.0.bcr.1 ×1
package_metadata 0.0.2 0.0.5 ×3
protobuf 33.4 34.0.bcr.1 ×2
rules_jvm_external 6.7 6.8 ×4
rules_nodejs 6.7.4 6.3.0 ×16.7.3 ×1
rules_python 1.7.0 2.0.1 ×1
rules_swift 3.1.2 3.6.1 ×1
tar.bzl 0.10.4 0.5.1 ×110.6.0 ×1
upb 0.0.0-20220923-a547704 0.0.0-20230516-61a97ef ×1
yq.bzl 0.3.4 0.1.1 ×12

Dependencies#

rules_vite in the registry graph — what it depends on (left) and what depends on it (right).

Depends on

platforms1.0.0bazel_skylib1.8.2aspect_rules_js3.1.2stardoc0.7.2devrules_shell0.6.1devrules_nodejs6.7.4dev

Used by (4 in the registry)

Versions#

2 published versions, newest first. Each resolves to an immutable, integrity-checked archive.

VersionIntegrity (sha256)Source archive
0.1.1 latest N88/msgXjjFCQqxM… tag archive ↗
0.1.0 rTAcQUqfTd+HX+vs… tag archive ↗

Changelog#

All notable changes to rules_vite. The format is loosely Keep a Changelog — version headers mirror the published bazel-registry entries.

0.1.0 — initial release

  • Initial release of Bazel rules for [Vitest] under aspect_rules_js. Wraps a vitest run as a hermetic js_test: the consumer’s package-local node_modules/vitest is resolved at runtime, test sources are passed explicitly via argv, and the launcher rewrites runfiles-relative paths so config + srcs survive the chdir into the consumer’s package.
  • Ships one rule, vitest_test (bazel test //path:target), running vitest in a hermetic sandbox with declared inputs only.
  • The consumer brings its own vitest npm dep — rules_vite doesn’t pin a version or impose a project key / config shape; pass any vitest config via config or use the minimal default.

← All modules