[package]
name = "rivet-cli"
version = "0.14.1"
edition = "2024"
rust-version = "1.94"
license = "MIT"
repository = "https://github.com/panchenkoai/rivet"
description = "Rivet: PostgreSQL/MySQL/SQL Server → Parquet/CSV (local, S3, GCS, Azure). Crate name rivet-cli; binary rivet."
readme = "README.md"
default-run = "rivet"
exclude = ["dev/", "USER_TEST_PLAN.md", "tests/", ".github/", "docs/gifs/"]

[lib]
name = "rivet"
path = "src/lib.rs"

[[bin]]
name = "rivet"
path = "src/main.rs"

[[bin]]
name = "rivet-mcp"
path = "src/bin/rivet-mcp.rs"

# Dev-only test-data generator. Gated behind the off-by-default `dev-seed`
# feature so `cargo install rivet-cli` (default features) does NOT build or
# install a generically-named `seed` binary on the user's PATH — its default
# run issues `TRUNCATE ... CASCADE` against a local DB (CWE-1188). Dev/docker
# workflows build it with `--features dev-seed`.
[[bin]]
name = "seed"
path = "src/bin/seed/main.rs"
required-features = ["dev-seed"]

[dependencies]
anyhow = "1"
# Part-body MD5 (RustCrypto) + base64 to match GCS's `md5Hash` encoding, so
# integrity can be verified against the object's listing metadata with no
# download (both already in the tree transitively).
base64 = "0.22"
md-5 = "0.11"
# `canonical_extension_types` enables Arrow's canonical extension wrappers
# (`arrow_schema::extension::{Uuid, Json}`) — see Cargo dep on `parquet`
# below for the writer-side pairing.
arrow = { version = "58", features = ["canonical_extension_types"] }
# Direct dep on `arrow-schema` so we can use the `extension` module — the
# `arrow` facade re-exports `DataType` / `Field` but not the `extension`
# submodule. Version is pinned to match `arrow`'s transitive choice.
arrow-schema = { version = "58", features = ["canonical_extension_types"] }
chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4", features = ["derive", "env"] }
csv = "1"
env_logger = "0.11"
libc = "0.2"
log = "0.4"
# `native-tls` feature wires the same OpenSSL-backed TLS stack the rest of
# the workspace already vendors (see `native-tls = { ... features = ["vendored"] }`
# above) so MySQL configs with `tls.mode: require | verify-ca | verify-full`
# work the same way they do on Postgres. Without this feature, the mysql
# crate panics at connect time with "Client had asked for TLS connection
# but TLS support is disabled" — operator-facing panic, no recoverable error.
mysql = { version = "28", default-features = false, features = ["minimal", "native-tls", "binlog"] }
opendal = { version = "0.55", features = ["blocking", "services-fs", "services-s3", "services-gcs", "services-azblob"] }
# `arrow_canonical_extension_types` enables parquet-rs to emit native Parquet
# `LogicalType::Uuid` / `LogicalType::Json` whenever an Arrow field carries the
# corresponding `arrow.uuid` / `arrow.json` extension type metadata. Without
# this flag, those columns would fall back to `String` and our downstream
# autoload story (DuckDB → native UUID, ClickHouse → Nullable(UUID), …)
# stays one cast away. See `src/types/mapping.rs` for the emission site.
parquet = { version = "58", features = ["arrow", "zstd", "lz4", "flate2", "arrow_canonical_extension_types"] }
clap_complete = "4"
postgres = {
    version = "0.19",
    features = ["with-chrono-0_4", "with-serde_json-1", "with-uuid-0_8"],
}
postgres-native-tls = "0.5"
# `vendored` statically links OpenSSL on Linux so `cargo install rivet-cli` works
# on bare systems and our cross-compiled aarch64-unknown-linux-gnu release
# builds don't need `libssl-dev`. On macOS `native-tls` uses the system
# `SecureTransport` framework and the `vendored` flag is a no-op — no OpenSSL
# is ever compiled or linked there.
native-tls = { version = "0.2", features = ["vendored"] }
rand = "0.10"
postgres-types = {
    version = "0.2",
    features = ["with-chrono-0_4", "with-serde_json-1", "with-uuid-0_8"],
}
bigdecimal = "0.4"
byteorder = "1"
uuid = "0.8"
rusqlite = { version = "0.39", features = ["bundled"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_yaml_ng = "0.10"
# JSON Schema generation for `rivet schema config` and the
# `schemas/rivet.schema.json` checked-in artifact (v0.7.3 P0.1/P0.2).
# `derive` feature gives us `#[derive(JsonSchema)]`; the `preserve_order`
# feature keeps Config field order stable across rebuilds so the
# generated schema diff is reviewable.
schemars = { version = "1", features = ["preserve_order"] }
tempfile = "3"
tikv-jemallocator = { version = "0.7", optional = true }
tokio = { version = "1.50.0", features = ["rt-multi-thread", "net", "time"] }
# MSSQL / SQL Server source driver (async). Bridged to the sync `Source` trait
# via a per-source `tokio` current-thread runtime + `block_on` (ADR-0011 keeps
# `Source` sync). `native-tls` matches the OpenSSL stack the PG/MySQL drivers
# already vendor; `rustls` default is disabled to avoid a second TLS tree.
tiberius = { version = "0.12", default-features = false, features = ["tds73", "chrono", "rustls"] }
# `compat` bridges a tokio `TcpStream` to the `futures-io` traits tiberius'
# `Client::connect` expects.
tokio-util = { version = "0.7", features = ["compat"] }
# `TryStreamExt` to consume tiberius' `QueryStream` row-by-row in the MSSQL
# export, so a chunk streams in `batch_size`-row batches instead of
# materialising whole — bounds RSS independent of `chunk_size`. Same 0.3.x
# tiberius already pulls in.
futures-util = "0.3"
reqsign = "0.16"
# Single reqwest version (0.12) shared with the one reqsign 0.16 / opendal pull
# in. Keeping one HTTP+TLS stack avoids duplicating rustls / hyper / h2 in the
# release binary. `rustls-tls` is selected explicitly so it matches the TLS
# backend opendal already links.
reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "rustls-tls"] }
xxhash-rust = { version = "0.8.15", features = ["xxh3"] }
indicatif = "0.18"
console = "0.16"
atoi = "3"
simdutf8 = "0.1"
zeroize = "1"

