Skip to content

feat: domain-oriented Cargo feature flags#69

Merged
suchapalaver merged 2 commits into
mainfrom
feat/domain-feature-flags
May 26, 2026
Merged

feat: domain-oriented Cargo feature flags#69
suchapalaver merged 2 commits into
mainfrom
feat/domain-feature-flags

Conversation

@suchapalaver

Copy link
Copy Markdown
Contributor

Summary

Splits the crate into per-domain Cargo features so downstream consumers can build only the parts of Semioscan they use. default enables every domain, so existing dependants compile unchanged; a consumer that only needs, say, block-window math can now use default-features = false, features = ["blocks"] and pull in nothing else. Closes #21.

What's in the diff

  • Cargo.toml — new [features] block (blocks, events, gas, price, provider, retrieval, transport, plus the existing ws); default enables all domains. alloy-erc20 becomes optional and is pulled only by price/retrieval. Feature-specific examples gain required-features.
  • src/lib.rs — module declarations and root re-exports gated with #[cfg(feature = "...")]; new # Feature flags crate-doc section.
  • src/types/decimal_precision.rs (moved from src/retrieval/) — relocating DecimalPrecision into types breaks the only real gas ↔ retrieval module cycle, which Cargo features cannot express. semioscan::DecimalPrecision keeps the same root path.
  • src/errors/mod.rs — per-domain error submodules and SemioscanError variants gated to their feature; RpcError stays always-on.
  • src/tracing/spans.rs, src/cache/block_range.rs, src/scan/logs.rs — domain-specific helpers in always-on core modules gated to their owning feature so a minimal build stays clean under -D warnings.
  • tests/* — feature-specific integration tests carry a #![cfg(feature = "...")] crate attribute.

Reviewer: start with Cargo.toml (the feature graph) and src/lib.rs (the gating); the rest follows from those.

Acceptance check (from #21)

  • cargo check --no-default-features succeeds (core build: config/errors/types).
  • cargo check --no-default-features --features blocks succeeds.
  • cargo check --no-default-features --features events succeeds.
  • cargo check --no-default-features --features gas succeeds.
  • cargo check --no-default-features --features price succeeds.
  • cargo check --no-default-features --features retrieval succeeds.
  • cargo check --all-features succeeds.
  • Existing default cargo test behavior intact (504 lib + integration + 97 doctests pass).
  • Docs explain feature dependencies (crate-level doc + CLAUDE.md).

Note: the issue sketched price = ["events"], but price has no crate::events usage, so per the issue's "feature dependencies reflect real module dependencies" directive it is price = ["dep:alloy-erc20"].

Test plan

  • cargo test, cargo test --no-default-features, cargo test --all-features — all pass
  • cargo clippy -- -D warnings clean for default, --all-features, and --no-default-features, plus each single feature
  • cargo clippy --all-targets --all-features -- -D warnings clean
  • cargo fmt --check clean
  • cargo doc --no-default-features --no-deps and --all-features --no-deps build (see self-review note on doc-link warnings)
  • reuse lint compliant

🤖 Generated with Claude Code

Each domain (blocks, events, gas, price, provider, retrieval, transport)
is now a Cargo feature. The default build enables all of them, so existing
dependants are unaffected, but consumers can now opt out — for example a
crate that only needs block-window calculations can depend on semioscan
with default-features = false, features = ["blocks"] and pull in nothing
else.

Feature dependencies mirror real module dependencies (gas enables events,
provider enables transport, retrieval enables events and gas, ws enables
provider), and alloy-erc20 becomes optional, compiled only for price and
retrieval builds.
The README's Feature Flags section listed only `ws`. Describe every domain
feature, how they compose, and how to build a slimmed-down dependency with
default-features = false.
@suchapalaver

Copy link
Copy Markdown
Contributor Author

Self-review pass

Pre-commit /code-review (5-angle recall sweep) + post-PR /pr-review (structural/consistency/packaging). Findings triaged below.

# Finding Status
1 README "Feature Flags" section listed only ws, now stale against the per-domain features (issue asks to document default + minimal builds) Fixed: 6748f73
2 Feature-predicate correctness — inter-feature deps must mirror real use crate:: graph (gas→events, provider→transport, retrieval→events+gas, price has no events dep) Verified clean: every --no-default-features --features <X> combo + --all-features compiles and is clippy-clean under -D warnings
3 DecimalPrecision move (retrieval → types) could break semioscan::DecimalPrecision source-compat or leave dangling refs Verified clean: root path unchanged, no remaining retrieval::DecimalPrecision references; the move breaks the only real gas↔retrieval cycle
4 SemioscanError variants now #[cfg]-gated — ? propagation must be intact in default builds Verified clean: default enables all variants; RpcError/SemioscanError stay always-on
5 alloy-erc20 made optional — a build without price/retrieval must not reference it Verified clean: only price/decimals.rs and retrieval/balance.rs use it
6 default = []default = [all domains] Intentional and non-breaking: a plain semioscan = "x" dependency got the full (ungated) API before and still does; only an explicit default-features = false consumer (previously a no-op) now gets the core-only build
7 8 rustdoc unresolved link warnings under --no-default-features (always-on errors/rpc docs link to gated domain types) Skipped: the Documentation CI job does not pass -D warnings (exits 0), and docs.rs builds with default features where every link resolves

No remaining blockers. All three CI feature combos (test/clippy/doc), fmt, and reuse pass locally; high confidence in shipping.

@suchapalaver suchapalaver merged commit 910e9cc into main May 26, 2026
11 checks passed
@suchapalaver suchapalaver deleted the feat/domain-feature-flags branch May 26, 2026 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add domain-oriented Cargo feature flags

1 participant