Skip to main content

🏗️ Architecture Overview

leetrs is designed as a modular, asynchronous Rust crate focused on performance, clean separation of concerns, and robust error handling.


📦 Workspace & Crate Structure​

leetrs is structured as a Cargo workspace with distinct crates for separation of concerns:

MemberDirectoryPurpose
leetrssrc/Main CLI binary and interactive Ratatui TUI application
cookie-extractcrates/cookie-extractStandalone, lightweight browser cookie extraction & cURL parsing library (completely replaces the deprecated rookie crate)
xtaskxtask/Developer and CI task runner for cross-platform linting, testing, and formatting

🧱 Module Structure​

The application codebase (src/) is organized into dedicated modules:

ModuleSource FileDescription
authsrc/auth.rsEncapsulates browser cookie extraction (cookie-extract) and credential persistence
clientsrc/client.rsAuthenticated HTTP client managing LeetCode REST and GraphQL API queries
modelssrc/models/Serde-compatible data models (ProblemSummary, Question, Submission, Language)
pickersrc/picker.rsMain workflow orchestrator connecting client, caching, disk I/O, and editor launching
tuisrc/tui/Ratatui rendering engine, screen state management, and custom widget components
servicessrc/services/Polling and submission handling logic
cachesrc/cache.rsDisk caching service for problem list metadata (data.json)
configsrc/config.rsGlobal configuration manager backed by OnceLock<Config>
formatsrc/format.rsTerminal colorizing and result formatting utilities
errorsrc/error.rsCustom error types implemented with thiserror (EngineError)

🔄 Core Execution Pipeline​

sequenceDiagram
autonumber
actor User
participant CLI as main.rs / commands.rs
participant Auth as auth.rs
participant Config as config.rs
participant Picker as picker.rs
participant Client as client.rs
participant Editor as Neovim Process

User->>CLI: leetrs pick 1
CLI->>Auth: LeetCodeCredentials::load()
Auth-->>CLI: Credentials
CLI->>Config: CONFIG.get()
Config-->>CLI: Config Options
CLI->>Picker: Picker::new(client).pick(1)
Picker->>Client: get_question_by_id(1)
Client-->>Picker: Question Details & Code Snippets
Picker->>Picker: Write two_sum.md & two_sum.rs to disk
Picker->>Editor: Launch nvim two_sum.md -c "vsplit two_sum.rs"
Editor-->>User: Side-by-side terminal split