# Orgbench — VS Code extension

A thin VS Code client of the `sf-core-server` core: compare Salesforce
`CustomField` metadata between two locally authenticated `sf` CLI aliases and
selectively deploy the differences, optionally synchronizing field-level
security (FLS). Authentication stays entirely in the local Salesforce CLI; the
extension never handles tokens or credentials. It shares the same Rust core as
the IntelliJ IDEA plugin.

## Requirements

- macOS arm64, macOS x64 or Windows x64 (the bundled core is fail-closed on
  other platforms; Linux is planned). The Windows x64 build is for Windows on
  x64; it has not been verified on Windows on ARM, and VS Code itself may
  reject installing an x64-targeted VSIX (`targetPlatform: win32-x64`) there.
- VS Code 1.85 or newer.
- Salesforce CLI (`sf`) installed and on `PATH`. On Windows the core also looks
  for `sf.exe`, `sf.cmd`, `sf.bat` and `sf` in `%LOCALAPPDATA%\sf\client\bin`.
- Two authenticated aliases that resolve to different Salesforce org IDs.

## Install from disk

1. Obtain the VSIX for your platform: `orgbench-darwin-arm64.vsix` (Apple
   silicon), `orgbench-darwin-x64.vsix` (Intel) or `orgbench-win32-x64.vsix`
   (Windows x64), or build it (below).
2. In VS Code, open the Extensions view, choose **Install from VSIX…** from the
   `…` menu, and select the file.
3. Open the **Orgbench** view from the Activity Bar.

## Workflow

1. Select a **Source Org** and a **Target Org** (different underlying org IDs).
2. Select one or more source objects and choose **Compare Fields**.
3. Review the differences, tick the deployable fields, pick an **FLS Mode**
   (**Do not transfer FLS**, **Additive FLS**, or **All FLS**), and **Deploy**;
   or **Back** to change the selection.
4. Read the field and FLS result tables. **Copy details** copies only the
   sanitized diagnostics. **New comparison** starts over.

Comparison or deployment can be cancelled from the progress view.

## Filtering

Every webview table (objects, differences, FLS containers, and both result
tables) shares one per-column filter row directly under its header:

- Text columns get a free-text prefix box (matches from the start of the
  value, case-insensitively).
- Enum columns — Change, Kind, Presence, Operation, Status — get a
  multi-select popup listing every value with checkboxes. Two carry a smart
  default: the differences Change popup hides `No change` rows, and the
  FLS-results Status popup hides `Skipped`.
- The selection column and boolean columns (Read/Edit) get a tri-state
  toggle.

Column filters combine with AND. Filtering only hides rows: a row that is
checked and then hidden by a filter keeps its selection, and the selection
column's header checkbox selects or clears only the currently visible,
filtered rows (hidden selections are left untouched). Filters reset to their
defaults when you leave the screen (a new comparison, or stepping between the
review and FLS-container screens).

Selections (chosen objects, deployable fields, and FLS containers), together
with each table's column filters and sort, are preserved when the view is
hidden and shown again, so switching away from the panel never re-checks a
container you deselected before deploying or drops the filters you set. Filters
and sort persist while you stay on a screen and reset only when you leave it.

## Sorting

Click any column header except the selection column to sort the table by that
column. Each click cycles the sort: ascending (▲), then descending (▼), then
off (original order). One column sorts at a time. Enum columns sort by their
displayed label; boolean columns (Read/Edit) sort unchecked-before-checked.
Sorting only reorders rows — it never changes which rows a filter has hidden —
and, like the column filters, persists while you stay on a screen, resetting to
the original order when you leave it.

## Settings

- `orgbench.coreServerPath` — absolute path to a `sf-core-server` binary
  that overrides the bundled one. For development only; leave empty to use the
  binary shipped inside the VSIX.

## Build

The extension is part of the repository's Gradle build:

```bash
cd vscode && npm ci
cd vscode && npm test          # tsc typecheck + node:test suite
cd vscode && npm run build     # esbuild: extension-host + webview bundles
./gradlew buildVsixAarch64     # writes vscode/orgbench-darwin-arm64.vsix
./gradlew buildVsixX64         # writes vscode/orgbench-darwin-x64.vsix
./gradlew buildVsixWin32X64    # writes vscode/orgbench-win32-x64.vsix
```

The three tasks share `vscode/bin/`, so they run one after another, never in
parallel. Building the Windows VSIX from macOS needs `cargo install cargo-xwin`
and `rustup target add --toolchain 1.97.0 x86_64-pc-windows-msvc`.

Each VSIX bundles exactly one native core binary for its target.

## Troubleshooting

### The Salesforce core process did not start

The extension launches a bundled `sf-core-server` binary from its `bin/`
directory. If the view reports that the core process could not start or
terminated, confirm the platform is supported (macOS arm64, macOS x64 or
Windows x64) and that the VSIX was installed without modification. On Windows
the bundled binary is unsigned, so SmartScreen or the antivirus may quarantine
it on first launch. The core process log is written to the **Orgbench Core**
output channel.

### No aliases are listed

Run `sf org list --json` in a terminal, authenticate aliases if needed, and use
the **Reload Orgs** button. Entries without an alias are intentionally not shown.

### Source and target are rejected as the same org

Choose aliases that resolve to different org IDs; two alias names can point to
one org.
