Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

oro-sftp

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

oro-sftp - npm Package Compare versions

Comparing version 1.0.1 to 1.1.0

babel.config.js

13

CHANGELOG.md

@@ -0,1 +1,14 @@

## 1.1.0 / 2023-07-04
* Added `TS` support.
* Added _ts tests_.
* Added `package-lock.json`.
* Improved _tests_.
* Improved _readme_.
* Improved _error messages_ and added param `code` in _responseKO error_.
* Fixed reducing duration of _connection timeout_ when fails.
* Fixed method `delete` allowing to remove folder (as `rmdir`) when it's empty.
* Updated lib `oro-functions` to `v1.3.2`.
* Updated lib `ssh2-sftp-client` to `v9.1.0`.
* Updated lib-dev `jest` to `v29.5.0`.
## 1.0.3 / 2022-06-21

@@ -2,0 +15,0 @@ * Updated lib `oro-functions` to `v1.1.7`.

280

index.js

@@ -6,7 +6,25 @@ const path = require( 'path' );

class OroSftp {
function getMsgAndCodeByErr( err ) {
let msg = err.toString().split( '\r\n' )[ 0 ].replace( 'Error: ', '' );
let code = err.code;
#ftpClient
#ftpConfig
if( msg.includes( 'No SFTP connection available' ) ) {
msg = `FtpConnectionError: connection status is not yet connected`;
code = 'UNCONNECTED';
}
switch( true ) {
case code === 2: code = 'ENOTFOUND'; break;
case code === 4: code = 'ENOTEMPTY'; break;
}
return { msg, code };
}
class OSFtp {
#ftpClient;
#config;
constructor( config = {} ) {

@@ -21,11 +39,12 @@ ! Ofn.objIsEmpty( config ) && this.#setFtpConfig( config );

#setFtpConfig( config ) {
this.#ftpConfig = Ofn.cloneObject( config );
this.#config = Ofn.cloneObject( config );
if( this.#ftpConfig.user ) {
this.#ftpConfig.username = this.#ftpConfig.user;
delete this.#ftpConfig.user;
if( this.#config.user ) {
this.#config.username = this.#config.user;
delete this.#config.user;
}
this.#ftpConfig.readyTimeout === undefined && ( this.#ftpConfig.readyTimeout = 3000 );
this.#ftpConfig.disconnectWhenError === undefined && ( this.#ftpConfig.disconnectWhenError = true );
this.#config.readyTimeout === undefined && ( this.#config.readyTimeout = 3000 );
this.#config.retry_minTimeout === undefined && ( this.#config.retry_minTimeout = this.#config.readyTimeout );
this.#config.disconnectWhenError === undefined && ( this.#config.disconnectWhenError = true );
}

@@ -36,15 +55,22 @@

if( Ofn.objIsEmpty( this.#ftpConfig ) ) {
return Ofn.setResponseKO( `SFTP Connect failed: ftpConfig is empty.` );
if( Ofn.objIsEmpty( this.#config ) ) {
return Ofn.setResponseKO(
`SFTP Connect failed: config is empty.`,
{ code: 'UNCONNECTED', config: {} }
);
}
return await this.#ftpClient.connect( this.#ftpConfig )
return await this.#ftpClient.connect( this.#config )
.then( data => Ofn.setResponseOK() )
.catch( err => {
let cloneConfig = Ofn.cloneObject( this.#ftpConfig );
cloneConfig.password && (cloneConfig.password = new Array( cloneConfig.password.length ).fill( '*' ).join( '' ));
let errArray = err.toString().split( '\r\n' );
let tryAgain = errArray[ 0 ] !== 'Error: Invalid username';
return Ofn.setResponseKO( `SFTP Connect failed: ${errArray[ 0 ]}.`,
{ ftpConfig: cloneConfig, ftpError: errArray }, tryAgain )
const config = Ofn.cloneObject( this.#config );
if( config.password ) {
config.password = new Array( config.password.length ).fill( '*' ).join( '' );
}
const { msg } = getMsgAndCodeByErr( err );
const code = msg.includes( 'Timed out while waiting for handshake' ) ? 'ENTIMEOUT' : err.code +'';
const tryAgain = msg !== 'Invalid username';
return Ofn.setResponseKO( `SFTP Connect failed: ${msg.replace( 'connect: ', '' )}.`,
{ config, code }, tryAgain )
} );

@@ -58,4 +84,7 @@ }

if( ! await fsExtra.exists( filepathFrom ) ) {
this.#ftpConfig.disconnectWhenError && ( await this.disconnect() );
return Ofn.setResponseKO( `SFTP Upload failed: File to upload not exist.`, { filepathFrom } );
this.#config.disconnectWhenError && ( await this.disconnect() );
return Ofn.setResponseKO(
`SFTP Upload failed: File (From) to upload not exist.`,
{ filepathFrom, filepathTo, code: 'ENOTFOUND' }
);
}

@@ -65,8 +94,14 @@

.then( data => {
return Ofn.setResponseOK( { filename: Ofn.getFilenameByPath( filepathTo ), filepath: filepathTo } );
return Ofn.setResponseOK( {
filename: Ofn.getFilenameByPath( filepathTo ),
filepath: filepathTo
} );
} )
.catch( err => {
this.#ftpConfig.disconnectWhenError && ( this.disconnect() );
let errArray = err.toString().split( '\r\n' );
return Ofn.setResponseKO( `SFTP Upload failed: ${errArray[0]}.`, { ftp: errArray } );
this.#config.disconnectWhenError && ( this.disconnect() );
const { msg, code } = getMsgAndCodeByErr( err );
return Ofn.setResponseKO(
`SFTP Upload failed: ${msg.replace( '_put: ', '' ).replace( 'Write stream error: ', '' )}.`,
{ filepathFrom, filepathTo, code }
);
} );

@@ -80,4 +115,7 @@ }

if( ! await fsExtra.exists( Ofn.getFolderByPath( filepathTo ) ) ) {
this.#ftpConfig.disconnectWhenError && ( await this.disconnect() );
return Ofn.setResponseKO( `SFTP Download failed: Folder to download not exist.`, { filepathFrom, filepath: filepathTo } );
this.#config.disconnectWhenError && ( await this.disconnect() );
return Ofn.setResponseKO(
`SFTP Download failed: Folder (From) to download not exist.`,
{ filepathFrom, filepathTo, code: 'ENOTFOUND' }
);
}

@@ -87,8 +125,14 @@

.then( data => {
return Ofn.setResponseOK( { filename: Ofn.getFilenameByPath( filepathTo ), filepath: Ofn.sanitizePath( filepathTo ) } );
return Ofn.setResponseOK( {
filename: Ofn.getFilenameByPath( filepathTo ),
filepath: Ofn.sanitizePath( filepathTo )
} );
} )
.catch( err => {
this.#ftpConfig.disconnectWhenError && ( this.disconnect() );
let errArray = err.toString().split( '\r\n' );
return Ofn.setResponseKO( `SFTP Download failed: ${errArray[0]}.`, { ftp: errArray } )
this.#config.disconnectWhenError && ( this.disconnect() );
const { msg, code } = getMsgAndCodeByErr( err );
return Ofn.setResponseKO(
`SFTP Download failed: ${msg.replace( 'get: ', '' )}.`,
{ filepathFrom, filepathTo, code }
)
} );

@@ -102,9 +146,9 @@ }

folder[ 0 ] === '/' && ( folder = `.${folder}` );
folder && folder.substr( folder.length - 1 ) !== '/' && ( folder += '/' );
folder && folder.slice( folder.length - 1 ) !== '/' && ( folder += '/' );
let folderPath = folder.indexOf( './' ) === 0 ? folder.substr( 2 ) : folder;
const folderPath = folder.indexOf( './' ) === 0 ? folder.slice( 2 ) : folder;
return await this.#ftpClient.list( folder, filters.pattern )
.then( data => {
let files = [];
const files = [];
for( const elem of data ) {

@@ -115,2 +159,10 @@ elem.date = new Date( elem.modifyTime );

elem.modifyDate = elem.modifyTime && new Date(elem.modifyTime);
delete elem.modifyTime;
elem.accessDate = elem.accessTime && new Date(elem.accessTime);
delete elem.modifyTime;
elem.owner = (elem.owner || '')+'';
elem.group = (elem.group || '')+'';
elem.path = `${folderPath}${elem.name}`;

@@ -123,5 +175,5 @@

.catch( err => {
this.#ftpConfig.disconnectWhenError && ( this.disconnect() );
let errArray = err.toString().split( '\r\n' );
return Ofn.setResponseKO( `SFTP List failed: ${errArray[0]}.`, { ftp: errArray } );
this.#config.disconnectWhenError && ( this.disconnect() );
const { msg, code } = getMsgAndCodeByErr( err );
return Ofn.setResponseKO( `SFTP List failed: ${msg}.`, { folder, filters, code } );
} );

@@ -133,10 +185,14 @@ }

.then( data => {
return Ofn.setResponseOK(
{ filepathFrom, filepath: filepathTo, filename: Ofn.getFilenameByPath( filepathTo ) } );
return Ofn.setResponseOK( {
filename: Ofn.getFilenameByPath( filepathTo ),
filepath: filepathTo
} );
} )
.catch( err => {
this.#ftpConfig.disconnectWhenError && ( this.disconnect() );
let errArray = err.toString().split( '\r\n' );
return Ofn.setResponseKO( `SFTP Move failed: ${errArray[0]}.`,
{ filepathFrom, filepath: filepathTo, ftp: errArray } );
this.#config.disconnectWhenError && ( this.disconnect() );
const { msg, code } = getMsgAndCodeByErr( err );
return Ofn.setResponseKO(
`SFTP Move failed: ${msg.replace( '_rename: ', '' )}.`,
{ filepathFrom, filepathTo, code }
);
} );

@@ -148,14 +204,44 @@ }

.then( data => {
return Ofn.setResponseOK( 'deleted successfully',
{ filepath: filepathFrom, filename: Ofn.getFilenameByPath( filepathFrom ) } );
return Ofn.setResponseOK( 'deleted successfully', {
filepath: filepathFrom,
filename: Ofn.getFilenameByPath( filepathFrom )
} );
} )
.catch( err => {
let errArray = err.toString().split( '\r\n' );
if( ! strict && errArray[ 0 ].match( /(Error: delete: No such file)/ ) ) {
return Ofn.setResponseOK( `file not found`,
{ filepath: filepathFrom, filename: Ofn.getFilenameByPath( filepathFrom ) } );
.catch( async (err) => {
let { msg, code } = getMsgAndCodeByErr( err );
if( ! strict && msg.match( /(delete: No such file)|(delete: Failure)/ ) ) {
const exists = await this.exists( filepathFrom );
if( ! exists.status || exists.type !== 'd') {
return Ofn.setResponseOK( `file not found`, {
filepath: filepathFrom,
filename: Ofn.getFilenameByPath( filepathFrom )
} );
}
const rmdir = await this.rmdir( filepathFrom, false, true );
return rmdir.status
? Ofn.setResponseOK( rmdir.msg,
{
filepath: rmdir.folderpath,
filename: rmdir.foldername
} )
: Ofn.setResponseKO( rmdir.error.msg.replace( 'Rmdir', 'Delete' ),
{
filepathFrom: rmdir.error.folder,
code: rmdir.error.code
} );
}
this.#ftpConfig.disconnectWhenError && ( this.disconnect() );
return Ofn.setResponseKO( `SFTP Delete failed: ${errArray[0]}.`,
{ filepath: filepathFrom, ftp: errArray } )
this.#config.disconnectWhenError && ( this.disconnect() );
if( msg === "TypeCannot read properties of undefined (reading 'unlink')" ) {
msg = `FtpConnectionError: connection status is not yet connected`;
code = 'UNCONNECTED';
}
return Ofn.setResponseKO(
`SFTP Delete failed: ${msg.replace('delete: ', '')}.`,
{ filepathFrom, code }
)
} );

@@ -167,4 +253,6 @@ }

.then( data => {
let response = Ofn.setResponseOK(
{ filepath: filepathFrom, filename: Ofn.getFilenameByPath( filepathFrom ) } );
const response = Ofn.setResponseOK( {
filepath: filepathFrom,
filename: Ofn.getFilenameByPath( filepathFrom )
} );

@@ -176,6 +264,12 @@ data && ( response.type = data );

.catch( err => {
this.#ftpConfig.disconnectWhenError && ( this.disconnect() );
let errArray = err.toString().split( '\r\n' );
this.#config.disconnectWhenError && ( this.disconnect() );
const { msg, code } = getMsgAndCodeByErr( err );
return Ofn.setResponseKO(
`SFTP Exists failed: ${errArray[0]}.`, { filepath: filepathFrom, ftp: errArray } );
`SFTP Exists failed: ${msg}.`,
{
filepath: filepathFrom,
filename: Ofn.getFilenameByPath( filepathFrom ),
code
}
);
} );

@@ -186,3 +280,3 @@ }

if( ! folder ) {
this.#ftpConfig.disconnectWhenError && ( this.disconnect() );
this.#config.disconnectWhenError && ( this.disconnect() );
return Ofn.setResponseKO( `SFTP Mkdir failed: param folder is required.` );

@@ -192,10 +286,12 @@ }

folder[ 0 ] === '/' && ( folder = `.${folder}` );
let folderpath = folder.indexOf( './' ) === 0 ? folder.substr( 2 ) : folder;
const folderpath = folder.indexOf( './' ) === 0 ? folder.slice( 2 ) : folder;
let exists = await this.exists( folder );
const exists = await this.exists( folder );
if( exists.status && exists.type === 'd' ) {
if( strict ) {
this.#ftpConfig.disconnectWhenError && ( this.disconnect() );
return Ofn.setResponseKO( `SFTP Mkdir failed: Folder already exists.`,
{ folderpath, foldername: Ofn.getFilenameByPath( folder ), } );
this.#config.disconnectWhenError && ( this.disconnect() );
return Ofn.setResponseKO(
`SFTP Mkdir failed: Folder already exists.`,
{ folderpath, foldername: Ofn.getFilenameByPath( folder ) }
);
}

@@ -210,5 +306,15 @@

.catch( err => {
this.#ftpConfig.disconnectWhenError && ( this.disconnect() );
let errArray = err.toString().split( '\r\n' );
return Ofn.setResponseKO( `SFTP Mkdir failed: ${errArray[0]}.`, { folder, ftp: errArray } );
this.#config.disconnectWhenError && ( this.disconnect() );
let { msg, code } = getMsgAndCodeByErr( err );
if( code === 'ERR_BAD_PATH' ) {
code = 'ENOTFOUND';
}
msg = msg.replace('mkdir: ', '').replace('_doMkdir: ', '')
return Ofn.setResponseKO(
`SFTP Mkdir failed: ${msg}.`,
{ folder, code }
);
} );

@@ -219,3 +325,3 @@ }

if( ! folder ) {
this.#ftpConfig.disconnectWhenError && ( this.disconnect() );
this.#config.disconnectWhenError && ( this.disconnect() );
return Ofn.setResponseKO( `SFTP Rmdir failed: param folder is required.` );

@@ -225,13 +331,27 @@ }

folder[ 0 ] === '/' && ( folder = `.${folder}` );
let folderpath = folder.indexOf( './' ) === 0 ? folder.substr( 2 ) : folder;
const folderpath = folder.indexOf( './' ) === 0 ? folder.slice( 2 ) : folder;
return await this.#ftpClient.rmdir( folder, recursive )
.then( () => Ofn.setResponseOK( { folderpath, foldername: Ofn.getFilenameByPath( folder ) } ) )
.then( () => Ofn.setResponseOK( {
folderpath, foldername:
Ofn.getFilenameByPath( folder )
} ) )
.catch( err => {
let errArray = err.toString().split( '\r\n' );
if( ! strict && errArray[ 0 ].match( /(Error: rmdir: Bad path:)/ ) ) {
return Ofn.setResponseOK( `Folder not found.`, { folderpath, foldername: Ofn.getFilenameByPath( folder ) } )
let { msg, code } = getMsgAndCodeByErr( err );
if( ! strict && msg.match( /(Bad Path:)/ ) ) {
return Ofn.setResponseOK( `Folder not found.`, {
folderpath,
foldername: Ofn.getFilenameByPath( folder )
} )
}
this.#ftpConfig.disconnectWhenError && ( this.disconnect() );
return Ofn.setResponseKO( `SFTP Rmdir failed: ${errArray[0]}.`, { folder, ftp: errArray } );
this.#config.disconnectWhenError && ( this.disconnect() );
if( code === 'ERR_BAD_PATH' ) {
code = 'ENOTFOUND';
}
return Ofn.setResponseKO(
`SFTP Rmdir failed: ${msg.replace('rmdir: ', '')}.`,
{ folder, code }
);
} );

@@ -244,4 +364,8 @@ }

.catch( err => {
let errArray = err.toString().split( '\r\n' );
return Ofn.setResponseKO( `SFTP Disconnect failed: ${errArray[0]}.`, { ftp: errArray } )
const { msg } = getMsgAndCodeByErr( err );
return Ofn.setResponseKO(
`SFTP Disconnect failed: ${msg}.`,
undefined,
true
)
} );

@@ -257,3 +381,3 @@ }

this.disconnect();
await this.disconnect();

@@ -264,2 +388,2 @@ return sftpUpload;

module.exports = OroSftp;
module.exports = OSFtp;
{
"name": "oro-sftp",
"version": "1.0.1",
"version": "1.1.0",
"description": "Class OroSftp is a wrapper of ssh2-sftp-client to work as promises async/await.",

@@ -26,8 +26,14 @@ "main": "index.js",

"dependencies": {
"oro-functions": "^1.1.7",
"ssh2-sftp-client": "^8.1.0"
"@types/ssh2-sftp-client": "^9.0.0",
"oro-functions": "^1.3.2",
"ssh2-sftp-client": "^9.1.0"
},
"devDependencies": {
"jest": "^28.1.1"
"@babel/core": "^7.22.5",
"@babel/preset-env": "^7.22.5",
"@babel/preset-typescript": "^7.22.5",
"@types/jest": "^29.5.2",
"babel-jest": "^29.5.0",
"jest": "^29.5.0"
}
}
}

@@ -7,2 +7,4 @@ # Oro Sftp

If you need the same wrapper using FTP, then use [OroFtp](https://www.npmjs.com/package/oro-ftp)
```shell

@@ -17,2 +19,5 @@ npm install oro-sftp

// ts
import OSFtp from 'oro-sftp';
const sftpClient = new OSftp( {

@@ -26,4 +31,5 @@ host: 'custom-server.com',

const sftpUpload = await sftpClient.uploadOne( `./folder-from/filename`, 'folder-to/filename' );
console.log( sftpUpload );
// { status: true, ... }
// -> { status: true, ... }
```

@@ -33,23 +39,62 @@

* [new OSFtp()](#new-osftp-config---)
* [Error Code List](#error-code-list)
* [new OSFtp()](#new-osftp)
* [.getClient()](#getclient)
* [await .connect( config = {} )](#await-connect-config---)
* [await .connect()](#await-connect)
* [await .disconnect()](#await-disconnect)
* [await .upload( filepathFrom, filepathTo = '' )](#await-upload-filepathfrom-filepathto---)
* [await .uploadOne( filepathFrom, filepathTo = '' )](#await-uploadone-filepathfrom-filepathto---)
* [await .download( filepathFrom, filepathTo = '' )](#await-download-filepathfrom-filepathto---)
* [await .list( folder = '', filters = {} )](#await-list-folder---filters---)
* [await .move( filepathFrom, filepathTo )](#await-move-filepathfrom-filepathto-)
* [await .delete( filepathFrom, strict = false )](#await-delete-filepathfrom-strict--false-)
* [await .exists( filepathFrom, disconnectWhenError = undefined )](#await-exists-filepathfrom-)
* [await .mkdir( folder, recursive = true, strict = false )](#await-mkdir-folder-recursive--true-strict--false-)
* [await .rmdir( folder, strict = false )](#await-rmdir-folder-recursive--false-strict--false-)
* [await .upload()](#await-upload)
* [await .uploadOne()](#await-uploadone)
* [await .download()](#await-download)
* [await .list()](#await-list)
* [await .move()](#await-move)
* [await .delete()](#await-delete)
* [await .exists()](#await-exists)
* [await .mkdir()](#await-mkdir)
* [await .rmdir()](#await-rmdir)
* [Testing](#testing)
### Error Code List
### new OSftp( config = {} )
When an error happens, instead to throw an error, it's returned a managed _responseKO_.
On the construct, you can pass the server config data. You can also do it in `.connect()`.
_responseKO_ is an object with 3 fields:
In addition, `config` has a new param `disconnectWhenError` default `true`, so when an error happens the connection close automatically.
````ts
interface responseKO {
status: false;
error: {
msg: string; // explaining the error
code: OSFtpErrorCode; // string
// ... // other data, it depends on method error
},
tryAgain: boolean;
}
type OSFtpErrorCode =
| 'UNCONNECTED'
| 'ENOTFOUND'
| 'ENTIMEOUT'
| 'ENOENT'
| 'EEXIST'
| 'ENOTEMPTY';
````
### new OSftp()
```ts
new OSFtp( config?: OSFtpConfig );
type OSFtpConfig = SftpClient.ConnectOptions & {
host?: string;
port?: number;
user?: string;
password?: string;
readyTimeout?: number; // def: 3000
disconnectWhenError?: boolean; // def: true
}
```
As parameters, you can pass the server config data (or you can also do it in `.connect()`).
In addition, `config` has param `disconnectWhenError` (default `true`), so when an error happens, connection closes automatically.
```js

@@ -63,3 +108,2 @@ const OSftp = require( 'oro-sftp' );

readyTimeout: 3000,
disconnectWhenError: true

@@ -69,8 +113,10 @@ }

const sftpClient = new OSftp( config );
```
### .getClient()
```ts
sftpClient.getClient(): SftpClient;
```
If you want to use the library ssh2-sftp-client, you can get the object.
If you want to use the library `ssh2-sftp-client`, you can get the object.

@@ -83,7 +129,43 @@ ```js

### await .connect( config = {} )
### await .connect()
```ts
await sftpClient.connect( config?: OSFtpConfig ) => Promise<OSFtpConnectResponse>;
type OSFtpConfig = PromiseFtp.Options & {
host?: string;
port?: number;
user?: string;
password?: string;
readyTimeout?: number; // def: 3000
disconnectWhenError?: boolean; // def: true
}
export type OSFtpConnectResponse = SResponse<
SResponseOK,
OSFtpConnectError // as SResponseKO
>;
interface SResponseOK {
status: true;
}
interface SResponseKO {
status: false;
error: {
msg: string;
code: OSFtpErrorCode;
config: OSFtpConfig;
}
}
interface OSFtpConnectError {
msg: string;
code: OSFtpErrorCode;
config: OSFtpConfig;
}
```
When you create a connection, it's expected that you will disconnect it later.
The action return a response, which is an object with `status: true` or `status: false`.
This method return a _response_, which is an object with `status: true | false`.

@@ -95,8 +177,30 @@ ```js

console.log( connected );
// -> { status: true }
```
### await .disconnect()
```ts
await sftpClient.disconnect() => Promise<OSFtpDisconnectResponse>;
Note: It's not necessary to use `await` in `.disconnect()`.
export type OSFtpDisconnectResponse = SResponse<
SResponseOK,
SResponseKO
>;
interface SResponseOK {
status: true;
}
interface SResponseKO {
status: false;
}
```
**Note**: If you don't `.disconnect()` when finished, the script still running.
**Note2**: There is a param in _config_ `disconnectWhenError` by default `true`.
This means that if a method (like `upload` or `move`) return `status: false`, the _ftpClient_ will be disconnected automatically.
This method return a _response_, which is an object with `status: true | false`.
```js

@@ -111,9 +215,49 @@ const sftpClient = new OSftp( config );

console.log( disconnected );
// -> { status: true }
```
### await .upload( filepathFrom, filepathTo = '' )
### await .upload()
```ts
await sftpClient.upload( filepathFrom: string, filepathTo?: string )
=> Promise<OSFtpFileResponse>;
If `filepathTo` is not declared, it takes the filename of `filepathFrom` and save it on the main folder.
export type OSFtpFileResponse = SResponse<
OSFtpFileObject, // as SResponseOK
OSFtpFileError // as SResponseKO
>;
interface SResponseOK {
status: true;
filename: string;
filepath: string;
}
interface SResponseKO {
status: false;
error: {
msg: string;
filepathFrom: string;
filepathTo?: string;
code?: OSFtpErrorCode;
}
}
interface OSFtpFileObject {
filename: string;
filepath: string;
}
interface OSFtpFileError {
msg: string;
filepathFrom: string;
filepathTo?: string;
code?: OSFtpErrorCode;
}
```
`upload` is the action to copy from _local_ to _ftp folder_.
If `filepathTo` is not declared, it takes the filename of `filepathFrom` and save it on _ftp_ main folder.
```js

@@ -127,2 +271,3 @@ const sftpClient = new OSftp( config );

console.log( uploaded );
// -> { status: true, filename: 'custom-file.pdf', ... }

@@ -132,9 +277,115 @@ sftpClient.disconnect();

### await .download( filepathFrom, filepathTo = '' )
### await .uploadOne()
```ts
await sftpClient.upload( filepathFrom: string, filepathTo?: string )
=> Promise<OSFtpUploadOneResponse>;
If `filepathTo` is not declared, it takes the filename of `filepathFrom` and save it on the main folder.
export type OSFtpUploadOneResponse = SResponse<
OSFtpFileObject, // as SResponseOK
OSFtpFileError | OSFtpConnectError // as SResponseKO
>;
interface SResponseOK {
status: true;
filename: string;
filepath: string;
}
type SResponseKO =
| {
status: false;
error: {
msg: string;
filepathFrom: string;
filepathTo?: string;
code?: OSFtpErrorCode;
}
}
| {
status: false;
error: {
msg: string;
code: OSFtpErrorCode;
config: OSFtpConfig;
}
}
interface OSFtpFileObject {
filename: string;
filepath: string;
}
interface OSFtpFileError {
msg: string;
filepathFrom: string;
filepathTo?: string;
code?: OSFtpErrorCode;
}
interface OSFtpConnectError {
msg: string;
code: OSFtpErrorCode;
config: OSFtpConfig;
}
```
If you want to upload just one file, you can use this method and inside:
1. it's connected,
2. file is uploaded,
3. it's disconnected.
```js
const sftpClient = new OSftp( config );
const uploaded = await sftpClient.uploadOne( './files/custom-file.pdf' );
console.log( uploaded );
// -> { status: true, filename: 'custom-file.pdf', ... }
```
### await .download()
```ts
await sftpClient.download( filepathFrom: string, filepathTo?: string )
=> Promise<OSFtpFileResponse>;
export type OSFtpFileResponse = SResponse<
OSFtpFileObject, // as SResponseOK
OSFtpFileError // as SResponseKO
>;
interface SResponseOK {
status: true;
filename: string;
filepath: string;
}
interface SResponseKO {
status: false;
error: {
msg: string;
filepathFrom: string;
filepathTo?: string;
code?: OSFtpErrorCode;
}
}
interface OSFtpFileObject {
filename: string;
filepath: string;
}
interface OSFtpFileError {
msg: string;
filepathFrom: string;
filepathTo?: string;
code?: OSFtpErrorCode;
}
```
`download` is the action to copy from _ftp folder_ to _local_.
If `filepathTo` is not declared, it takes the filename of `filepathFrom` and save it on _local_ main folder.
```js
const sftpClient = new OSftp( config );
const connected = await sftpClient.connect();

@@ -145,2 +396,3 @@ if( ! connected.status ) { return connected; }

console.log( downloaded );
// -> { status: true, filename: 'custom-file.pdf', ... }

@@ -150,44 +402,107 @@ sftpClient.disconnect();

### await .uploadOne( filepathFrom, filepathTo = '' )
### await .list()
```ts
await sftpClient.list( folder?: string, filters?: OSFtpListFilters )
=> Promise<OSFtpListResponse>;
If you want to upload just one file, you can use sftpClient method and inside it creates the connection/disconnection flow.
interface OSFtpListFilters {
onlyFiles?: boolean | undefined; // def: false
onlyFolders?: boolean | undefined; // def: false
pattern?: string | RegExp | undefined;
}
export type OSFtpListResponse = SResponse<
OSFtpListObject, // as SResponseOK
OSFtpListError // as SResponseKO
>;
interface SResponseOK {
status: true;
count: number; // list.length
list: OSFtpListFile[];
}
interface SResponseKO {
status: false;
error: {
msg: string;
folder: string;
filters: OSFtpListFilters;
code?: OSFtpErrorCode;
}
}
export interface OSFtpListFile {
path: string;
name: string;
type: OSFtpListFileType;
date: Date;
size: number;
owner: string;
group: string;
target: string | undefined;
rights: {
user: string;
group: string;
other: string;
}
}
type OSFtpListFileType = '-' | 'd' | 'l';
// 'file' | 'folder' | 'symlink'
export interface OSFtpListObject {
count: number; // list.length
list: OSFtpListFile[];
}
export interface OSFtpListError {
msg: string;
folder: string;
filters: OSFtpListFilters;
code?: OSFtpErrorCode;
}
```
`list` is the action to take a look at what is in _ftp folder_.
```js
const sftpClient = new OSftp( config );
const uploaded = await sftpClient.uploadOne( './files/custom-file.pdf' );
console.log( uploaded );
const connected = await sftpClient.connect();
if( ! connected.status ) { return connected; }
const files = await sftpClient.list();
console.log( files );
// -> { status: true, count: 7, list: [ ... ] }
sftpClient.disconnect();
```
### await .list( folder = '', filters = {} )
* Filter: `pattern`
`pattern` filter can be a regular expression (most powerful option) or
a simple glob-like string where `*` will match any number of characters, e.g.
```js
// Default filters:
{
pattern: undefined,
onlyFiles: false,
onlyFolders: false,
}
// The filter options can be a regular expression (most powerful option) or
// a simple glob-like string where * will match any number of characters, e.g.
foo* => foo, foobar, foobaz
*bar => bar, foobar, tabbar
*oo* => foo, foobar, look, book
```
// Response
response example
```js
{
status: true,
count: // list.length
list:: [
list: [
{
type: // file type(-, d, l)
name: // file name
longname: // file name as linux promp
path: // file path
date: // file date of modified time
modifyDate: // file date of modified time
accessDate: // file date of access time
size: // file size
rights: { user: group: other: } // rwx
modifyTime: // file timestamp of modified time
accessTime: // file timestamp of access time
rights: { user: 'rwx', group: 'rwx', other: 'rwx' }
owner: // user number ID

@@ -201,15 +516,42 @@ group: // group number ID

```js
const sftpClient = new OSftp( config );
### await .move()
```ts
await sftpClient.move( filepathFrom: string, filepathTo?: string )
=> Promise<OSFtpFileResponse>;
const connected = await sftpClient.connect();
if( ! connected.status ) { return connected; }
export type OSFtpFileResponse = SResponse<
OSFtpFileObject, // as SResponseOK
OSFtpFileError // as SResponseKO
>;
const files = await sftpClient.list();
console.log( files );
interface SResponseOK {
status: true;
filename: string;
filepath: string;
}
sftpClient.disconnect();
interface SResponseKO {
status: false;
error: {
msg: string;
filepathFrom: string;
filepathTo?: string;
code?: OSFtpErrorCode;
}
}
interface OSFtpFileObject {
filename: string;
filepath: string;
}
interface OSFtpFileError {
msg: string;
filepathFrom: string;
filepathTo?: string;
code?: OSFtpErrorCode;
}
```
### await .move( filepathFrom, filepathTo )
`move` is the action to move from _ftp folder_ to _ftp folder_ (or event _rename_).

@@ -224,2 +566,3 @@ ```js

console.log( moved );
// -> { status: true, filename: 'custom-file.pdf', ... }

@@ -229,4 +572,41 @@ sftpClient.disconnect();

### await .delete( filepathFrom, strict = false )
### await .delete()
```ts
await sftpClient.delete( filepathFrom: string, strict?: boolean )
=> Promise<OSFtpFileResponse>;
export type OSFtpFileResponse = SResponse<
OSFtpFileObject, // as SResponseOK
OSFtpFileError // as SResponseKO
>;
interface SResponseOK {
status: true;
filename: string;
filepath: string;
}
interface SResponseKO {
status: false;
error: {
msg: string;
filepathFrom: string;
code?: OSFtpErrorCode;
}
}
interface OSFtpFileObject {
filename: string;
filepath: string;
}
interface OSFtpFileError {
msg: string;
filepathFrom: string;
code?: OSFtpErrorCode;
}
```
`delete` is the action to remove a file from _ftp folder_.
When `strict = false` and not found the file, it returns `{ status: true }`.

@@ -242,2 +622,3 @@

console.log( deleted );
// -> { status: true, filename: 'custom-file.pdf', ... }

@@ -247,6 +628,45 @@ sftpClient.disconnect();

### await .exists( filepathFrom )
### await .exists()
```ts
await sftpClient.exists( filepathFrom: string, disconnectWhenError?: boolean )
=> Promise<OSFtpExistResponse>;
It returns `{ status: Boolean, filepath: filepathFrom, [ type: <- only when file exists ] }`.
export type OSFtpExistResponse = SResponse<
OSFtpExistObject, // as SResponseOK
OSFtpExistError // as SResponseKO
>;
interface SResponseOK {
status: true;
filename: string;
filepath: string;
type: string;
}
interface SResponseKO {
status: false;
error: {
msg: string;
filename: string;
filepath: string;
code?: OSFtpErrorCode;
}
}
interface OSFtpExistObject {
filename: string;
filepath: string;
type: string;
}
interface OSFtpExistError {
msg: string;
filename: string;
filepath: string;
code?: OSFtpErrorCode;
}
```
`exists` is the action to check if a file or folder exists in _ftp folder_.
```js

@@ -260,2 +680,3 @@ const sftpClient = new OSftp( config );

console.log( exists );
// -> { status: true, filename: 'custom-file.pdf', type: 'd' ... }

@@ -265,6 +686,45 @@ sftpClient.disconnect();

### await .mkdir( folder, recursive = true, strict = false )
### await .mkdir()
```ts
await sftpClient.mkdir( folder, recursive?: boolean, strict?: boolean )
=> Promise<OSFtpFolderResponse>;
It allows to create folders recursively.
export type OSFtpFolderResponse = SResponse<
OSFtpFolderObject, // as SResponseOK
OSFtpFolderError // as SResponseKO
>;
interface SResponseOK {
status: true;
foldername: string;
folderpath: string;
}
interface SResponseKO {
status: false;
error: {
msg: string;
filepathFrom: string;
code?: OSFtpErrorCode;
}
}
interface OSFtpFolderObject {
foldername: string;
folderpath: string;
}
interface OSFtpFolderError {
msg: string;
folder: string;
code?: OSFtpErrorCode;
}
```
`mkdir` is the action to create folders in _ftp folder_.
When `recursive = true` it allows to create the subfolders too.
When `strict = false` and folder already exist, it returns `{ status: true }`.
```js

@@ -278,2 +738,3 @@ const sftpClient = new OSftp( config );

console.log( created );
// -> { status: true, foldername: 'custom-subfolder', ... }

@@ -283,5 +744,43 @@ sftpClient.disconnect();

### await .rmdir( folder, recursive = false, strict = false )
### await .rmdir()
```ts
await sftpClient.rmdir( folder, recursive?: boolean, strict?: boolean )
=> Promise<OSFtpFolderResponse>;
export type OSFtpFolderResponse = SResponse<
OSFtpFolderObject, // as SResponseOK
OSFtpFolderError // as SResponseKO
>;
interface SResponseOK {
status: true;
foldername: string;
folderpath: string;
}
interface SResponseKO {
status: false;
error: {
msg: string;
filepathFrom: string;
code?: OSFtpErrorCode;
}
}
interface OSFtpFolderObject {
foldername: string;
folderpath: string;
}
interface OSFtpFolderError {
msg: string;
folder: string;
code?: OSFtpErrorCode;
}
```
`rmdir` is the action to remove folders in _ftp folder_.
When `recursive = true` it allows to remove the folder-content too.
When `strict = false` and not found the folder, it returns `{ status: true }`.

@@ -297,2 +796,3 @@

console.log( removed );
// -> { status: true, foldername: 'custom-folder', ... }

@@ -305,3 +805,3 @@ sftpClient.disconnect();

If you want to run `npm run test`, it's required to declare your own `./test/config.json`
(you can copypaste it from `./test/config-default.json`)
(you can _copypaste_ it from `./test/config-default.json`)

@@ -317,6 +817,23 @@ ```json

__ADVISE:__ When run the testing, in the server it's created and removed the next folders:
`test-exists`, `test-mkdir`, `test-rmdir`, `test-list`, `test-delete`, `test-move`, `test-upload`, `test-download`;
__NOTICE:__ When tests are running, in the _server ftp_ it's created (and removed when it has finished) the next folders:
* `test-exists`,
* `test-mkdir`,
* `test-rmdir`,
* `test-list`,
* `test-delete`,
* `test-move`,
* `test-upload`,
* `test-download`;
* `test-exists-ts`,
* `test-mkdir-ts`,
* `test-rmdir-ts`,
* `test-list-ts`,
* `test-delete-ts`,
* `test-move-ts`,
* `test-upload-ts`,
* `test-download-ts`;
and the files `./zpython.pdf`, `./zpython2.pdf`.
So, if in your _sftp server_ already exist them and there are required for you, avoid to `run test`.
So,
* `rw` permissions should be allowed,
* and if in your _sftp server_ already exist them and there are required for you, avoid to `run test`.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc