npm package: @front-ops/domino
Description: True Affected - Semantic change detection for monorepos
Latest version: 1.2.1

<p align="center">
  <img src="https://github.com/user-attachments/assets/012a005f-04e4-480e-8d50-5314bdd04a6d" alt="domino logo" width="120" />
</p>

<h1 align="center">domino</h1>

<p align="center">
  A high-performance Rust implementation of <b>True Affected</b> — semantic change detection for monorepos using the Oxc parser.
</p>
<br />

## Overview

domino is a drop-in replacement for the TypeScript version of [traf](https://github.com/@lemonade-hq/traf), providing the same semantic analysis capabilities with significantly better performance thanks to Rust and the Oxc parser.

## Features

- **Semantic Change Detection**: Analyzes actual code changes at the AST level, not just file changes
- **Cross-File Reference Tracking**: Follows symbol references across your entire workspace
- **Lockfile Change Detection**: Detects dependency version changes in npm, yarn, pnpm, and bun lockfiles and traces affected projects
- **Fast Oxc Parser**: 3-5x faster than TypeScript's compiler API
- **Workspace Support**: Works with Nx, Turborepo, and generic npm/yarn/pnpm/bun workspaces
- **Module Resolution**: Uses oxc_resolver (same as Rolldown and Nova) for accurate module resolution

## Quick Start

```bash
# Run directly with npx (no installation required)
npx @front-ops/domino@latest affected

# Show all projects in the workspace
npx @front-ops/domino@latest affected --all
```

## Installation

### Using npx (Recommended)

No installation required! Just run:

```bash
npx @front-ops/domino@latest affected
```

### Binary Installation

If you prefer to use the standalone binary:

```bash
# Clone and build from source
git clone git@github.com:frontops-dev/domino.git
cd domino
cargo build --release

# The binary will be available at ./target/release/domino
# You can then run it from anywhere:
/path/to/domino/target/release/domino affected
```

## Usage

### Using npx

```bash
# Show all projects in the workspace
npx @front-ops/domino affected --all

# Find affected projects (compared to origin/main)
npx @front-ops/domino affected

# Use a different base branch
npx @front-ops/domino affected --base origin/develop

# Compare specific commits (useful in CI patch pipelines)
npx @front-ops/domino affected --base abc123 --head def456

# Output as JSON
npx @front-ops/domino affected --json

# Enable debug logging
npx @front-ops/domino affected --debug

# Generate a detailed report
npx @front-ops/domino affected --report report.html
```

### Using the Binary

If you've built the binary from source:

```bash
# Show all projects in the workspace
domino affected --all

# Find affected projects (compared to origin/main)
domino affected

# Use a different base branch
domino affected --base origin/develop

# Compare specific commits (useful in CI patch pipelines)
domino affected --base abc123 --head def456

# Output as JSON
domino affected --json

# Enable debug logging
domino affected --debug

# Generate a detailed report
domino affected --report report.html
```

### Options

- `--base <BRANCH>`: Base branch to compare against (default: `origin/main`)
- `--head <COMMIT>`: Head commit to compare (defaults to working tree)
- `--all`: Show all projects regardless of changes
- `--json`: Output results as JSON
- `--report <PATH>`: Generate a detailed analysis report
- `--debug`: Enable debug logging
- `--cwd <PATH>`: Set the current working directory
- `--lockfile-strategy <STRATEGY>`: Lockfile change detection strategy (default: `direct`)

### Lockfile Change Detection

domino automatically detects when your lockfile changes and identifies which projects are affected by dependency version updates. This works with all major package managers:

| Package Manager | Lockfile            |
| --------------- | ------------------- |
| npm             | `package-lock.json` |
| yarn            | `yarn.lock`         |
| pnpm            | `pnpm-lock.yaml`    |
| bun             | `bun.lock`          |

Three strategies are available via `--lockfile-strategy`:

- **`none`** — Ignore lockfile changes entirely
- **`direct`** (default) — Mark projects that directly import an affected dependency
- **`full`** — Like `direct`, but also traces the full reference chain (e.g. if `lib-a` changed and `ProjectA` imports it, `full` follows all re-exports of `lib-a` symbols to find additional affected projects)

The detection is transitive: if a deeply nested dependency changes, domino walks the reverse dependency graph to find which direct dependency was affected, then finds all projects importing that dependency.

```bash
# Default: detect lockfile changes with "direct" strategy
domino affected

# Disable lockfile detection
domino affected --lockfile-strategy none

# Full reference chain tracing
domino affected --lockfile-strategy full
```

## How It Works

1. **Git Diff Analysis**: Detects which files and specific lines have changed
2. **Semantic Parsing**: Parses all TypeScript/JavaScript files using Oxc
3. **Symbol Resolution**: Identifies which symbols (functions, classes, constants) were modified
4. **Reference Finding**: Recursively finds all cross-file references to those symbols
5. **Lockfile Analysis**: Detects dependency version changes and traces affected imports
6. **Project Mapping**: Maps affected files to their owning projects

## Performance

Thanks to Rust and Oxc, domino is significantly faster than the TypeScript version:

- **Parsing**: 3-5x faster using Oxc
- **Memory**: Lower memory footprint
- **Startup**: Near-instant startup time

## Comparison with TypeScript Version

| Feature      | TypeScript                     | Rust                     |
| ------------ | ------------------------------ | ------------------------ |
| Parser       | ts-morph (TypeScript compiler) | Oxc parser               |
| Speed        | Baseline                       | 3-5x faster              |
| Memory       | Baseline                       | ~50% less                |
| Binary Size  | Requires Node.js + deps        | Single standalone binary |
| Startup Time | ~1-2s                          | <100ms                   |

## Architecture

### Core Components

- **Git Integration** (`src/git.rs`): Parses git diffs to identify changed files and lines
- **Workspace Discovery** (`src/workspace/`): Discovers projects in Nx, Turbo, and generic npm/yarn/pnpm/bun workspaces
- **Semantic Analyzer** (`src/semantic/analyzer.rs`): Uses Oxc to parse and analyze TypeScript/JavaScript
- **Reference Finder** (`src/semantic/reference_finder.rs`): Tracks cross-file symbol references
- **Lockfile Analyzer** (`src/lockfile.rs`): Parses lockfiles, builds reverse dependency graphs, and detects affected packages
- **Core Algorithm** (`src/core.rs`): Orchestrates the affected detection logic

### Key Technologies

- **[Oxc](https://github.com/oxc-project/oxc)**: High-performance JavaScript/TypeScript parser and toolchain
- **oxc_resolver**: Module resolution (used by Rolldown, Nova, knip)
- **clap**: CLI argument parsing
- **git2**: Git integration
- **serde**: JSON/YAML parsing

## Development

### Quick Reference

```bash
# Build (debug)
cargo build

# Build (release)
cargo build --release

# Run tests
cargo test

# Run integration tests (must be serial)
cargo test --test integration_test -- --test-threads=1

# Run from source
cargo run -- affected --all

# Format code
cargo fmt

# Lint code
cargo clippy

# Enable debug logging
RUST_LOG=domino=debug cargo run -- affected
```

## License

Same as the original traf project.

## Credits

This is a Rust port of the original [traf](https://github.com/@lemonade-hq/traf) TypeScript implementation.

Built with:

- [Oxc](https://github.com/oxc-project/oxc) - The JavaScript Oxidation Compiler
- [oxc_resolver](https://github.com/oxc-project/oxc-resolver) - Fast module resolution