DataverseTableManager.CLI 1.4.8

dotnet tool install --global DataverseTableManager.CLI --version 1.4.8
                    
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 DataverseTableManager.CLI --version 1.4.8
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=DataverseTableManager.CLI&version=1.4.8
                    
nuke :add-package DataverseTableManager.CLI --version 1.4.8
                    

Dataverse Table Manager (DTM)

A powerful CLI tool for managing Dataverse tables, columns, forms, and webresources from JSON schema definitions. Build, deploy, and manage your Dataverse data model with ease.

.NET NuGet License: MIT

🚀 Features

Table & Column Management

  • ✅ Create, update, and delete Dataverse tables and columns from JSON
  • ✅ Support for all column types (Text, Number, Choice, Lookup, Boolean, etc.)
  • ✅ Global and local option sets (choice columns)
  • ✅ Relationship management with cascade configurations
  • ✅ Publisher prefix auto-generation
  • ✅ Dry-run mode to preview changes
  • ✅ Solution integration with automatic component binding

WebResource Management

  • ✅ Upload/download webresources (HTML, CSS, JS, XML, images)
  • ✅ File watching with auto-sync
  • ✅ Pattern-based include/exclude filtering
  • ✅ Solution integration and auto-publish
  • ✅ Bulk operations with progress reporting

Form Management

  • ✅ Create complete Main form layouts with tabs, sections, and fields
  • ✅ Export existing Main forms to JSON for backup or migration
  • ✅ Validate form definitions against table metadata
  • ✅ Rich JSON schema for form layout definition
  • ✅ Control visibility of tabs, sections, and fields
  • ✅ Support for Main forms (other form types not currently supported)

Developer Experience

  • ✅ Rich CLI with colored output and progress bars
  • ✅ Profile-based authentication management
  • ✅ JSON schema validation with helpful error messages
  • ✅ Comprehensive help system
  • ✅ Cross-platform support (Windows, Linux, macOS)

📦 Installation

# Install from NuGet
dotnet tool install --global DataverseTableManager.CLI

# Verify installation
dtm --version

Download Executable

Download the latest release from GitHub Releases

⚡ Quick Start

1. Authentication Setup

# Create authentication profile
dtm auth create --name "Dev" --environment "https://yourorg.crm.dynamics.com"

# Set as active profile
dtm auth set --name "Dev"

# List all profiles
dtm auth list

2. Create Your First Table

Create a schema.json file:

{
  "tables": [
    {
      "logicalName": "cjs_tutoringsession",
      "displayName": "Tutoring Session",
      "description": "Tracks tutoring sessions",
      "ownership": "UserOwned",
      "settings": {
        "enableActivities": true,
        "enableNotes": true,
        "isAuditEnabled": true
      },
      "primaryName": {
        "displayName": "Session Name",
        "maxLength": 200
      },
      "columns": [
        {
          "logicalName": "cjs_duration",
          "type": "Integer",
          "displayName": "Duration (mins)",
          "min": 0,
          "max": 1440,
          "requiredLevel": "ApplicationRequired"
        },
        {
          "logicalName": "cjs_sessiondate",
          "type": "DateTime",
          "displayName": "Session Date",
          "format": "DateOnly",
          "requiredLevel": "ApplicationRequired"
        },
        {
          "logicalName": "cjs_level",
          "type": "Choice",
          "displayName": "Level",
          "choice": {
            "globalName": "cjs_level_global"
          }
        },
        {
          "logicalName": "cjs_topics",
          "type": "MultiSelect",
          "displayName": "Topics",
          "choice": {
            "localOptions": ["Math", "Science", "English", "History"]
          }
        },
        {
          "logicalName": "cjs_studentid",
          "type": "Lookup",
          "displayName": "Student",
          "targets": ["contact"],
          "relationship": {
            "schemaName": "cjs_TutoringSession_Contact",
            "cascade": "Assign,Share,Unshare,Reparent,RemoveLink"
          }
        }
      ]
    }
  ]
}

3. Deploy to Dataverse

# Dry run to preview changes
dtm upsert schema.json --solution "YourSolution" --dry-run

# Deploy for real
dtm upsert schema.json --solution "YourSolution"

📖 Usage Guide