[target.'cfg(target_os = "macos")'.dependencies]
mach2 = "0.6"

[dev-dependencies]
bytes = "1"
csv = "1"
serde_json = "1"
serde_yaml_ng = "0.10"
criterion = { version = "0.8", features = ["html_reports"] }
# OPT-3: property-based type round-trip (tests/type_roundtrip/property.rs).
proptest = "1"
# MSSQL type-roundtrip harness (tests/common/mssql.rs) needs the async driver
# directly to seed fixtures — same crates the lib uses, exposed to the
# integration-test crate.
tiberius = { version = "0.12", default-features = false, features = ["tds73", "chrono", "rustls"] }
tokio = { version = "1.50.0", features = ["rt-multi-thread", "net", "time"] }
tokio-util = { version = "0.7", features = ["compat"] }

[[bench]]
name = "hot_paths"
harness = false

[[bench]]
name = "resource_aware"
harness = false

[features]
default = ["jemalloc"]
jemalloc = ["tikv-jemallocator"]
# Builds the dev-only `seed` test-data generator (see `[[bin]] seed`). Off by
# default so it is never installed by `cargo install rivet-cli`.
dev-seed = []

[profile.release]
strip = true
lto = "fat"
codegen-units = 1
# opt-level 3 (speed), not "s" (size): rivet is CPU-bound on the row→Arrow
# decode path, where `3` measured 11–21% faster than `s` on the pure-Rust
# value-formatting hot loop (criterion `csv_write_batch`, 2026-06-08); the
# zstd-bound Parquet write benefits ~5% (zstd is a C lib, opt-insensitive).
# Costs ~+28% binary size (~14.6 -> ~18.8 MB) — the size-optimised `z` profile
# is kept below as `release-min` for the distributable artifact.
opt-level = 3

# Size-optimised profile for distributable artifacts. Use with:
#   cargo build --profile release-min --bin rivet
# Inherits everything from `release`, then trades runtime/panic ergonomics for
# a smaller binary. Not used by `cargo bench` / `cargo test`, so criterion's
# unwinding tests and `should_panic` continue to work as before.
[profile.release-min]
inherits = "release"
opt-level = "z"
panic = "abort"
debug = false

# Profiling: release codegen + debug symbols (no strip) so `sample` / dtrace can
# symbolicate the row->Arrow decode hot path. Not for distribution.
[profile.profiling]
inherits = "release"
strip = false
debug = true
overflow-checks = false
