2021-11-03 08:02:20 -07:00
import { ITriggerFunctions } from 'n8n-core' ;
import {
IDataObject ,
INodeType ,
INodeTypeDescription ,
ITriggerResponse ,
} from 'n8n-workflow' ;
import { watch } from 'chokidar' ;
export class LocalFileTrigger implements INodeType {
description : INodeTypeDescription = {
displayName : 'Local File Trigger' ,
name : 'localFileTrigger' ,
icon : 'fa:folder-open' ,
group : [ 'trigger' ] ,
version : 1 ,
subtitle : '=Path: {{$parameter["path"]}}' ,
description : 'Triggers a workflow on file system changes' ,
:sparkles: Improve Waiting Webhook call state in WF Canvas (#2430)
* N8N-2586 Improve Waiting Webhook call state in WF Canvas
* N8N-2586 Added watcher for showing Webhook's Node Tooltip on execution
* N8N-2586 Show helping tooltip for trigger node if wokrflow is running, it is a trigger node, if it is only one trigger node in WF
* N8N-2586 Rework/Move logic to computed property, Created getter for ActveTriggerNodesInWokrflow, Add style to trigger node's tooltip, remove comments
* N8N-2586 Added EventTriggerDescription prop in INodeTypeDescription Interface, Updated Logic for TriggerNode Tooltip based on the new prop
* N8N-2586 Add new use cases/watcher to show Trigger Nodes Tooltip / If has issues, if paused, if wokrlfow is running, Refactor Getter
* N8N-2586 Added z-index to tooltip, Added new Scenario for Tooltip if it is Draged&Droped on the WF
* N8N-2586 Refactor computed property for draged nodes
* N8N-2586 Fixed Conflicts
* N8N-2586 Fixed Tooltip
* N8N-2586 Dont show tooltip on core trigger nodes that execute automatically
* N8N-2586 Fixed Webhook tooltip when adding/deleting canvas during WF execution
* N8N-2586 Updated Logic, Simplify the code
* N8N-2586 Simplify Code
* N8N-2586 Added check for nodetype
* update dragging to use local state
* N8N-2586 Added eventTriggerDescription to Interval Node
* add comment, use new getter
* update to always check
Co-authored-by: Mutasem <mutdmour@gmail.com>
2021-11-25 14:33:41 -08:00
eventTriggerDescription : '' ,
2021-11-03 08:02:20 -07:00
defaults : {
name : 'Local File Trigger' ,
color : '#404040' ,
} ,
inputs : [ ] ,
outputs : [ 'main' ] ,
properties : [
{
2022-06-03 10:23:49 -07:00
displayName : 'Trigger On' ,
2021-11-03 08:02:20 -07:00
name : 'triggerOn' ,
type : 'options' ,
options : [
{
name : 'Changes to a Specific File' ,
value : 'file' ,
} ,
{
name : 'Changes Involving a Specific Folder' ,
value : 'folder' ,
} ,
] ,
required : true ,
default : '' ,
} ,
{
displayName : 'File to Watch' ,
name : 'path' ,
type : 'string' ,
displayOptions : {
show : {
triggerOn : [
'file' ,
] ,
} ,
} ,
default : '' ,
placeholder : '/data/invoices/1.pdf' ,
} ,
{
displayName : 'Folder to Watch' ,
name : 'path' ,
type : 'string' ,
displayOptions : {
show : {
triggerOn : [
'folder' ,
] ,
} ,
} ,
default : '' ,
placeholder : '/data/invoices' ,
} ,
{
displayName : 'Watch for' ,
name : 'events' ,
type : 'multiOptions' ,
displayOptions : {
show : {
triggerOn : [
'folder' ,
] ,
} ,
} ,
options : [
{
name : 'File Added' ,
value : 'add' ,
description : 'Triggers whenever a new file was added' ,
} ,
{
name : 'File Changed' ,
value : 'change' ,
description : 'Triggers whenever a file was changed' ,
} ,
{
name : 'File Deleted' ,
value : 'unlink' ,
description : 'Triggers whenever a file was deleted' ,
} ,
{
name : 'Folder Added' ,
value : 'addDir' ,
description : 'Triggers whenever a new folder was added' ,
} ,
{
name : 'Folder Deleted' ,
value : 'unlinkDir' ,
description : 'Triggers whenever a folder was deleted' ,
} ,
] ,
required : true ,
default : [ ] ,
description : 'The events to listen to' ,
} ,
{
displayName : 'Options' ,
name : 'options' ,
type : 'collection' ,
placeholder : 'Add Option' ,
default : { } ,
options : [
{
displayName : 'Include Linked Files/Folders' ,
name : 'followSymlinks' ,
type : 'boolean' ,
default : true ,
2022-06-20 07:54:01 -07:00
description : 'Whether linked files/folders will also be watched (this includes symlinks, aliases on MacOS and shortcuts on Windows). Otherwise only the links themselves will be monitored).' ,
2021-11-03 08:02:20 -07:00
} ,
{
displayName : 'Ignore' ,
name : 'ignored' ,
type : 'string' ,
default : '' ,
placeholder : '**/*.txt' ,
description : 'Files or paths to ignore. The whole path is tested, not just the filename. Supports <a href="https://github.com/micromatch/anymatch">Anymatch</a>- syntax.' ,
} ,
2022-04-22 09:29:51 -07:00
// eslint-disable-next-line n8n-nodes-base/node-param-default-missing
2021-11-03 08:02:20 -07:00
{
displayName : 'Max Folder Depth' ,
name : 'depth' ,
type : 'options' ,
options : [
{
2022-06-03 10:23:49 -07:00
name : '1 Levels Down' ,
value : 1 ,
2021-11-03 08:02:20 -07:00
} ,
{
2022-06-03 10:23:49 -07:00
name : '2 Levels Down' ,
value : 2 ,
2021-11-03 08:02:20 -07:00
} ,
{
name : '3 Levels Down' ,
value : 3 ,
} ,
{
2022-06-03 10:23:49 -07:00
name : '4 Levels Down' ,
value : 4 ,
2021-11-03 08:02:20 -07:00
} ,
{
2022-06-03 10:23:49 -07:00
name : '5 Levels Down' ,
value : 5 ,
2021-11-03 08:02:20 -07:00
} ,
{
name : 'Top Folder Only' ,
value : 0 ,
} ,
2022-06-03 10:23:49 -07:00
{
name : 'Unlimited' ,
value : - 1 ,
} ,
2021-11-03 08:02:20 -07:00
] ,
default : - 1 ,
description : 'How deep into the folder structure to watch for changes' ,
} ,
] ,
} ,
] ,
} ;
async trigger ( this : ITriggerFunctions ) : Promise < ITriggerResponse > {
const triggerOn = this . getNodeParameter ( 'triggerOn' ) as string ;
const path = this . getNodeParameter ( 'path' ) as string ;
const options = this . getNodeParameter ( 'options' , { } ) as IDataObject ;
let events : string [ ] ;
if ( triggerOn === 'file' ) {
events = [ 'change' ] ;
} else {
events = this . getNodeParameter ( 'events' , [ ] ) as string [ ] ;
}
const watcher = watch ( path , {
ignored : options.ignored ,
persistent : true ,
ignoreInitial : true ,
followSymlinks : options.followSymlinks === undefined ? true : options . followSymlinks as boolean ,
depth : [ - 1 , undefined ] . includes ( options . depth as number ) ? undefined : options . depth as number ,
} ) ;
const executeTrigger = ( event : string , path : string ) = > {
this . emit ( [ this . helpers . returnJsonArray ( [ { event , path } ] ) ] ) ;
} ;
for ( const eventName of events ) {
watcher . on ( eventName , path = > executeTrigger ( eventName , path ) ) ;
}
function closeFunction() {
return watcher . close ( ) ;
}
return {
closeFunction ,
} ;
}
}