Private/Angular/Model/New-NgModule.ps1

<############################################################################
 # Given a valid Angular folder and a connection string to a database,
 # make a folder ...\src\app\Model, and for each table in the database,
 # make a POTO class where the POTO properties match the column names.
 # Use our custom attribute decorators to designate required fields
 # and max lengths.
 ############################################################################>

Function New-NgModelPrivate([SolnInfo]$solnInfo, [WebCsProjInfo]$webCsprojInfo, $tableInfos)
{
    Write-Host "### Generate angular model for $($webCsprojInfo.csprojName)"
    if(Test-Path $webCsprojInfo.angularModelDir) {
        Remove-Item -Recurse -Force $webCsprojInfo.angularModelDir
    }
    New-Item $webCsprojInfo.angularModelDir -ItemType directory

    $tableInfos.Keys | % { New-NgModelTable $webCsprojInfo $tableInfos[$_] }
}

<############################################################################
 # Given metadata about a table, generate a TypeScript model class
 # including properties for all the fields, and use custom attribute decorators
 # to describe the columns. Save to .../angular/src/app/model folder
 ############################################################################>

Function New-NgModelTable([WebCsprojInfo]$webCsprojInfo, [TableInfo]$tableInfo) 
{
    # Table name should be initial capital
    $tableName = $tableInfo.tableCapitalCamel
    [string]$potoFileName = "$($webCsprojInfo.angularModelDir)\$tableName.ts"

    Write-Host "### Generate angular model for $($tableName) to $potoFileName"
    
    # Generate a TypeScript POTO file that represents this table

    # These are the custom decorates we use
    [string]$result = "import { Required, DisplayName, MinLength, MaxLength, PrimaryKey, PreserveMe } from 'box-turtle-ng';`n`n"

    # Make one class per table
    $result = $result + "export class $tableName {`n"

    # Loop through all fields
    foreach ($columnInfo in $tableInfo.ColumnInfos)
    { 
        [string]$thisLine = New-NgModelColumn $tableName $columnInfo
        $result = $result + $thisline;
    }
    $result = $result + "}"

    # Save output to desired folder
    $result | Out-FileUtf8NoBom $potoFileName
}

<############################################################################
 ############################################################################>

Function New-NgModelColumn([string] $tableName, [ColumnInfo]$columnInfo)
{
    [string]$result = "";

    if($columnInfo.isPrimaryKey) {
        # Special case, don't mark primary key as required
        # since it's autofilled.
        $result += "`t@PrimaryKey()`n"
    } else {
        # Mark non-nullable fields as required
        if($columnInfo.isNullable -eq $false) {
            $result += "`t@Required()`n"
        }
    }

    $jsType = "any";
    if(($columnInfo.dataType -eq "CHAR") -or ($columnInfo.dataType -eq "VARCHAR") -or ($columnInfo.dataType -eq "NCHAR") -or ($columnInfo.dataType -eq "NVARCHAR")) {
        $jsType = "string";

        if($columnInfo.maxLength -gt 0) {
            $result += "`t@MaxLength(" + $columnInfo.maxLength + ")`n"
        }
    } elseif($columnInfo.dataType -eq "int") {
        $jsType = "number";
    } elseif($columnInfo.dataType -eq "datetime") {
        $jsType = "Date";
    } elseif($columnInfo.dataType -eq "bit") {
        $jsType = "boolean";
    }

    if($result -eq "") {
        # No decorators so far, add the defaut one so we can track metadata reliably
        $result += "`t@PreserveMe()`n"
    }

    $result = $result + "`t" + $columnInfo.columnLowerCamel + ": " + $jsType + ";`n`n"
    return $result
}