Table Management Commands

# Create/update tables from JSON
dtm upsert <file> --solution <solution> [--dry-run] [--verbose]

# Delete tables
dtm delete <file> --solution <solution> [--dry-run] [--force]

# Generate schema template
dtm schema generate --output schema.json [--table-count 3]

# Validate JSON schema
dtm schema validate <file>

WebResource Management Commands

# Upload webresources
dtm webresource push --path ./webresources --solution MySolution --publish

# Download webresources
dtm webresource pull --path ./webresources --solution MySolution --overwrite

# List webresources
dtm webresource list --solution MySolution --type JS --verbose

# Watch for changes (auto-sync)
dtm webresource watch --path ./webresources --solution MySolution --publish

# Delete webresources
dtm webresource delete --names "js/main.js,css/styles.css" --force

Forms Management Commands

# Create a new Main form with schema
dtm forms create --table contact --name "Enhanced Contact Form" --schema ./contact-form.json --solution MySolution

# Create a basic Main form
dtm forms create --table account --name "Simple Account Form" --type Main --solution MySolution

# Export existing Main form to JSON
dtm forms export --table contact --form "Information" --output ./contact-form.json

# Validate form definition
dtm forms validate --file ./contact-form.json

# Create form with dry-run (preview only)
dtm forms create --table lead --name "Lead Form" --schema ./lead-form.json --dry-run --verbose

Authentication Management

# Create profile
dtm auth create --name <name> --environment <url>

# List profiles
dtm auth list

# Set active profile
dtm auth set --name <name>

# Delete profile
dtm auth delete --name <name>

🏗️ JSON Schema Reference

Table Definition

{
  "logicalName": "prefix_tablename",      // Required: Table logical name
  "displayName": "Table Display Name",   // Required: Friendly name
  "description": "Table description",    // Optional: Description
  "pluralDisplayName": "Tables",         // Optional: Plural form
  "ownership": "UserOwned",              // UserOwned | OrganizationOwned
  "tableType": "Standard",               // Standard | Activity | Virtual
  "settings": {
    "enableActivities": true,            // Enable activities
    "enableNotes": true,                 // Enable notes/attachments
    "enableConnections": false,          // Enable connections
    "isAuditEnabled": true,              // Enable auditing
    "isDuplicateDetectionEnabled": false,// Enable duplicate detection
    "isBusinessProcessEnabled": false    // Enable business process flows
  },
  "primaryName": {
    "displayName": "Name",               // Primary name field display name
    "maxLength": 100                     // Max length (default: 100)
  },
  "delete": false                        // Set to true to delete table
}

Column Types

Text Column
{
  "logicalName": "prefix_textfield",
  "type": "Text",
  "displayName": "Text Field",
  "description": "A text field",
  "maxLength": 100,
  "requiredLevel": "None"               // None | Recommended | ApplicationRequired
}
Number Columns
{
  "logicalName": "prefix_number",
  "type": "Integer",                    // Integer | Decimal | Money
  "displayName": "Number Field",
  "min": 0,
  "max": 1000,
  "precision": 2                        // For Decimal/Money types
}
Choice Column (Local Options)
{
  "logicalName": "prefix_status",
  "type": "Choice",
  "displayName": "Status",
  "choice": {
    "localOptions": ["Active", "Inactive", "Pending"]
  }
}
Choice Column (Global Option Set)
{
  "logicalName": "prefix_priority",
  "type": "Choice",
  "displayName": "Priority",
  "choice": {
    "globalName": "priority_global"
  }
}
Lookup Column
{
  "logicalName": "prefix_customerid",
  "type": "Lookup",
  "displayName": "Customer",
  "targets": ["account", "contact"],
  "relationship": {
    "schemaName": "prefix_table_customer",
    "cascade": "Assign,Share,Unshare,Reparent,RemoveLink"
  }
}
Boolean Column
{
  "logicalName": "prefix_isactive",
  "type": "Boolean",
  "displayName": "Is Active",
  "trueLabel": "Yes",
  "falseLabel": "No"
}
DateTime Column
{
  "logicalName": "prefix_duedate",
  "type": "DateTime",
  "displayName": "Due Date",
  "format": "DateOnly"                  // DateOnly | DateAndTime
}

