Pdelvo.Dvx.Cli 0.1.0-ci.2

This is a prerelease version of Pdelvo.Dvx.Cli.
The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet tool install --global Pdelvo.Dvx.Cli --version 0.1.0-ci.2
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local Pdelvo.Dvx.Cli --version 0.1.0-ci.2
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=Pdelvo.Dvx.Cli&version=0.1.0-ci.2&prerelease
                    
nuke :add-package Pdelvo.Dvx.Cli --version 0.1.0-ci.2
                    

dvx

Declarative deployment + SDK for Microsoft Dataverse / Dynamics 365 plugins. dvx replaces spkl-style imperative registration with a Terraform-like plan/apply model, and replaces hand-written plugin boilerplate with source-generated code.

You write only this, in a plain SDK-style csproj:

using Dvx;
using Dvx.Model;

public partial class AccountPlugins
{
    [Step(typeof(Account), Msg.Update, Stage.PreOperation,
        Filtering = new[] { Account.Cols.CreditLimit },
        Key = "account-block-creditlimit-downgrade")]
    public void BlockCreditLimitDowngrade(IStepContext<Account> ctx)
    {
        if (ctx.Target.CreditLimit < ctx.PreImage.CreditLimit)
            throw ctx.Fail("Credit limits can't be lowered.");
    }
}

Then run dotnet build -t:Deploy. Everything else is generated or computed:

  • the IPlugin entry class and the embedded context runtime (no base classes, no runtime DLL, no ILMerge),
  • the pre-image registration — columns inferred from your code (ctx.PreImage.CreditLimit above ⇒ a pre-image with exactly creditlimit); escapes are compile errors, never a silent "all columns",
  • the registration manifest, diffed field-by-field against the live environment.

A no-op deploy performs zero writes in ~5 read round trips. dvx plan shows exactly what would change (--json for machines, exit code 0 = clean / 2 = changes pending) — put it in CI and never let an environment drift again.

Feature overview

Feature How
Early-bound models dvx model sync --entities account,contact snapshots metadata into dataverse.snapshot.json (committed); a source generator emits entity classes, Cols constants, and optionset enums in-memory — no generated .cs files on disk
Plugin steps [Step(typeof(Account), Msg.Update, Stage.PreOperation, ...)] on a plain method taking IStepContext<Account>
Images Inferred from ctx.PreImage.X / ctx.PostImage.X access; explicit [Image(...)] as the escape hatch
Custom APIs [CustomApi("dvx_Reverse")] on a method with record request/response types; parameters sync automatically; typed callers are generated
Computed columns [Derive(Account.Cols.Description)] on a pure static method — compiles to coalesced, dependency-ordered Create/Update steps with inferred filtering
Deployment dvx plan / dvx apply (or dotnet build -t:Plan / -t:Deploy): field-level diff, sha256 assembly-upload skip, --prune for env-only components
Guard rails 20+ compile-time diagnostics (DVX0xx): invalid stage/mode combos, pre-image on Create, filtering on unsupported messages, duplicate keys, impure derives, …

Getting started

The five-minute version

# 1. install the CLI (or run it from source: dotnet run --project src/Dvx.Cli --)
dotnet tool install --global Pdelvo.Dvx.Cli --prerelease

# 2. in your plugin repo: describe your environments (no secrets — this file is committed)
cat > dataverse.yaml <<'EOF'
default: dev
environments:
  dev:
    url: https://yourorg.crm.dynamics.com
    solution: yoursolution
    prefix: your
EOF

# 3. sign in once (device code; later runs are silent)
dvx auth login
dvx whoami

# 4. snapshot the entities you use
dvx model sync --entities account,contact

# 5. build & deploy
dotnet build -t:Deploy

Architecture in one paragraph

Plugins target net462 and reference exactly one package, Dvx.Sdk (attributes + source generators + MSBuild targets). The generators are pure: metadata comes exclusively from the committed dataverse.snapshot.json, so builds are reproducible and CI needs no Dataverse connection. The registration manifest is emitted as an inactive preprocessor block — it contributes zero IL, so a registration-only change (a rank, a filter column) never changes the assembly hash and never re-uploads the DLL. The dvx CLI talks raw Dataverse Web API (no Microsoft.PowerPlatform.Dataverse.Client dependency), reads the environment in a constant number of queries, canonicalizes both sides, and PATCHes only changed columns. Matching precedence for existing steps: explicit IdKey → natural key (plugin type, message, entity, stage) when unique on both sides → name; ambiguity is a hard error, never a heuristic.

Repository layout

src/Dvx.Cli/              the dvx CLI (net9.0, packs as dotnet tool Dvx.Cli)
src/Dvx.Sdk/              attributes (netstandard2.0) — the package plugins reference
src/Dvx.Sdk.Generators/   Roslyn incremental generators + diagnostics (ships inside Dvx.Sdk)
src/Dvx.Sdk.Targets/      MSBuild props/targets (ship inside Dvx.Sdk)
tests/                    unit, generator, and live-environment integration tests
samples/TestPlugins/      end-to-end sample plugin project
docs/                     getting started, spkl migration, API spec, backlog

Building

dotnet build && dotnet test

Integration tests run only when DVX_TEST_URL is set and create only prefixed, torn-down test components. CI publishes prerelease packages to NuGet as unlisted versions.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated