public/Import-SfMetadataModel.ps1

function Import-SfMetadataModel {

    <#
        .SYNOPSIS
        Imports a metadata model from Excel workbooks and/or CSV files.

        .LINK
        Online version: https://codeberg.org/uwe-braig/sf-metadata-toolkit
    #>


    [CmdletBinding()]
    param (
        # Path to a .xlsx file, a .csv file, or a directory containing schema-named files.
        # Accepts pipeline input; multiple paths are accumulated into a single metadata model.
        [Parameter(Position = 0, ValueFromPipeline)]
        [string] $Path,

        # If Path is a directory, recurse into subdirectories.
        [Parameter()]
        [switch] $Recurse
    )

    begin {
        $ErrorActionPreference = 'Stop'
        [bool] $IsDebug   = $DebugPreference   -ne 'SilentlyContinue'
        [bool] $IsVerbose = $VerbosePreference -ne 'SilentlyContinue'

        Write-Debug "ModuleRoot: $($Script:ModuleRoot)"

        # --- initialize model; schema and SchemaToTableMapping are loaded inside New-SfMetadataModel
        $MetadataModel = New-SfMetadataModel

        # --- local helper: normalize and merge a single table into the model
        function AddToModel {
            param (
                [string] $SchemaName,
                [string] $Source,
                [array]  $Rows
            )

            [string] $TableName = $MetadataModel.SchemaToTableMapping[$SchemaName]

            $ConvertParams = @{
                Rows        = $Rows
                TableSchema = $MetadataModel.Schema[$SchemaName]
                Source      = $Source
            }
            [PSCustomObject[]] $NormalizedRows = ConvertTo-NormalizedModelTable @ConvertParams

            $MetadataModel.Tables[$TableName] += $NormalizedRows

            $LogString = "{0,-8}|{1,10}|{2}" -f 'Imported', $NormalizedRows.Count, $Source
            Write-Verbose $LogString
        }
    }

    process {

        # --- resolve input: single file or directory
        [array] $Files = if (Test-Path -Path $Path -PathType Leaf) {
            Get-Item -Path $Path
        }
        elseif ($Recurse) {
            Get-ChildItem -Path (Join-Path $Path '*') -Include '*.xlsx', '*.csv' -Recurse
        }
        else {
            Get-ChildItem -Path (Join-Path $Path '*') -Include '*.xlsx', '*.csv'
        }

        # --- check ImportExcel dependency if any .xlsx files are present
        if ($Files | Where-Object { $_.Extension -eq '.xlsx' }) {
            Assert-ModuleDependency -ModuleName 'ImportExcel'
        }

        # --- process each file
        foreach ($File in $Files) {

            if ($File.Extension -eq '.csv') {

                $SourceName = $File.FullName
                # --- schema names never contain a hash; a hash marks a numbered suffix (comment-style), e.g. '_FieldDependencies#1'
                [string] $SchemaName = ($File.BaseName -split '#', 2)[0]

                if ($MetadataModel.Schema.ContainsKey($SchemaName)) {
                    AddToModel -SchemaName $SchemaName -Source $SourceName -Rows (Import-Csv -Path $File.FullName)
                }
                else {
                    $LogString = "{0,-8}|{1,-10}|{2}" -f 'Skipped', 'no schema', $SourceName
                    Write-Verbose $LogString
                }
            }
            elseif ($File.Extension -eq '.xlsx') {

                foreach ($Worksheet in (Get-ExcelSheetInfo -Path $File.FullName)) {

                    $SourceName = "{0,-32}|{1}" -f $Worksheet.Name, $File.FullName
                    # --- schema names never contain a hash; a hash marks a numbered suffix (comment-style), e.g. '_FieldDependencies#1'
                    [string] $SchemaName = ($Worksheet.Name -split '#', 2)[0]
                    if ($MetadataModel.Schema.ContainsKey($SchemaName)) {
                        AddToModel -SchemaName $SchemaName -Source $SourceName -Rows (Import-Excel -Path $File.FullName -WorksheetName $Worksheet.Name)
                    }
                    else {
                        $LogString = "{0,-8}|{1,-10}|{2}" -f 'Skipped', 'no schema', $SourceName
                        Write-Verbose $LogString
                    }
                }
            }
        }
    }

    end {
        return $MetadataModel
    }
}