Cascade Options

Available cascade behaviors for relationships:

  • Assign - Cascade on assign
  • Share - Cascade on share
  • Unshare - Cascade on unshare
  • Reparent - Cascade on reparent
  • Delete - Cascade on delete
  • Merge - Cascade on merge
  • RemoveLink - Remove link only

Combine multiple behaviors with commas: "Assign,Share,Unshare,Reparent,RemoveLink"

🔧 Advanced Usage

Publisher Prefix Auto-Generation

DTM automatically generates logical names using your solution's publisher prefix:

# If your solution has publisher prefix "cjs", this JSON:
{
  "logicalName": "tutoringsession",
  "displayName": "Tutoring Session"
}

# Becomes: "cjs_tutoringsession" in Dataverse

Batch Operations

# Process multiple schema files
dtm upsert schema1.json schema2.json --solution MySolution

# Use wildcards
dtm upsert schemas/*.json --solution MySolution

WebResource File Patterns

# Include only JavaScript files
dtm wr push --include "**/*.js"

# Exclude node_modules and build artifacts  
dtm wr push --exclude "node_modules/**,dist/**,*.min.*"

# Complex patterns
dtm wr push --include "src/**" --exclude "src/**/*.test.js"

Environment-Specific Workflows

# Development
dtm auth create --name "Dev" --environment "https://yourorg-dev.crm.dynamics.com"
dtm upsert schema.json --profile "Dev" --solution "DevSolution"

# Production  
dtm auth create --name "Prod" --environment "https://yourorg.crm.dynamics.com"
dtm upsert schema.json --profile "Prod" --solution "ProdSolution"

🎯 Best Practices

1. Schema Organization

  • Keep table definitions in separate files for large projects
  • Use consistent naming conventions
  • Document your schema with descriptions
  • Version control your JSON schemas

2. Solution Management

  • Always specify a solution to avoid components in the default solution
  • Use meaningful solution names and descriptions
  • Separate development and production solutions

3. Testing Strategy

  • Always use --dry-run before actual deployment
  • Test in development environment first
  • Validate your JSON schema before deployment
  • Use version control to track changes

4. WebResource Organization

webresources/
├── css/
│   ├── global.css
│   └── forms.css
├── js/
│   ├── common.js
│   ├── account.form.js
│   └── contact.form.js
├── html/
│   └── help.html
└── images/
    ├── logo.png
    └── icons/

🚨 Troubleshooting

Common Issues

Authentication Errors
# Check active profile
dtm auth list

# Recreate profile if needed
dtm auth delete --name "ProfileName"
dtm auth create --name "ProfileName" --environment "URL"
Schema Validation Errors
# Validate schema first
dtm schema validate schema.json

# Check for common issues:
# - Missing required fields
# - Invalid column types
# - Malformed JSON
Connection Issues
  • Verify environment URL is correct
  • Check network connectivity
  • Ensure user has appropriate permissions
  • Try recreating the authentication profile
Permission Issues

Required Dataverse permissions:

  • System Customizer role or equivalent
  • Create, Read, Write permissions on:
    • Entity (Table) metadata
    • Attribute (Column) metadata
    • Solution components
    • WebResource entities (for webresource commands)

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# Clone repository
git clone https://github.com/wezthecode/dataverse-table-manager.git
cd DataverseTableManager

# Build
dotnet build

# Run tests
dotnet test

# Run CLI locally
dotnet run --project DataverseTableManager.CLI -- --help

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

This project was inspired by and builds upon patterns from:

  • Greg.Xrm.Command by Gered King - A fantastic CLI tool for Dataverse operations that provided excellent patterns for command structure, authentication management, and professional CLI UX. Many of our CLI design decisions and authentication patterns were influenced by this outstanding project.

  • Javista.AttributesFactory - A tool for bulk attribute creation that demonstrated clean approaches to Dataverse metadata operations.

Special thanks to the Microsoft Dataverse team for providing the foundational tools and APIs that make this project possible.

📞 Support


Made with ❤️ for the Dataverse community

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  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
1.4.8 226 10/6/2025

Enhanced authentication with token caching, improved error handling, and comprehensive form management capabilities.