PACX ⁓ Working with solutions
Tags: powerplatform, dataverse, github, opensource
Published: 2024-06-09 14:39:57

[PAC CLI provides a rich namespace](https://learn.microsoft.com/en-us/power-platform/developer/cli/reference/solution) dedicated to working with Dataverse solutions.

The commands provided there are really powerful, and designed to **drive a code-first approach to solution management**, that personally I ❤️ a lot.

Before PACX, my usual Dataverse development cycle was:

1. use `pac solution init` to initialize locally my dataverse solution project (*.cdsproj)
2. manually update the generated `Solution.xml` file to add details about my company's publisher
3. build the solution via `dotnet build`
4. if not previously done, connect to my Dataverse environment via `pac auth`
5. publish the solution to dataverse via `pac solution import`
6. start manually create/update solution components via make.powerapps.com
7. sync the changes locally via `pac solution sync`
8. when ready, commit everything on my Azure DevOps repo

When I started scripting data model manipulations with PACX, I felt the urge of a couple more commands to streamline my development activities.

## pacx solution setDefault

At first it was `pacx solution setDefault`. This came [before Dataverse preferred solution](https://learn.microsoft.com/en-us/power-apps/maker/data-platform/preferred-solution) feature came out, and it's pretty much a "local" version of it.

When I created tables or columns via PACX (_we'll see how to in the upcoming articles_) I wanted them to be placed automatically in the context of a given solution. `pacx solution setDefault` allows user to define which solution should be considered "default" from now on, on the currently selected environment. 

![pacx solution setDefault](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z7kq4cg6pg7wdp8vqf4b.png)

PACX saves in it's local settings storage the default solution specified for each environment. Then, when I ran any command such as `pacx table create`, I no longer needed to pass the --solution argument. Time saved 😎

## pacx solution getDefault

In complex scenarios, when I have multiple solutions in place, it happens to forget which solution is set as default for the current environment. That's why I created the second command, `pacx solution getDefault`. It simply returns the default solution set for the current environment, if any.

![pacx solution getDefault](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0tppvsye7ul63q6qlmuk.png)

## pacx solution create

The code-first approach to solution management is great but... what if you just need to create a temporary solution (e.g. to work with Ribbon Workbench) that you don't want to save locally or on the repo? 

I often found myself in the situation where the solution where already there, and I needed to segregate specific components in a separate one. `pacx solution create` creates a new solution directly on the current environment, without saving anything locally. 

> If you want, you can later clone that solution using `pac solution clone` and keep it updated via `pac solution sync`.

`pacx solution create` has the same behavior of `pac solution init`: creates the solution and also the publisher if needed.

The minimum required info for the command is the (display) `name` of the solution to create, and one of `publisherUniqueName` or `publisherPrefix` (you can specify both, at least 1 is required).

```Powershell
pacx solution create --name master --publisherUniqueName greg
pacx solution create -n master -pun greg

pacx solution create --name master --publisherPrefix greg
pacx solution create -n master -pp greg
```

The following conventions apply:

- if the `uniqueName` argument is not specified, it's reduced from the `name` argument considering only letters, numbers or underscores, all in lowercase.
- solution version is set to 1.0.0.0 by default
- solution is (of course) unmanaged
- about the publisher
  - if `publisherUniqueName` is specified, the tool tries to find a publisher with that unique name in the environment. If found, it is used as publisher for the solution. 
  - if `publisherUniqueName` is not specified, but `publisherPrefix` is provided, the tool tries to find a publisher with that prefix in the environment. If found, it is used as publisher for the solution. 

If no publisher has been found, a new publisher is created, with the following defaults:

- **uniquename**: 
  - uses `publisherUniqueName` if provided, otherwise 
  - uses `publisherFriendlyName` if provided (considering only letters, numbers and underscores), otherwise
  - uses `publisherPrefix` 
- **friendlyname**:
  - uses `publisherFriendlyName` if provided, otherwise
  - uses `publisherUniqueName` if provided, otherwise 
  - uses `publisherPrefix`
- **customizationprefix**:
  - uses `publisherPrefix` if provided, otherwise
  - uses `publisherUniqueName` if provided, considering only letters or numbers. If the length of the generated string is <= 5 chars, takes the whole string, otherwise extracts the first 3 chars. Otherwise...
  - uses `publisherFriendlyName`, considering only letters or numbers. If the length of the generated string is <= 5 chars, takes the whole string, otherwise extracts the first 3 chars.
- **customizationoptionvalueprefix**:
  - uses `publisherOptionSetPrefix` argument if provided, otherwise sets it to 10000

Personally, now I use it a lot. I changed the approach described in the beginning of the current article this way:

1. use `pacx solution create` to create my solution on the dataverse environment, also creating the publisher if needed
2. set that solution to default via `pacx solution setDefault`
3. start the data model manipulations via `pacx table`, `pacx column` and `pacx rel` commands
4. when ready, clone the solution locally via `pac solution clone`
5. do all the other stuff via pacx or make.powerapps.com
6. sync the changes locally via `pac solution sync`
7. when ready, commit everything on my Azure DevOps repo

I find this approach more lean and direct, and allows me to focus on content right at step #2 instead of step #6 as before.

## pacx solution delete

I added this command because I'm lazy. [PAC CLI already contains a command to delete a solution](https://learn.microsoft.com/en-us/power-platform/developer/cli/reference/solution#pac-solution-delete) from a given environment, but I kept forgetting it and writing 

```Powershell
pacx solution delete ...
```

instead of

```Powershell
pac solution delete ...
```

Thus... I created an alias command, that does basically the same thing.

## pacx solution getPublisherList

This is quite easy, it just prints the list of publishers already available in the current environment

![pacx solution getPublisherList](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gfomgh32125g4fl1x2ot.png)

---

In the next articles we'll deep dive on table management commands.