Contributing
Layout
| Path | Contents |
|---|---|
crates/vld | the core crate: src/, tests/all/ (one test binary), benches/ (Criterion) |
crates/vld-* | integration crates (each with src/, tests/, usually examples/) |
fuzz/ | cargo-fuzz targets (not in the workspace) |
examples/playground | a small app that uses many crates together |
docs/ | this site (Nuxt + Nuxt Content) |
justfile | CI, checks and the release hook (just lists them) |
All crates share one version and are released together; see PUBLISHING.md.
Running CI locally
CI runs just recipes, so the same commands work locally. Install the tools once:
cargo install just cargo-hack cargo-deny cargo-shear cargo-semver-checks
just # list recipes
just ci # what CI runs on every push
just lint test # only these
| Recipe | What it does |
|---|---|
fmt | cargo fmt --check |
lint | cargo shear (unused / misplaced dependencies), then clippy -D warnings: workspace, each vld feature alone and all together, feature pairs of integration crates |
test | tests and doctests with the same feature sets as lint |
docs | cargo doc with -D warnings |
deny | cargo deny (advisories, licenses, duplicates) |
package | cargo package dry run |
fuzz | builds the fuzz targets |
playground | runs the playground example |
wasm | wasm32 builds of the UI integrations |
powerset | every pair of vld features compiles (slow) |
msrv | every crate on its rust-version (see MSRV) |
minimal | lowest allowed dependency versions (nightly) |
semver | cargo semver-checks: API changes vs the latest crates.io release fit the version bump |
clean | removes target/ci and the MSRV / minimal build dirs |
Feature combinations come from cargo-hack. Crates with one feature per supported major of a dependency (redis-0 / redis-1, sqlx-0_8 / sqlx-0_9, …) are listed in feature_crates at the top of the justfile; cargo-hack runs every major alone and with each other feature, never two majors together. wasm, powerset, msrv, minimal and the Windows / macOS tests run only before a release, by hand (Actions → CI → Run workflow).
Lints shared by every crate live in [workspace.lints] in the root Cargo.toml (each crate has [lints] workspace = true); external dependencies used by several crates are declared once in [workspace.dependencies].
Builds use the committed Cargo.lock (--locked) and the ci profile (no debuginfo, output in target/ci). diesel's postgres / mysql features need libpq / libmysqlclient (brew install libpq mysql-client, apt install libpq-dev libmysqlclient-dev).
--all-features on crates with dual-major features (ntex-3 / ntex-4, utoipa-5 / utoipa-6, sqlx-0_8 / sqlx-0_9, …): the majors are mutually exclusive and fail with compile_error!.Keeping target/ small
With ~30 integration crates a debug target/ grows fast. The workspace already helps:
[profile.dev]usesdebug = "line-tables-only"for workspace crates and no debuginfo for dependencies;split-debuginfo = "off"stops macOS from leaving stale object files intarget/*/depson every rebuild;justrecipes build intotarget/ci;just cleanremoves it without touching the dev build.
If it still grows, remove old artifacts with cargo sweep:
cargo install cargo-sweep
cargo sweep --time 7 # delete artifacts not used for 7 days
Snapshot tests
vld-utoipa, vld-aide and vld-ts use insta snapshots. After an intended output change:
cargo insta test -p vld-ts
cargo insta review
vld-ts cross-check against Node
vld-ts can compare its generated Zod / Valibot schemas against real Node runs. Point VLD_TS_NODE_DIR at a directory with zod@3 and valibot@1 installed:
mkdir -p .ts-check && echo '{"private":true}' > .ts-check/package.json && npm --prefix .ts-check install zod@3 valibot@1
VLD_TS_NODE_DIR=$PWD/.ts-check cargo test -p vld-ts
Without the variable the cross-check is skipped.
Fuzzing
cargo install cargo-fuzz
cd fuzz
cargo +nightly fuzz list
cargo +nightly fuzz run iso_formats -- -max_total_time=60
Targets: iso_formats, string_formats, url_decode, error_truncation. Crashes are saved to fuzz/artifacts/<target>/.
Documentation
This site lives in docs/ and is built with Nuxt Content:
cd docs
pnpm install
pnpm dev # http://localhost:3000
NUXT_APP_BASE_URL=/vld/ pnpm generate # static build in .output/public
CHANGELOG.md and MSRV.md are copied into the site by docs/scripts/sync.mjs; edit the originals. The site is deployed to GitHub Pages by .github/workflows/docs.yml.
Rust API docs: RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps must stay clean.
Changelog
Add entries under ## [Unreleased] at the top of CHANGELOG.md (create the heading if it is not there), and a line in "Migration" for anything breaking.