PSFaker.psm1
|
# PSFaker.psm1 – root loader $script:PSFakerSeed = $null # $null = random $script:PSFakerRng = $null # System.Random instance $script:UniqueCache = @{} # formatter-name -> [System.Collections.Generic.HashSet[string]] function _Rng { if ($null -eq $script:PSFakerRng) { $script:PSFakerRng = [System.Random]::new() } return $script:PSFakerRng } $providerOrder = @('Base','Lorem','Person','Address','Company','Internet','DateTime','Misc') foreach ($name in $providerOrder) { $p = Join-Path $PSScriptRoot "src\Providers\$name.ps1" if (Test-Path $p) { . $p } } $locales = Get-ChildItem -Path "$PSScriptRoot\src\Locales\*.ps1" -ErrorAction SilentlyContinue foreach ($l in $locales) { . $l.FullName } # ─── Factory ──────────────────────────────────────────────────────────────── function New-Faker { <# .SYNOPSIS Initialise (or re-initialise) the PSFaker generator. .PARAMETER Seed Optional integer seed for reproducible output. .PARAMETER Locale IETF locale tag (default 'en_US'). #> [CmdletBinding()] param( [Parameter()] [Nullable[int]] $Seed = $null, [Parameter()] [string] $Locale = 'en_US' ) # Ensure script variables are initialized if (-not (Test-Path variable:script:PSFakerSeed)) { $script:PSFakerSeed = $null } if (-not (Test-Path variable:script:PSFakerRng)) { $script:PSFakerRng = $null } if (-not (Test-Path variable:script:UniqueCache)) { $script:UniqueCache = @{} } $script:PSFakerSeed = $Seed if ($null -ne $Seed) { $script:PSFakerRng = [System.Random]::new($Seed) } else { $script:PSFakerRng = [System.Random]::new() } $script:UniqueCache = @{} # locale overrides would be dot-sourced here in a full implementation } # ─── Modifier: unique ─────────────────────────────────────────────────────── function Get-FakeUnique { <# .SYNOPSIS Calls a scriptblock and retries until a unique (never-seen) value is returned. .PARAMETER Generator A scriptblock that calls a PSFaker function. .PARAMETER MaxAttempts Safety ceiling (default 10000). #> [CmdletBinding()] param( [Parameter(Mandatory)] [scriptblock] $Generator, [Parameter()] [int] $MaxAttempts = 10000 ) $key = $Generator.ToString().Trim() $uniqueCache = (Get-Variable -Scope 1 -Name 'UniqueCache' -ErrorAction SilentlyContinue).Value if (-not $uniqueCache.ContainsKey($key)) { $uniqueCache[$key] = [System.Collections.Generic.HashSet[string]]::new() } $seen = $uniqueCache[$key] for ($i = 0; $i -lt $MaxAttempts; $i++) { $val = & $Generator $str = [string]$val if ($seen.Add($str)) { return $val } } throw [System.OverflowException]::new("PSFaker: unique() exhausted after $MaxAttempts attempts for: $key") } function Reset-FakeUnique { <#.SYNOPSIS Clear all unique-value caches.#> [CmdletBinding()] param() Set-Variable -Scope 1 -Name 'UniqueCache' -Value @{} } # ─── Modifier: optional ───────────────────────────────────────────────────── function Get-FakeOptional { <# .SYNOPSIS With probability (1-Weight) returns $Default; otherwise calls Generator. .PARAMETER Weight 0.0–1.0, probability of returning real value (default 0.5). .PARAMETER Default Value to return when skipping (default $null). #> [CmdletBinding()] param( [Parameter(Mandatory)] [scriptblock] $Generator, [Parameter()] [double] $Weight = 0.5, [Parameter()] $Default = $null ) if ((_Rng).NextDouble() -lt $Weight) { return & $Generator } return $Default } # ─── Modifier: valid ──────────────────────────────────────────────────────── function Get-FakeValid { <# .SYNOPSIS Calls Generator until Validator returns $true. .PARAMETER Generator Scriptblock generating a value. .PARAMETER Validator Scriptblock accepting a value and returning bool. .PARAMETER MaxAttempts Safety ceiling (default 10000). #> [CmdletBinding()] param( [Parameter(Mandatory)] [scriptblock] $Generator, [Parameter(Mandatory)] [scriptblock] $Validator, [Parameter()] [int] $MaxAttempts = 10000 ) for ($i = 0; $i -lt $MaxAttempts; $i++) { $val = & $Generator if (& $Validator $val) { return $val } } throw [System.OverflowException]::new("PSFaker: valid() exhausted after $MaxAttempts attempts.") } |