# Contributing Thanks for your interest! This is an early-stage project — issues, discussions, and PRs are welcome. ## Development setup **Prerequisites:** - Rust 1.85+ ([rustup.rs](https://rustup.rs)) - Node.js 20+ (for Tauri app frontend build; Tailwind CSS v4 requires it) - Windows, Linux, or macOS **Clone and build:** ```bash git clone https://github.com/kts982/sap-odata-explorer.git cd sap-odata-explorer # CLI cargo build --release # Binary at target/release/sap-odata.exe (or sap-odata on Linux/macOS) # Desktop app cd tauri-app npm install cargo tauri build # Binary at ../target/release/sap-odata-explorer-app.exe ``` **Run tests:** ```bash cargo fmt --check cargo test --workspace # Frontend CSS build cd tauri-app npm run css ``` ## Project structure ``` sap-odata-explorer/ ├── crates/ │ ├── core/ # Shared library (protocol, auth, HTTP, metadata, query, catalog, config) │ └── cli/ # CLI binary (clap) └── tauri-app/ ├── src/ # Frontend — vanilla HTML + Tailwind CSS v4 + ES modules └── src-tauri/ # Tauri backend (Rust commands wrapping core) ``` All business logic lives in `crates/core`. The CLI and Tauri app are thin shells — add new capabilities in core first. The frontend is split into focused ES modules — `app.js` is wiring only (DOM ready, button bindings, click delegate). Feature logic lives in dedicated modules: `state.js`, `tabs.js`, `auth.js`, `services.js`, `query.js`, `executor.js`, `results.js`, `trace.js`, `describe.js`, `annotations.js`, `history.js`, `valueList.js`, `fiori.js`, `favorites.js`, `addProfile.js`, plus utility modules (`html.js`, `format.js`, `status.js`, `clipboard.js`, `api.js`, `resultCache.js`). All imports flow downward — no module imports back up to `app.js`. ## Making changes 1. Fork and create a feature branch 2. Run `cargo fmt --check`, `cargo test --workspace`, and `git diff --check` 3. For frontend changes: rebuild CSS with `cd tauri-app && npm run css` 4. For Tauri changes: test the app with `cargo tauri build` 5. Keep commits focused — one concern per commit 6. Open a PR with a clear description ### Code style - **Rust**: run `cargo fmt` before committing - **JS**: ES modules, no framework, no TypeScript, no bundler (vendored Tauri API loaded directly). Keep it simple. Add new feature logic in a dedicated module — `app.js` is the entry/wiring file and stays small. - **HTML/CSS**: Tailwind utility classes, no inline event handlers (CSP forbids them) - **Clippy**: `cargo clippy --workspace --all-targets -- -D warnings` runs in CI as a hard gate. Don't introduce warnings; if a clippy lint is genuinely wrong for a specific case, suppress it locally with a narrowly-scoped `#[allow(clippy::xxx)]` attribute and a comment explaining why. ### Release hygiene - Do not commit local release builds, scratch metadata, traces, customer captures, or credentials. - Keep release packages under `dist/` and scratch SAP metadata under `tmp/`; both are ignored. - Do not commit `connections.toml`, `.env` files, TLS private keys, or customer certificates. - Keep public docs clear that this project is independent from SAP and intended for authorized, human-driven exploration of documented or customer-owned OData services. - See [docs/RELEASE-CHECKLIST.md](docs/RELEASE-CHECKLIST.md) before publishing a GitHub release. ### No inline event handlers The Tauri app's CSP sets `script-src 'self'` (no `'unsafe-inline'`), which blocks inline scripts and inline event-handler attributes such as `onclick="..."` from executing. Use `addEventListener` in the appropriate module, or `data-action` attributes routed through the document-level event-delegation handler. ### Always escape `innerHTML` interpolations SAP `$metadata` is untrusted input — entity names, annotation values, and error messages can contain HTML special characters. Any HTML string assigned to `.innerHTML` must escape every interpolation. Use the `safeHtml` tagged-template helper from `tauri-app/src/html.js`: ```js el.innerHTML = safeHtml`