Private/FileMonitor.ps1
function Start-PodeFileMonitor { # don't configure if not supplied, or we're running as serverless if (!$PodeContext.Server.FileMonitor.Enabled -or $PodeContext.Server.IsServerless) { return } # what folder and filter are we moitoring? $folder = $PodeContext.Server.Root $filter = '*.*' # setup the file monitor $watcher = [System.IO.FileSystemWatcher]::new($folder, $filter) $watcher.IncludeSubdirectories = $true $watcher.NotifyFilter = [System.IO.NotifyFilters]'FileName,LastWrite,CreationTime' $watcher.EnableRaisingEvents = $true # setup the monitor timer - only restart server after changes + 2s of no changes $timer = [System.Timers.Timer]::new() $timer.AutoReset = $false $timer.Interval = 2000 # setup the message data for the events $msgData = @{ Timer = $timer Settings = $PodeContext.Server.FileMonitor } # setup the events script logic $action = { # if there are exclusions, and one matches, return if (($null -ne $Event.MessageData.Settings.Exclude) -and ($Event.SourceEventArgs.Name -imatch $Event.MessageData.Settings.Exclude)) { return } # if there are inclusions, and none match, return if (($null -ne $Event.MessageData.Settings.Include) -and ($Event.SourceEventArgs.Name -inotmatch $Event.MessageData.Settings.Include)) { return } # if enabled, add the file to the list of files that trigggered the restart if ($Event.MessageData.Settings.ShowFiles) { $name = "[$($Event.SourceEventArgs.ChangeType)] $($Event.SourceEventArgs.Name)" if ($Event.MessageData.Settings.Files -inotcontains $name) { $Event.MessageData.Settings.Files += $name } } # restart the timer $Event.MessageData.Timer.Stop() $Event.MessageData.Timer.Start() } # listen out of file created, changed, deleted events Register-ObjectEvent -InputObject $watcher -EventName 'Created' ` -SourceIdentifier (Get-PodeFileMonitorName Create) -Action $action -MessageData $msgData -SupportEvent Register-ObjectEvent -InputObject $watcher -EventName 'Changed' ` -SourceIdentifier (Get-PodeFileMonitorName Update) -Action $action -MessageData $msgData -SupportEvent Register-ObjectEvent -InputObject $watcher -EventName 'Deleted' ` -SourceIdentifier (Get-PodeFileMonitorName Delete) -Action $action -MessageData $msgData -SupportEvent # listen out for timer ticks to reset server Register-ObjectEvent -InputObject $timer -EventName 'Elapsed' -SourceIdentifier (Get-PodeFileMonitorTimerName) -Action { # if enabled, show the files that triggered the restart if ($Event.MessageData.FileSettings.ShowFiles) { if (!$Event.MessageData.Quiet) { # The following files have changed Write-PodeHost $PodeLocale.filesHaveChangedMessage -ForegroundColor Magenta foreach ($file in $Event.MessageData.FileSettings.Files) { Write-PodeHost "> $($file)" -ForegroundColor Magenta } } $Event.MessageData.FileSettings.Files = @() } # trigger the restart $Event.MessageData.Tokens.Restart.Cancel() $Event.Sender.Stop() } -MessageData @{ Tokens = $PodeContext.Tokens FileSettings = $PodeContext.Server.FileMonitor Quiet = $PodeContext.Server.Quiet } -SupportEvent } function Stop-PodeFileMonitor { if ($PodeContext.Server.IsServerless) { return } if ($PodeContext.Server.FileMonitor.Enabled) { Unregister-Event -SourceIdentifier (Get-PodeFileMonitorName Create) -Force Unregister-Event -SourceIdentifier (Get-PodeFileMonitorName Delete) -Force Unregister-Event -SourceIdentifier (Get-PodeFileMonitorName Update) -Force Unregister-Event -SourceIdentifier (Get-PodeFileMonitorTimerName) -Force } } function Get-PodeFileMonitorName { param( [Parameter(Mandatory = $true)] [ValidateSet('Create', 'Delete', 'Update')] [string] $Type ) return "PodeFileMonitor$($Type)" } function Get-PodeFileMonitorTimerName { return 'PodeFileMonitorTimer' } |