Scripts/ExportSolution.ps1

# ExportSolution.ps1
function Get-DataverseSolution {
    Param(
        [string] [Parameter(Mandatory = $true)] $StartPath,
        [string] [Parameter(Mandatory = $true)] $SelectedSolution
    )
    try {
        
        $SolutionName = $SelectedSolution
        ######################## EXPORT SOLUTION
        
        ##Update version file
        Set-DataverseSolutionVersion
        
        $patchFilesFolderPath = (Join-Path $StartPath "Patches\") 
        $deployfilesfolderpath = (Join-Path $StartPath "Deploy\") 
    
        ## No Patches
        If (!$PatchQuery.CrmRecords) {
            
            Remove-Item $patchFilesFolderPath -Force -Recurse -ErrorAction Ignore
            Remove-Item $deployfilesfolderpath -Force -Recurse -ErrorAction Ignore
            
            # Export and unpack
            Unpack-Solution "$SolutionName" -IsPatchExport $false
        }
        else {
            ##Export Patches
            $patchSolutionNames = @()

            foreach ($PatchSolution in $PatchQuery.CrmRecords) {
                $patchSolutionNames += $PatchSolution.uniquename
                # Export and unpack
                Unpack-Solution "$($PatchSolution.uniquename)" -IsPatchExport $true
            }
            
            $exportedPatchSolutionNames = Get-ChildItem -Path $patchFilesFolderPath -Directory | Select-Object -ExpandProperty Name
            $filteredPatchSolutionNames = $exportedPatchSolutionNames | Where-Object { $patchSolutionNames -notcontains $_ }
            foreach ($patchSolutionName in $filteredPatchSolutionNames) {
                Write-Host "Deleting patch: $patchSolutionName"

                # Remove the folder and its contents
                Remove-Item -Path (Join-Path $patchFilesFolderPath $patchSolutionName) -Recurse -Force -ErrorAction SilentlyContinue
                
                # Remove the managed and unmanaged zip files
                Remove-Item -Path (Join-Path $deployfilesfolderpath "$patchSolutionName.zip") -Force -ErrorAction SilentlyContinue
                Remove-Item -Path (Join-Path $deployfilesfolderpath "$($patchSolutionName)_managed.zip") -Force -ErrorAction SilentlyContinue

                Write-Host "Deleted patch: $patchSolutionName"
            }
        }
         
        Get-FlowsToBeDeployed "$StartPath" $SelectedSolution

        Get-ExportDataValid
    }
    catch {
        Write-Host $_
        pause
    }
    finally {

    }
}

function Unpack-Solution {
    Param(
        [string] [Parameter(Mandatory = $true)] $ExportSolutionName,
        [bool] [Parameter(Mandatory = $true)] $IsPatchExport = $false
    )
    try {
        $pacexepath = "$env:APPDATA\Capgemini.PowerPlatform.DevOps\PACTools\tools\pac.exe"
        $deployfilesfolderpath = (Join-Path $StartPath "Deploy\") 
        
        # Define the full path for the exported ZIP file
        $unmanagedExportedZipFilePath = Join-Path $deployfilesfolderpath "$ExportSolutionName.zip"
        Write-Host "Unmanaged solution file name: $unmanagedExportedZipFilePath"
        
        if (!(Test-Path -Path $unmanagedExportedZipFilePath)) {

            # Export the unmanaged solution to a ZIP file
            $unmanagedExportCommand = "solution export -n $ExportSolutionName -p $deployfilesfolderpath --managed false --async --max-async-wait-time 120"
            Write-Host "Running export command: $pacexepath $unmanagedExportCommand"
            & $env:APPDATA\Capgemini.PowerPlatform.DevOps\PACTools\tools\pac.exe solution export -n $ExportSolutionName -p $deployfilesfolderpath --managed false --async --max-async-wait-time 120
        
            # Export the unmanaged solution to a ZIP file
            $managedExportCommand = "solution export -n $ExportSolutionName -p $deployfilesfolderpath --managed true --async --max-async-wait-time 120"
            Write-Host "Running export command: $pacexepath $managedExportCommand"
            & $env:APPDATA\Capgemini.PowerPlatform.DevOps\PACTools\tools\pac.exe solution export -n $ExportSolutionName -p $deployfilesfolderpath --managed true --async --max-async-wait-time 120
        
            # Check if the export was successful
            if (Test-Path -Path $unmanagedExportedZipFilePath) {
                Write-Host "Solution exported successfully: $unmanagedExportedZipFilePath"            

                # If $IsPatchExport unpack to Patches folder. Otherwise unpack to src folder
                if ($IsPatchExport) {
                    Write-Host "Patch solution exported"
                    $destinationfolderpath = (Join-Path $StartPath "Patches\$ExportSolutionName\")

                }
                else {
                    Write-Host "Full solution exported"
                    Remove-Item (Join-Path $StartPath "src\.") -Force -Recurse -ErrorAction Ignore
                    $destinationfolderpath = (Join-Path $StartPath "src\")
                }
            
                Write-Host "Unpacking to destination folder path - " $destinationfolderpath

                # Unpack the solution (extract the content)
                $unpackCommand = "solution unpack --zipfile $unmanagedExportedZipFilePath --folder $destinationfolderpath --packagetype Both --processCanvasApps true"
                Write-Host "Running unpack command: $pacexepath $unpackCommand"
                & $env:APPDATA\Capgemini.PowerPlatform.DevOps\PACTools\tools\pac.exe solution unpack --zipfile $unmanagedExportedZipFilePath --folder $destinationfolderpath --packagetype Both --processCanvasApps true
        
            } 
            else {
                Write-Host "Solution export failed!"
            }
        }
    }
    catch {
        Write-Host $_
        pause
    }
}

function Get-FlowsToBeDeployed {
    Param(
        [string] [Parameter(Mandatory = $true)] $StartPath,
        [string] [Parameter(Mandatory = $true)] $SelectedSolution
    )
    try {
        Write-Host "Generating Flows_Default.json to Support Flow Activation"
        $SolutionName = $SelectedSolution
        $SolutionPath = (Join-Path $StartPath "src\Workflows")
        $FlowJSON = @()

        $Workflows = Get-ChildItem -Path $SolutionPath -Filter *.json -ErrorAction SilentlyContinue
        if ($Workflows) {
            $Workflows | ForEach-Object {
                $FlowName = $_.BaseName.SubString(0, $_.BaseName.Length - 36)
                $FlowID = $_.BaseName.Replace($FlowName, '')
                $FlowJSON += @([ordered]@{FlowID = $FlowID; FlowName = $FlowName; ActivateAsUser = ""; })
            }
            ConvertTo-Json -Depth 3 $FlowJSON | Format-Json | Out-FileUtf8NoBom $StartPath\Flows_Default.json            
        }

    }
    catch {
        Write-Host $_
        pause
    }
}