Private/BoxTurtleClasses.ps1
<############################################################################ # Store metadata about a Visual Studio solution. # By convention, the solution has a nickname like "MyThing" # and the solution is stored in "MyThingSolution\MyThingSolution.sln" # # $nickName User supplied abbreviation for this whole solution # $solnDir Directory where .sln file lives # $solnFile Fully qualified path to .sln file # $solnName Name of *.sln file without path or .sln suffix ############################################################################> class SolnInfo { [string]$nickName [string]$solnDir [string]$solnFile [string]$solnName [WebCsprojInfo]$webCsprojInfo [ModelCsprojInfo]$modelCsprojInfo [CsprojInfo]$bizCsprojInfo [DbInfo]$dbInfo [string]$rootDir [string]$confFile $tableInfos SolnInfo() { } SolnInfo($nickName, $outputDir) { $this.solnName = "${nickName}Solution" $this.solnDir = $outputDir + "\" + $this.solnName $this.nickName = $nickName $this.solnFile = $this.solnDir + "\" + $this.solnName + ".sln" $this.rootDir = $outputDir $this.confFile = "$($this.rootDir)\boxTurtle.conf.json" $this.tableInfos = $null } [SolnInfo] static Load() { # Get boxturtle.conf.json from this directory tree [bool]$foundIt = $false [SolnInfo]$solnInfo = $null [string]$boxTurtleConfJson = "" [string]$boxTurlteConfJson = "" # Check dir, parent dir, grand-parent, etc. recursively [string]$myDir = (Get-Location) while($myDir.length -gt 3 <# because "c:\" is 3 characters#>) { # Make absolutely sure path ends in slash $myDir = $myDir.TrimEnd('\') + '\' $boxTurtleConfJson = "$($myDir)boxturtle.conf.json" #Write-Host "### Looking up for $boxTurtleConfJson" if(Test-Path $boxTurtleConfJson) { $foundIt = $true break } else { $parent = (Get-Item $myDir).Parent if($parent -eq $null) { break } else { $myDir = [string]($parent.FullName) } } } # Try child directories. If one and only one subdir has it, use that [int]$subdirsWithConf = 0 [string]$latestMatch = "" if($foundIt -eq $false) { $subdirs = get-childitem | where-object {$_.Psiscontainer -eq "True"} | select-object FullName foreach($subdir in $subdirs) { $myDir = $subdir.FullName $myDir = $myDir.TrimEnd('\') + '\' $temp = "$($myDir)boxTurtle.conf.json" #Write-Host "### Looking down for $temp in myDir=$($myDir)###" if(Test-Path $temp) { $subdirsWithConf++ $latestMatch = $temp } } if($subdirsWithConf -eq 1) { $foundIt = $true $boxTurtleConfJson = $latestMatch } } if($foundIt -eq $false) { throw "Unable to find a unique boxturtle.conf.json in current directory '" + (Get-Location) + "' or lower" } else { Write-Host "### Using config $boxTurtleConfJson" [string]$jsonStr = Get-Content -raw $boxTurtleConfJson $solnInfo = [SolnInfo](ConvertFrom-Json $jsonStr) } # Force this to be loaded explicitly when needed $solnInfo.tableInfos = $null return $solnInfo } SaveConf() { # Don't save table metadata, we'll reload each time to get it fresh $this.tableInfos = $null $this | ConvertTo-Json | Out-File $this.confFile } [System.Collections.Hashtable]GetTableInfos() { if($this.tableInfos -eq $null) { $this.tableInfos = New-PsModel $this.dbInfo } return $this.tableInfos } [CsprojInfo]GetProjInfoByName([string]$projName) { if(($this.webCsprojInfo -ne $null) -and ($this.webCsprojInfo.csprojName -eq $projName)) { return $this.webCsprojInfo } elseif(($this.modelCsprojInfo -ne $null) -and ($this.modelCsprojInfo.csprojName -eq $projName)) { return $this.modelCsprojInfo } elseif(($this.bizCsprojInfo -ne $null) -and ($this.bizCsprojInfo.csprojName -eq $projName)) { return $this.bizCsprojInfo } else { throw "cannot find project named '$projName'" } } } <############################################################################ # Store metadata about a Visual Studio project. # By convention, it has a name csprojName like "MyProject" # and the project will be $solnInfo.solnDir\MyProject\MyProject.csproj # # $csprojName Name of project without path or .csproj suffix # $csprojDir Directory where .csproj file lives # $csprojFile Fully qualified path to .csproj file # $namespace Default C# namespace to use for this project ############################################################################> class CsprojInfo { [string]$csprojName [string]$csprojDir [string]$csprojFile [string]$namespace CsprojInfo() { } CsprojInfo([SolnInfo] $solnInfo, [string]$csprojName) { $this.csprojName = $csprojName $this.csprojDir = "{0}\{1}" -f $solnInfo.solnDir, $csprojName $this.csprojFile = "{0}\{1}.csproj" -f $this.csprojDir, $this.csprojName $this.namespace = $csprojName } } <############################################################################ # Subclass of CsprojInfo, but for ASP DotNet Core websites with angular. # # $angularDir Directory where angular is stored, by convention just inside C# web project # $angularModelDir Directory where angular model TypeScripts are stored, by convention "$($webcsprojInfo.csprojDir)\ClientApp\app\model" # $angularServiceDir Directory where angular Service TypeScripts are stored, by convention "$($webcsprojInfo.csprojDir)\ClientApp\app\Service" # $angularComponentDir Directory where angular Component TypeScripts are stored, by convention "$($webcsprojInfo.csprojDir)\ClientApp\app\Component" ############################################################################> class WebCsprojInfo : CsprojInfo { [string]$angularDir [string]$angularAppDir [string]$angularModelDir [string]$angularServiceDir [string]$angularComponentDir [string]$appModuleFile [string]$appRoutingFile [string]$angularStyle [string]$styleCss WebCsprojInfo() { } WebCsprojInfo([SolnInfo] $solnInfo, [string]$csprojName, [string]$angularStyle):base($solnInfo, $csprojName) { $this.angularStyle = $angularStyle if($angularStyle -eq 'ANGULAR_IO') { # It's Angular.io style against MS Web API $this.angularDir = "$($this.csprojDir)\angular" $this.angularAppDir = "$($this.csprojDir)\angular\src\app" $this.appModuleFile = "$($this.angularAppDir)\app.module.ts" $this.appRoutingFile = "$($this.angularAppDir)\app-routing.module.ts" $this.styleCss = "$($this.angularDir)/src/styles.css" } else { # It's microsoft "dotnet new angular" style against MS MVC $this.angularDir = "$($this.csprojDir)" $this.angularAppDir = "$($this.csprojDir)\ClientApp\app" $this.appModuleFile = "$($this.angularAppDir)\app.module.shared.ts" $this.appRoutingFile = "$($this.angularAppDir)\app.module.shared.ts" $this.styleCss = "$($this.angularDir)/src/styles.css" } $this.angularModelDir = "$($this.angularAppDir)\model" $this.angularServiceDir = "$($this.angularAppDir)\service" $this.angularComponentDir = "$($this.angularAppDir)\component" } } <############################################################################ # Subclass of CsprojInfo, but for ASP DotNet Core entity framework projects. # ############################################################################> class ModelCsprojInfo : CsprojInfo { [string]$efContextName [string]$efWithViewContextName [string]$contextName [string]$efNamespace [string]$efWithViewNamespace ModelCsprojInfo() { } ModelCsprojInfo([SolnInfo] $solnInfo, [string]$csprojName):base($solnInfo, $csprojName) { $this.efContextName = "$($solnInfo.nickName)Context" $this.efWithViewContextName = "$($solnInfo.nickName)WithViewContext" $this.contextName = $this.efWithViewContextName $this.efNamespace = "$($this.namespace).Model" $this.efWithViewNamespace = "$($this.namespace).ModelWithView" } } <############################################################################ # Database connection info # # $dbServer Database server name # $db Database name # $connStr C# database connection string ############################################################################> class DbInfo { [string]$dbServer [string]$db [string]$connStr DbInfo() { } DbInfo([SolnInfo]$solnInfo, $dbServer, $db) { $this.dbServer = $dbServer $this.db = $solnInfo.nickName $this.connStr = "Server=${dbServer};Database=${db};Trusted_Connection=True" } } <############################################################################ # Metadata about database column used to generate angular ORM stuff and some C# stuff # # $columnCapitalCamel Column name in capitalized format like "ClientFirstName" # $columnLowerCamel Column name in not-capitalized format like "clientFirstName" # $dataType Column data type in SQL Server syntax # $isNullable True if column is nullable # $maxLength Max char length in database # $caption Column name as a caption "Client First Name" ############################################################################> class ColumnInfo { [string]$columnCapitalCamel [string]$columnLowerCamel [string]$dataType [bool]$isNullable [bool]$isPrimaryKey [int]$maxLength [string]$caption ColumnInfo([string]$column, [string]$dataType, [bool]$isNullable, [int]$maxLength, [bool]$isPrimarykey) { $this.columnCapitalCamel = (ConvertTo-CapitalCamelCase $column) $this.caption = (ConvertTo-TitleCase $column) $this.columnLowerCamel = (ConvertTo-LowerCamelCase $column) $this.dataType = $dataType $this.isNullable = $isNullable $this.maxLength = $maxLength $this.isPrimaryKey = $isPrimaryKey } } <############################################################################ # Metadata about database table used to generate angular ORM stuff and some C# stuff # # $tablePretty Table name like "Customer Account" # $tableCapitalCamel Table name like "CustomerAccount" # $tableLowerCamel Table name like "customerAccount" # $tableLowerKebab Table name like "customer-account" # $columnInfos Array of ColumnInfos describing columns ############################################################################> class TableInfo { [string]$tablePretty [string]$tableCapitalCamel [string]$tableLowerCamel [string]$tableLowerKebab [ColumnInfo[]]$columnInfos [bool]$isView TableInfo([string]$entity, [ColumnInfo[]]$columnInfos, [bool]$isView) { $this.tableCapitalCamel = (ConvertTo-CapitalCamelCase $entity) $this.tableLowerCamel = (ConvertTo-LowerCamelCase $entity) $this.tableLowerKebab = (ConvertTo-KebabCase $entity) $this.tablePretty = (ConvertTo-TitleCase $entity) $this.columnInfos = $columnInfos $this.isView = $isView } } |