test-SiLaju / do_inject_controllers.ps1
RyZ
deploy: deploy on HF
d88b81b
#Requires -Version 5.1
<#
.SYNOPSIS
Automatic Dependency Injection Generator for Go Controllers
.DESCRIPTION
Scans ./controllers/ directory, discovers all controller constructors, infers their dependencies,
and generates provider/controller_provider.go with full DI wiring.
.EXAMPLE
.\controller_injector.ps1
.NOTES
- Works with PowerShell 5.1+ and PowerShell 7+
- No external dependencies required
- Supports multi-line constructor signatures
- Controllers depend on services from ServicesProvider
#>
[CmdletBinding()]
param()
# Configuration
$ControllersDir = "./controllers"
$OutputFile = "provider/controller_provider.go"
$ModulePath = "dinacom-11.0-backend/controllers"
# ANSI colors for better output
$script:UseColors = $Host.UI.SupportsVirtualTerminal
function Write-ColorOutput {
param([string]$Message, [string]$Color = "White")
if ($script:UseColors) {
$colors = @{
"Green" = "`e[32m"; "Yellow" = "`e[33m"; "Red" = "`e[31m"
"Cyan" = "`e[36m"; "Blue" = "`e[34m"; "Reset" = "`e[0m"
}
Write-Host "$($colors[$Color])$Message$($colors['Reset'])"
} else {
Write-Host $Message
}
}
# Data structures
class ControllerInfo {
[string]$ConstructorName # NewAccountController
[string]$Domain # AccountController
[string]$VarName # accountController
[System.Collections.Generic.List[Parameter]]$Parameters
ControllerInfo() {
$this.Parameters = [System.Collections.Generic.List[Parameter]]::new()
}
}
class Parameter {
[string]$Name
[string]$RawType
[string]$NormalizedType
}
function Get-LowerCamelCase {
param([string]$Text)
if ($Text.Length -eq 0) { return $Text }
return $Text.Substring(0, 1).ToLower() + $Text.Substring(1)
}
function Normalize-TypeName {
param([string]$TypeStr)
# Remove leading pointer
$cleaned = $TypeStr -replace '^\*+', ''
# Remove package prefix (everything before last dot)
if ($cleaned -match '\.([^.]+)$') {
$cleaned = $matches[1]
}
return $cleaned.Trim()
}
function Parse-GoFiles {
param([string]$Directory)
Write-ColorOutput "Scanning for controller constructors in $Directory..." "Cyan"
if (-not (Test-Path $Directory)) {
Write-ColorOutput "ERROR: Directory '$Directory' not found!" "Red"
exit 1
}
$goFiles = Get-ChildItem -Path $Directory -Filter "*.go" -Recurse -File
$controllers = [System.Collections.Generic.List[ControllerInfo]]::new()
foreach ($file in $goFiles) {
$content = Get-Content $file.FullName -Raw
# Match function signatures (support multi-line)
# Pattern: func NewXxxController(...) XxxController
$pattern = '(?ms)func\s+(New[a-zA-Z0-9]+Controller)\s*\(([^)]*)\)\s+([a-zA-Z0-9*_.]+Controller)'
$matches = [regex]::Matches($content, $pattern)
foreach ($match in $matches) {
$constructorName = $match.Groups[1].Value
$paramsStr = $match.Groups[2].Value
$returnType = $match.Groups[3].Value
# Extract domain name (XxxController)
$domain = Normalize-TypeName $returnType
$varName = Get-LowerCamelCase $domain
$controller = [ControllerInfo]::new()
$controller.ConstructorName = $constructorName
$controller.Domain = $domain
$controller.VarName = $varName
# Parse parameters
if ($paramsStr.Trim() -ne "") {
# Split by comma, but be careful with nested types
$paramList = $paramsStr -split ',\s*(?![^<>]*>)'
foreach ($param in $paramList) {
$param = $param.Trim()
if ($param -eq "") { continue }
# Split into name and type
$parts = $param -split '\s+', 2
$p = [Parameter]::new()
if ($parts.Count -eq 2) {
$p.Name = $parts[0]
$p.RawType = $parts[1]
} elseif ($parts.Count -eq 1) {
# Anonymous parameter - synthesize name
$p.Name = "param$($controller.Parameters.Count)"
$p.RawType = $parts[0]
} else {
continue
}
$p.NormalizedType = Normalize-TypeName $p.RawType
$controller.Parameters.Add($p)
}
}
$controllers.Add($controller)
Write-ColorOutput " Found: $constructorName" "Green"
}
}
if ($controllers.Count -eq 0) {
Write-ColorOutput "No controller constructors found matching pattern 'NewXxxController'!" "Red"
exit 1
}
Write-ColorOutput "`nTotal controllers discovered: $($controllers.Count)" "Blue"
return $controllers
}
function Resolve-ControllerArgument {
param([Parameter]$Param)
$type = $Param.NormalizedType
# DEPENDENCY RESOLUTION RULES
# ============================================
# 1. Service pattern: XxxxService -> servicesProvider.ProvideXxxxService()
if ($type -match '^(.+)Service$') {
$serviceName = $type
return "servicesProvider.Provide${serviceName}()"
}
# ADD MORE SPECIAL CASES HERE:
# --------------------------------------------
# Example: Config dependency
# if ($type -eq "Config") {
# return "configProvider.ProvideConfig()"
# }
#
# Example: Logger
# if ($type -eq "Logger") {
# return "loggerProvider.ProvideLogger()"
# }
#
# Example: Validator
# if ($type -eq "Validator") {
# return "validatorProvider.ProvideValidator()"
# }
# --------------------------------------------
# 2. Fallback: unresolved type
return "/* TODO: provide $($Param.RawType) */"
}
function Generate-ProviderCode {
param([System.Collections.Generic.List[ControllerInfo]]$Controllers)
Write-ColorOutput "`nGenerating controller provider code..." "Cyan"
# Sort controllers alphabetically for consistent output
$sortedControllers = $Controllers | Sort-Object -Property Domain
$sb = [System.Text.StringBuilder]::new()
[void]$sb.AppendLine("package provider")
[void]$sb.AppendLine()
[void]$sb.AppendLine("import `"$ModulePath`"")
[void]$sb.AppendLine()
# Interface
[void]$sb.AppendLine("type ControllerProvider interface {")
foreach ($ctrl in $sortedControllers) {
$line = "`tProvide$($ctrl.Domain)() controllers.$($ctrl.Domain)"
[void]$sb.AppendLine($line)
}
[void]$sb.AppendLine("}")
[void]$sb.AppendLine()
# Struct
[void]$sb.AppendLine("type controllerProvider struct {")
foreach ($ctrl in $sortedControllers) {
$line = "`t$($ctrl.VarName) controllers.$($ctrl.Domain)"
[void]$sb.AppendLine($line)
}
[void]$sb.AppendLine("}")
[void]$sb.AppendLine()
# Constructor
[void]$sb.AppendLine("func NewControllerProvider(servicesProvider ServicesProvider) ControllerProvider {")
[void]$sb.AppendLine()
# Initialize controllers
foreach ($ctrl in $sortedControllers) {
$args = @()
foreach ($param in $ctrl.Parameters) {
$args += Resolve-ControllerArgument $param
}
$argsStr = $args -join ", "
$line = "`t$($ctrl.VarName) := controllers.$($ctrl.ConstructorName)($argsStr)"
[void]$sb.AppendLine($line)
}
[void]$sb.AppendLine("`treturn &controllerProvider{")
foreach ($ctrl in $sortedControllers) {
$line = "`t`t$($ctrl.VarName): $($ctrl.VarName),"
[void]$sb.AppendLine($line)
}
[void]$sb.AppendLine("`t}")
[void]$sb.AppendLine("}")
[void]$sb.AppendLine()
# Getter methods
[void]$sb.AppendLine("// --- Getter Methods ---")
[void]$sb.AppendLine()
foreach ($ctrl in $sortedControllers) {
[void]$sb.AppendLine("func (c *controllerProvider) Provide$($ctrl.Domain)() controllers.$($ctrl.Domain) {")
[void]$sb.AppendLine("`treturn c.$($ctrl.VarName)")
[void]$sb.AppendLine("}")
[void]$sb.AppendLine()
}
return $sb.ToString()
}
function Write-ProviderFile {
param([string]$Code, [string]$OutputPath)
Write-ColorOutput "Writing to $OutputPath..." "Cyan"
# Ensure directory exists
$dir = Split-Path $OutputPath -Parent
if ($dir -and -not (Test-Path $dir)) {
New-Item -ItemType Directory -Path $dir -Force | Out-Null
}
# Write file as UTF-8 without BOM
$utf8NoBom = [System.Text.UTF8Encoding]::new($false)
[System.IO.File]::WriteAllText($OutputPath, $Code, $utf8NoBom)
Write-ColorOutput " Successfully generated $OutputPath" "Green"
}
# ============================================
# MAIN EXECUTION
# ============================================
try {
Write-ColorOutput "`n=========================================" "Blue"
Write-ColorOutput " Go Controller Provider Generator v1.0" "Blue"
Write-ColorOutput "=========================================`n" "Blue"
# Step 1: Parse all controller constructors
$controllers = Parse-GoFiles -Directory $ControllersDir
# Step 2: Generate provider code
$code = Generate-ProviderCode -Controllers $controllers
# Step 3: Write to file
Write-ProviderFile -Code $code -OutputPath $OutputFile
Write-ColorOutput "`nSUCCESS! Controller provider generated successfully.`n" "Green"
Write-ColorOutput "Next steps:" "Cyan"
Write-ColorOutput " 1. Review $OutputFile" "White"
Write-ColorOutput " 2. Fill any /* TODO: provide ... */ placeholders" "White"
Write-ColorOutput " 3. Run: go build ./provider" "White"
} catch {
Write-ColorOutput "`nERROR: $($_.Exception.Message)" "Red"
Write-ColorOutput "Stack trace: $($_.ScriptStackTrace)" "Yellow"
exit 1
}