Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Simply AT4DXNew to Visual Studio Code? Get it now.
Simply AT4DX

Simply AT4DX

SimplySF

|
50 installs
| (0) | Free
Explore AT4DX Trigger Action Framework bindings for an SObject — execution order, criteria, and actions — without leaving VS Code.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Simply AT4DX for Visual Studio Code

Explore AT4DX framework bindings without leaving VSCode.

  • View bindings from local source and connected orgs
  • Edit bindings from local source and connected orgs
  • Reports errors with configured bindings and sequence collisions

Usage

The panel is titled AT4DX Explorer and carries a tab strip across the top for the framework's four explorers — Domain Process Bindings, SObject Bindings, Service Bindings, and Platform Events. SObject Bindings and Service Bindings share one lazily-triggered Application Factory scan: switching to either the first time triggers it against whatever source you picked, and switching between the two afterward never re-scans. Platform Events scans lazily the same way, on its own first visit.

Run AT4DX: Open Explorer from the Command Palette. You'll be prompted to:

  1. Pick a workspace folder (if more than one is open).
  2. Pick where to read bindings from — the whole workspace, a specific folder you browse to (handy for a multi-package-directory project), or a connected org. The connected-org list is read directly from your local Salesforce CLI auth files, not by shelling out to sf org list.

The panel then opens right away, with its SObject and Trigger Event dropdowns disabled while it scans. Once the scan completes, the dropdowns populate and enable — pick an SObject, then a trigger event (Created/Updated/Deleted/Undeleted) or Domain Method Execution, and the panel groups that SObject's bindings into Before/After sections in execution order. Switching either dropdown re-renders instantly, with no re-scan. Click a row to open its class.

Each section shows a real column grid — Order, Type, Class to Inject, Async, Recursion, Logical Inverse, and Status — instead of one flex row of icons and a developer name. Class to Inject is the row's identifier (clicking it, or anywhere in the row, opens the class). Async and Logical Inverse render as Yes or a dim em-dash; Recursion (short for "recursion prevented") renders as Disabled or a dim em-dash, so a whole section can be scanned at a glance without hovering anything. Below roughly 700px those two columns drop out to keep the remaining ones legible, with a tooltip on each cell so their state stays discoverable; the row's own tooltip shows its developer name.

When a section's bindings span more than one order prefix (10.1–10.3 vs 20.1–20.2, following the AT4DX convention where the integer part of Execution_Order__c is a unit of work and the fraction orders the bindings inside it), the rows group into collapsible bands — a caption naming the prefix, what it's made of (1 criteria gates 2 actions), and its order range. A section with only one prefix renders no band at all. Collapsing a band never hides a problem: if any row inside carries an issue badge, the caption shows a warning count while collapsed.

Validation

Every scan is also validated, automatically — there's no separate command and nothing to turn on. A summary bar above the dropdowns reads ✓ No problems found, or ⚠ N errors · M warnings split into "in this SObject" and "elsewhere in this scan" so a clean-looking selection is never masking a problem under a different SObject; clicking it scrolls to the Issues section. Any row with a problem gets a colored badge naming it. Below the binding sections, an Issues section lists every problem found, including ones that can't appear as a row at all — a binding with no SObject reference, for example, is dropped from the SObject list entirely and only ever shows up here. Clicking a local issue opens its .md-meta.xml beside the panel; org-sourced issues aren't clickable, since there's no local file to open.

Creating and editing bindings

Click + New Binding in the panel toolbar to add a binding, prefilled with the SObject and Trigger Event you're currently viewing, or click the pencil icon on any row to edit that binding. The toolbar and its + New Binding button are hidden the whole time either form is open, so there's never more than one primary action on screen. A breadcrumb under the header names the scope the binding is locked to and its Action/Criteria type; while creating, a monospace line under the "resulting binding" sentence previews the equivalent domain-process-binding create command. Either opens a form for every DomainProcessBinding__mdt field, grouped into three sections — Identity, When it runs, What it does — with a live sentence above them showing the binding you're about to save (e.g. "When an Account is Created, run the Action AssignOwner.cls at order 10.3 during Trigger Execution"), recomputed as you type. Developer Name is fixed once you're editing an existing record, since renaming one is really a delete-and-recreate from Salesforce's own perspective. Execute asynchronously only appears for an Action — a Criteria row has no async concept, so the checkbox (and any stale value on an existing record) is hidden and cleared rather than shown disabled.

Saving writes to whatever you picked when you opened the panel: a local folder gets its .md-meta.xml file created or updated on disk; a connected org gets the equivalent record deployed directly, with nothing left in your workspace. If the write would introduce a wiring problem AT4DX validation already knows how to catch — an order collision, a duplicate Developer Name, and so on — the form stays open with the issue(s) shown and the button becomes Save Anyway, so you can push through deliberately instead of guessing why nothing happened. A successful save re-scans and refreshes the panel immediately, so the new or changed binding (and anything it now flags) shows up right away.

SObject Bindings and Service Bindings

These two tabs read the four ApplicationFactory_{Service,Selector,Domain,UnitOfWork}Binding__mdt Custom Metadata Types — which Apex class implements which interface, which selector/domain handles which SObject, and which SObjects join the shared Unit of Work. See 0017 for the full design and its staging.

