aprender-db 0.29.0

GPU-first embedded analytics database with SIMD fallback and SQL query interface
Documentation
[package]
exclude = ["tests/", "benches/", "docs/", ".github/", "book/", ".pmat/", "target/", ".profraw", ".profdata", ".vscode/", ".idea/", "proptest-regressions/"]
name = "aprender-db"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
description = "GPU-first embedded analytics database with SIMD fallback and SQL query interface"
repository.workspace = true
keywords = ["database", "gpu", "simd", "analytics", "wasm"]
categories = ["database", "science", "wasm"]
rust-version.workspace = true

[lib]
name = "trueno_db"

[dependencies]
# Core compute (SIMD - always included)
trueno = "0.17"  # SIMD-accelerated compute

# Serialization (experiment tracking schema)
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

# Timestamps for experiment tracking
chrono = { version = "0.4", features = ["serde"] }

# GPU compute (optional - feature-gated to avoid +3.8MB binary bloat)
wgpu = { version = "22", optional = true, features = ["wgsl"] }  # GPU compute (Vulkan/Metal/DX12/WebGPU)
bytemuck = { version = "1", features = ["derive"], optional = true }  # Safe byte casting for GPU buffers
futures-intrusive = { version = "0.5", optional = true }  # Async primitives for GPU

# Storage (Arrow columnar format)
# NOTE: arrow 54+ fixes chrono 0.4.42 conflict (quarter() method ambiguity)
# Minimal features: drops arrow-csv, arrow-json, arrow-ipc, flatbuffers (~50 fewer transitive deps)
arrow = { version = "57", default-features = false }
parquet = { version = "57", default-features = false, features = ["arrow"], optional = true }  # Parquet I/O (opt-in)

# Query parsing
sqlparser = "0.52"         # SQL parsing

# Async runtime (optional for WASM)
tokio = { version = "1", features = ["full"], optional = true }
rayon = { version = "1.8", optional = true }  # CPU parallelism (for spawn_blocking isolation)

# Key-value store (Phase 6)
dashmap = "6.0"  # Lock-free concurrent hashmap for MemoryKvStore
rustc-hash = "2.0"  # Fast FxHash for SIMD-friendly key hashing

# Compression for KV cache (GH-5) - via batuta-common shared module
batuta-common = "0.1"
lz4_flex = { version = "0.11", optional = true }
zstd = { version = "0.13", optional = true }

# Server (HTTP API)
axum = { version = "0.7", optional = true }
clap = { version = "4.5", features = ["derive"], optional = true }
serde_yaml_ng = { version = "0.10", optional = true }

# Error handling
thiserror = "2"
anyhow = "1"

# Logging
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

[build-dependencies]
serde = { version = "1", features = ["derive"] }
serde_yaml_ng = "0.10"

[dev-dependencies]
# Testing
criterion = { version = "0.5", features = ["html_reports", "async_tokio"] }
proptest = "1.5"           # Property-based testing
quickcheck = "1"           # Property-based testing (backend equivalence)
rand = "0.8"               # Random data generation for examples

# Competitive benchmarks (CORE-009) - only used when running benchmarks
duckdb = { version = "1.1", features = ["bundled"] }  # DuckDB comparison (bundled = build from source)
rusqlite = "0.32"  # SQLite comparison

# Coverage
cargo-llvm-cov = "0.6"

[target.'cfg(target_arch = "wasm32")'.dependencies]
# WASM support
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
js-sys = "0.3"
console_error_panic_hook = "0.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde-wasm-bindgen = "0.6"
web-sys = { version = "0.3", features = [
    "console",
    "Window",
    "Navigator",
    "Performance",
    "Gpu",
    "GpuAdapter",
    "GpuDevice",
    "Request",
    "RequestInit",
    "Response",
    "Headers",
    "RequestMode",
    "RequestCredentials",
] }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
# Native-only dependencies (Phase 3: gRPC distribution)
tonic = { version = "0.12", optional = true }
prost = { version = "0.13", optional = true }

[[bin]]
name = "aprender-db"
path = "src/main.rs"
required-features = ["server"]

[features]
# Default: SIMD with tokio/rayon, parquet I/O, and server binary (native builds)
default = ["simd", "tokio", "rayon", "parquet-io", "server"]

# Parquet file I/O (adds ~18 transitive crates)
parquet-io = ["dep:parquet"]

# Server binary (HTTP API + CLI)
server = ["dep:axum", "dep:clap", "dep:serde_yaml_ng", "tokio", "parquet-io"]

# SIMD-only backend (12 dependencies, -0.4 MB vs SQLite, 18s compile)
simd = []

# GPU backend (95 dependencies, +3.8 MB, 63s compile) - opt-in only
gpu = ["dep:wgpu", "dep:bytemuck", "dep:futures-intrusive"]

# KV cache compression (GH-5) - LZ4 for speed, ZSTD for ratio
compression = ["dep:lz4_flex", "dep:zstd"]

# Phase 3: Distributed multi-GPU
distributed = ["tonic", "prost"]

# Phase 4: WASM build (no tokio/rayon - not WASM compatible)
wasm = []

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

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

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

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

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

[lints]
workspace = true

[profile.test]
# Optimizations for faster test execution (certeza formula)
opt-level = 1

[profile.release]
opt-level = 3
lto = "fat"
codegen-units = 1
strip = false  # Keep symbols for profiling

[profile.bench]
inherits = "release"

# GPU examples require the gpu feature
[[example]]
name = "gpu_aggregations"
required-features = ["gpu"]

[[example]]
name = "gpu_sales_analytics"
required-features = ["gpu"]

# Toyota Way: Enforce quality gates in development
[package.metadata.pmat]
quality_gates = true
tdg_score_minimum = 85  # B+ grade minimum
mutation_testing = true
mutation_kill_rate_minimum = 85  # 85% kill rate (certeza formula)
coverage_minimum = 85  # 85% code coverage (certeza minimum, target 95%)

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--generate-link-to-definition"]

[package.metadata.release]
shared-version = true

[[package.metadata.release.pre-release-replacements]]
file = "CHANGELOG.md"
search = "## \\[Unreleased\\]"
replace = "## [{{version}}] - {{date}}"

[profile.dev]
panic = "abort"