diff --git a/packages/nodes-base/nodes/Ftp.node.ts b/packages/nodes-base/nodes/Ftp.node.ts index 49f828f2e..84106640a 100644 --- a/packages/nodes-base/nodes/Ftp.node.ts +++ b/packages/nodes-base/nodes/Ftp.node.ts @@ -220,6 +220,21 @@ export class Ftp implements INodeType { description: 'Path of directory to list contents of.', required: true, }, + { + displayName: 'Recursive', + displayOptions: { + show: { + operation: [ + 'list', + ], + }, + }, + name: 'recursive', + type: 'boolean', + default: false, + description: 'Return object representing all directories / objects recursively found within SFTP server', + required: true, + }, ], }; @@ -234,6 +249,7 @@ export class Ftp implements INodeType { let credentials: ICredentialDataDecryptedObject | undefined = undefined; const protocol = this.getNodeParameter('protocol', 0) as string; + if (protocol === 'sftp') { credentials = this.getCredentials('sftp'); } else { @@ -244,11 +260,11 @@ export class Ftp implements INodeType { throw new Error('Failed to get credentials!'); } - let ftp: ftpClient; - let sftp: sftpClient; + let ftp : ftpClient; + let sftp : sftpClient; + if (protocol === 'sftp') { sftp = new sftpClient(); - await sftp.connect({ host: credentials.host as string, port: credentials.port as number, @@ -258,7 +274,6 @@ export class Ftp implements INodeType { } else { ftp = new ftpClient(); - await ftp.connect({ host: credentials.host as string, port: credentials.port as number, @@ -286,8 +301,15 @@ export class Ftp implements INodeType { const path = this.getNodeParameter('path', i) as string; if (operation === 'list') { - responseData = await sftp!.list(path); - returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + const recursive = this.getNodeParameter('recursive', i) as boolean; + + if (recursive) { + responseData = await callRecursiveList(path, sftp); + returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + } else { + responseData = await sftp!.list(path); + returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + } } if (operation === 'download') { @@ -347,8 +369,15 @@ export class Ftp implements INodeType { const path = this.getNodeParameter('path', i) as string; if (operation === 'list') { - responseData = await ftp!.list(path); - returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + const recursive = this.getNodeParameter('recursive', i) as boolean; + + if (recursive) { + responseData = await callRecursiveList(path, ftp); + returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + } else { + responseData = await ftp!.list(path); + returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + } } if (operation === 'download') { @@ -432,3 +461,37 @@ export class Ftp implements INodeType { return [returnItems]; } } +async function callRecursiveList(path: string, client : sftpClient | ftpClient) { + const pathArray : string[] = [path]; + let currentPath = path; + const directoryItems : sftpClient.FileInfo[] = []; + let index = 0; + + do { + // tslint:disable-next-line: array-type + const returnData : sftpClient.FileInfo[] | (string | ftpClient.ListingElement)[] = await client.list(pathArray[index]); + + // @ts-ignore + returnData.map((item : sftpClient.FileInfo) => { + if ((pathArray[index] as string).endsWith('/')) { + currentPath = `${pathArray[index]}${item.name}`; + } else { + currentPath = `${pathArray[index]}/${item.name}`; + } + + // Is directory + if (item.type === 'd') { + pathArray.push(currentPath); + } + + //@ts-ignore + item.path = currentPath; + directoryItems.push(item); + }); + index++; + + } while (index <= pathArray.length - 1); + + + return directoryItems; +}