Public/FileWatchers.ps1
<#
.SYNOPSIS Adds a new File Watcher to monitor file changes in a directory. .DESCRIPTION Adds a new File Watcher to monitor file changes in a directory. .PARAMETER Name An optional Name for the File Watcher. (Default: GUID) .PARAMETER EventName An optional EventName to be monitored. Note: '*' refers to all event names. (Default: Changed, Created, Deleted, Renamed) .PARAMETER Path The Path to a directory which contains the files to be monitored. .PARAMETER ScriptBlock The ScriptBlock defining logic to be run when events are triggered. .PARAMETER FilePath A literal, or relative, path to a file containing a ScriptBlock for the File Watcher's logic. .PARAMETER ArgumentList A hashtable of arguments to supply to the File Watcher's ScriptBlock. .PARAMETER NotifyFilter The attributes on files to monitor and notify about. (Default: FileName, DirectoryName, LastWrite, CreationTime) .PARAMETER Exclude An optional array of file patterns to be excluded. .PARAMETER Include An optional array of file patterns to be included. (Default: *.*) .PARAMETER InternalBufferSize The InternalBufferSize of the file monitor, used when temporarily storing events. (Default: 8kb) .PARAMETER NoSubdirectories If supplied, the File Watcher will only monitor files in the specified directory path, and not in all sub-directories as well. .PARAMETER PassThru If supplied, the File Watcher object registered will be returned. .EXAMPLE Add-PodeFileWatcher -Path 'C:/Projects/:project/src' -Include '*.ps1' -ScriptBlock {} .EXAMPLE Add-PodeFileWatcher -Path 'C:/Websites/:site' -Include '*.config' -EventName Changed -ScriptBlock {} .EXAMPLE Add-PodeFileWatcher -Path '/temp/logs' -EventName Created -NotifyFilter CreationTime -ScriptBlock {} .EXAMPLE $watcher = Add-PodeFileWatcher -Path '/temp/logs' -Exclude *.txt -ScriptBlock {} -PassThru #> function Add-PodeFileWatcher { [CmdletBinding(DefaultParameterSetName = 'Script')] param( [Parameter()] [string] $Name = $null, [Parameter()] [ValidateSet('Changed', 'Created', 'Deleted', 'Renamed', 'Existed', '*')] [string[]] $EventName = @('Changed', 'Created', 'Deleted', 'Renamed'), [Parameter(Mandatory = $true)] [string] $Path, [Parameter(Mandatory = $true, ParameterSetName = 'Script')] [scriptblock] $ScriptBlock, [Parameter(Mandatory = $true, ParameterSetName = 'File')] [string] $FilePath, [Parameter()] [object[]] $ArgumentList, [Parameter()] [System.IO.NotifyFilters[]] $NotifyFilter = @('FileName', 'DirectoryName', 'LastWrite', 'CreationTime'), [Parameter()] [string[]] $Exclude, [Parameter()] [ValidateNotNullOrEmpty()] [string[]] $Include = '*.*', [Parameter()] [ValidateRange(4kb, 64kb)] [int] $InternalBufferSize = 8kb, [switch] $NoSubdirectories, [switch] $PassThru ) # set random name if ([string]::IsNullOrEmpty($Name)) { $Name = New-PodeGuid -Secure } # set all for * event if ('*' -iin $EventName) { $EventName = @('Changed', 'Created', 'Deleted', 'Renamed', 'Existed') } # resolve path if relative if (!(Test-PodeIsPSCore)) { $Path = Convert-PodePlaceholder -Path $Path -Prepend '%' -Append '%' } $Path = Get-PodeRelativePath -Path $Path -JoinRoot -Resolve if (!(Test-PodeIsPSCore)) { $Path = Convert-PodePlaceholder -Path $Path -Pattern '\%(?<tag>[\w]+)\%' -Prepend ':' -Append ([string]::Empty) } # resolve path, and test it $hasPlaceholders = Test-PodePlaceholder -Path $Path if ($hasPlaceholders) { $rgxPath = Update-PodeRouteSlash -Path $Path -NoLeadingSlash $rgxPath = Resolve-PodePlaceholder -Path $rgxPath -Slashes $Path = $Path -ireplace (Get-PodePlaceholderRegex), '*' } # test path to make sure it exists if (!(Test-PodePath $Path -NoStatus)) { # Path does not exist throw ($PodeLocale.pathNotExistExceptionMessage -f $Path) } # test if we have the file watcher already if (Test-PodeFileWatcher -Name $Name) { # A File Watcher named has already been defined throw ($PodeLocale.fileWatcherAlreadyDefinedExceptionMessage -f $Name) } # if we have a file path supplied, load that path as a scriptblock if ($PSCmdlet.ParameterSetName -ieq 'file') { $ScriptBlock = Convert-PodeFileToScriptBlock -FilePath $FilePath } # check for scoped vars $ScriptBlock, $usingVars = Convert-PodeScopedVariables -ScriptBlock $ScriptBlock -PSSession $PSCmdlet.SessionState # enable the file watcher threads $PodeContext.Fim.Enabled = $true # resolve the path's widacards if any $paths = @($Path) if ($Path.Contains('*')) { $paths = @(Get-ChildItem -Path $Path -Directory -Force | Select-Object -ExpandProperty FullName) } # add the file watcher $PodeContext.Fim.Items[$Name] = @{ Name = $Name Events = @($EventName) Path = $Path Placeholders = @{ Path = $rgxPath Exist = $hasPlaceholders } Script = $ScriptBlock UsingVariables = $usingVars Arguments = $ArgumentList NotifyFilters = @($NotifyFilter) IncludeSubdirectories = !$NoSubdirectories.IsPresent InternalBufferSize = $InternalBufferSize Exclude = $Exclude Include = $Include Paths = $paths } # return? if ($PassThru) { return $PodeContext.Fim.Items[$Name] } } <# .SYNOPSIS Tests whether the passed File Watcher exists. .DESCRIPTION Tests whether the passed File Watcher exists by its name. .PARAMETER Name The Name of the File Watcher. .EXAMPLE if (Test-PodeFileWatcher -Name WatcherName) { } #> function Test-PodeFileWatcher { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string] $Name ) return (($null -ne $PodeContext.Fim.Items) -and $PodeContext.Fim.Items.ContainsKey($Name)) } <# .SYNOPSIS Returns any defined File Watchers. .DESCRIPTION Returns any defined File Watchers. .PARAMETER Name An optional File Watcher Name(s) to be returned. .EXAMPLE Get-PodeFileWatcher .EXAMPLE Get-PodeFileWatcher -Name Name1, Name2 #> function Get-PodeFileWatcher { [CmdletBinding()] param( [Parameter()] [string[]] $Name ) $watchers = $PodeContext.Fim.Items.Values # further filter by file watcher names if (($null -ne $Name) -and ($Name.Length -gt 0)) { $watchers = @(foreach ($_name in $Name) { foreach ($watcher in $watchers) { if ($watcher.Name -ine $_name) { continue } $watcher } }) } # return return $watchers } <# .SYNOPSIS Removes a specific File Watchers. .DESCRIPTION Removes a specific File Watchers. .PARAMETER Name The Name of the File Watcher to be removed. .EXAMPLE Remove-PodeFileWatcher -Name 'Logs' #> function Remove-PodeFileWatcher { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string] $Name ) $null = $PodeContext.Fim.Items.Remove($Name) } <# .SYNOPSIS Removes all File Watchers. .DESCRIPTION Removes all File Watchers. .EXAMPLE Clear-PodeFileWatchers #> function Clear-PodeFileWatchers { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')] [CmdletBinding()] param() $PodeContext.Fim.Items.Clear() } <# .SYNOPSIS Automatically loads File Watchers ps1 files .DESCRIPTION Automatically loads File Watchers ps1 files from either a /filewatcher folder, or a custom folder. Saves space dot-sourcing them all one-by-one. .PARAMETER Path Optional Path to a folder containing ps1 files, can be relative or literal. .EXAMPLE Use-PodeFileWatchers .EXAMPLE Use-PodeFileWatchers -Path './my-watchers' #> function Use-PodeFileWatchers { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')] [CmdletBinding()] param( [Parameter()] [string] $Path ) Use-PodeFolder -Path $Path -DefaultPath 'filewatchers' } |