SObject Bindings groups Selector, Domain, and Unit of Work bindings into one card per SObject (any SObject wired into at least one of the three). A card names its SObject, an "N gap(s)" indicator when it's missing a Domain or a Unit of Work binding (Selector has no such floor — an SObject can have zero, one, or several), and lists its bindings: each Selector row's priority and WINS/SHADOWED status (the same resolution AT4DX itself computes — a higher Priority__c wins, a blank sorts lowest), each Domain row's bound implementation, and the Unit of Work row's commit position and sequence. A missing Domain or Unit of Work binding renders as its own row with an Add link, prefilled with the type and SObject already fixed. Click + New Binding — its caret opens a menu naming which of Selector, Domain, or Unit of Work you're creating (each with a one-line note on how many are allowed per SObject and what happens if you add a second) — or the pencil icon on any row to edit an existing one; either opens the form with the type already fixed and picks up the same wiring-problem/Save Anyway contract the Domain Process form already uses. A Selector, Domain, or Unit of Work binding's SObject field flags a standard object that can't support a metadata relationship (e.g. Task) in red with a "Use … as an alternate name" action, rather than blocking the save outright — the underlying eligibility table is explicitly best-effort.

Service Bindings is a flat interface → implementation table. Each row shows its resolution — Effective (this is the one AT4DX actually uses), Shadowed (a higher-priority binding for the same interface won instead) — with priority the deciding field, same as Selector's. Two bindings tied on priority render an amber banner over the group, with Resolves today on the one AT4DX currently picks and May win instead on the rest — that's a "this isn't deterministic" notice, not an error, since AT4DX itself still resolves one and binding validate doesn't fail on it.

A card whose SObject has a Unit of Work binding can also be reordered directly on the sheet: drag its ⣿ handle, or use the Move Up/Down buttons beside it — both stage the same pending move, so keyboard and pointer users get the identical result (this is the keyboard-operable equivalent an earlier release deliberately deferred, since plain HTML5 drag-and-drop has none). Staged moves show in a bar at the top — Revert discards them, Save commit order writes each one; if a save fails partway through, the bar reports how many of the pending moves actually saved and which SObject stopped it, and the rest are left unattempted rather than guessed at. Two cards sharing the same sequence show an amber sequence-collision banner between them — both still register, only their relative order is indeterminate, so it's a warning, never something that blocks a drag or a save. A card with no Unit of Work binding at all has nothing to reorder — that's what its own Add row is for.

A Selector row's edit form has its own Field set inclusions section: which field sets Selector queries include on top of the object's base fields, listed by API name with a ✕ to remove one and a text field + Add to include another. Both write immediately and independently of the binding form's own Save button — the drawer stays open either way, so adding a field set never interrupts whatever else you were editing. Removing one deactivates rather than deletes it (the underlying metadata has no delete), so it's never truly gone, just stops contributing. A SObject's total active count shows right on its Selector row on the SObject Bindings sheet, e.g. "2 field sets."

Commit order can still be set directly, without dragging, via the Unit of Work binding's edit form — its Commit Sequence number field's live preview shows where a typed value would land (1st, 2nd, ...) against every other Unit of Work binding already in the scan.

Every create/edit form's breadcrumb names its type (Selector/Domain/Unit of Work/Service) and how it was opened — free-typed from the toolbar, or fixed from a card's own Add link — and a monospace line previews the equivalent binding create command while creating. The "resulting binding" sentence itself reflects live priority competition: creating or editing a Selector or Service binding that shares its key with another one already in the scan says so — who wins, who's tied, or who shadows whom — the same resolution AT4DX itself computes.

A Problems section below each tab lists what Application Factory validation catches for that tab's own binding types — a missing or ambiguous SObject reference, a standard object that can't support a metadata relationship (e.g. Task), a duplicate To__c/SObject/sequence, and so on — grouped errors-then-warnings, with the same click-to-open-the-file behavior as the Domain Process explorer's own Issues section.

Platform Events

This tab reads PlatformEvents_Subscription__mdt — the AT4DX Platform Event Distributor's registration table. It matters more than it might look: the distributor swallows every consumer construction/execution failure into a debug log and nothing else, so a dead subscription is otherwise invisible in the org. See 0018 for the full design.

Subscriptions are grouped Event Bus → Category → subscription, since EventCategory__c is the axis the distributor's own matcher rules branch on. Each row shows its consumer class, which fields its Matcher Rule compares (Bus only, Bus + Category, Bus + Event, or Bus + Category + Event), its event value (or any when the rule doesn't use it, or a red blank warning when it does and the field is empty), sync/async, and a status: Active, Inactive (excluded by the distributor's own WHERE IsActive__c = TRUE), Throws (the matcher rule needs a field that's blank — a real NullPointerException at distribution), or Never fires (registered and legal, but the distributor's own pre-filter can never admit it). Throws/Never-fires rows carry an inline explanation of exactly why, right under the row.

Simulate a match… opens a drawer where you pick an Event Bus and type a Category__c/EventName__c, and it shows the exact consumer set the distributor would build for that event — in order, sync/async — plus every subscription on that bus that wouldn't match and why. This runs entirely against the already-scanned metadata; it never touches your org.

+ New Subscription opens a create form (or click a row's pencil icon to edit): Matcher Rule is chosen first, since it decides which of Event Category/Event become required — the form's hint text updates live as you switch it. Saving writes one .md-meta.xml file (or deploys the equivalent record to a connected org), with IsActive__c defaulting to true. Same wiring-problem/Save Anyway contract as every other binding form in this panel.

Troubleshooting

Every binding lookup logs a one-line summary (source, duration, outcome) to the AT4DX Explorer output channel (View → Output, then pick it from the dropdown) — no setup needed. If something's failing and you need to share more detail in a bug report, turn on the simply-at4dx.debug setting, reproduce the problem, and copy the channel's contents: with it on, entries also include the org/source detail and captured error output. It's off by default since that detail can include org usernames and local file paths.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft