npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

unnbound-sftp-sdk

v1.0.21

Published

An SFTP client with structured logging.

Downloads

5,745

Readme

Unnbound SFTP Client

A TypeScript SFTP client with structured logging and distributed tracing capabilities, built on top of ssh2-sftp-client and integrated with the Unnbound logging system.

Features

  • Full SFTP Operations: Complete set of SFTP operations including file transfer, directory management, and file system operations
  • Structured Logging: Built-in integration with Unnbound Logger for comprehensive operation tracking
  • Distributed Tracing: Automatic span creation for all SFTP operations with detailed payload information
  • Type Safety: Full TypeScript support with comprehensive type definitions
  • Performance Monitoring: Built-in metrics collection for file sizes, operation counts, and timing
  • Flexible Configuration: Support for various authentication methods and connection options

Installation

npm install unnbound-sftp-sdk
# or
pnpm add unnbound-sftp-sdk
# or
yarn add unnbound-sftp-sdk

Quick Start

import { UnnboundSftpClient } from 'unnbound-sftp-sdk';
import { logger } from 'unnbound-logger-sdk';

const sftp = new UnnboundSftpClient({
  host: 'your-sftp-server.com',
  port: 22,
  username: 'your-username',
  privateKey: 'your-private-key', // or use password
});

// Connect to the SFTP server
await sftp.connect();

// Get current working directory
const currentPath = await sftp.cwd();
console.log('Current path:', currentPath);

// Create a directory
await sftp.mkdir('./uploads', true); // recursive

// Upload a file
const fileContent = Buffer.from('Hello, World!');
await sftp.put(fileContent, './uploads/hello.txt');

// Download a file
const downloadedContent = await sftp.get('./uploads/hello.txt');
console.log('Downloaded:', downloadedContent.toString());

// List files in a directory
const files = await sftp.list('./uploads');
console.log(
  'Files:',
  files.map((f) => f.name)
);

// Close the connection
await sftp.close();

API Reference

Constructor

new UnnboundSftpClient(options: UnnboundSftpClientOptions)

Options

| Property | Type | Required | Description | | ------------------- | ---------------- | -------- | ----------------------------------------------------- | | host | string | ✅ | SFTP server hostname | | port | number | ❌ | SFTP server port (default: 22) | | username | string | ❌ | Username for authentication | | password | string | ❌ | Password for authentication | | privateKey | string | ❌ | Private key for key-based authentication | | passphrase | string | ❌ | Passphrase for encrypted private keys | | localHostname | string | ❌ | Local hostname for hostbased authentication | | localUsername | string | ❌ | Local username for hostbased authentication | | keepaliveInterval | number | ❌ | SSH keepalive interval in milliseconds (0 to disable) | | keepaliveCountMax | number | ❌ | Max unanswered keepalive packets before disconnection | | readyTimeout | number | ❌ | SSH handshake timeout in milliseconds | | localAddress | string | ❌ | Local network interface IP address | | localPort | number | ❌ | Local port number | | timeout | number | ❌ | Socket timeout in milliseconds | | ident | string | ❌ | Server software identifier (default: 'unnbound') | | logger | UnnboundLogger | ❌ | Custom logger instance (uses default if not provided) |

Connection Management

connect(): Promise<void>

Establishes a connection to the SFTP server.

await sftp.connect();

close(): Promise<boolean>

Closes the SFTP connection.

const closed = await sftp.close();

File Operations

get(path: string): Promise<Buffer>

Downloads a file from the remote server.

const content = await sftp.get('/remote/path/file.txt');

put(input: Buffer, path: string): Promise<string>

Uploads a buffer to the remote server.

const data = Buffer.from('file content');
await sftp.put(data, '/remote/path/file.txt');

append(input: Buffer | NodeJS.ReadableStream, path: string): Promise<string>

Appends data to an existing file.

const additionalData = Buffer.from('more content');
await sftp.append(additionalData, '/remote/path/file.txt');

Directory Operations

list(path: string, filter?: ListFilterFunction): Promise<FileInfo[]>

Lists files and directories in the specified path.

const files = await sftp.list('/remote/directory');
const onlyFiles = await sftp.list('/remote/directory', (item) => item.type === '-');

mkdir(path: string, recursive?: boolean): Promise<string>

Creates a directory.

await sftp.mkdir('/remote/new-directory');
await sftp.mkdir('/remote/nested/path', true); // recursive

rmdir(path: string, recursive?: boolean): Promise<string>

Removes a directory.

await sftp.rmdir('/remote/empty-directory');
await sftp.rmdir('/remote/directory-with-files', true); // recursive

uploadDir(sourcePath: string, destinationPath: string, options?: UploadDirOptions): Promise<string>

Uploads an entire directory.

await sftp.uploadDir('./local/directory', '/remote/destination');

downloadDir(sourcePath: string, destinationPath: string, options?: DownloadDirOptions): Promise<string>

Downloads an entire directory.

await sftp.downloadDir('/remote/directory', './local/destination');

File System Operations

exists(path: string): Promise<false | FileInfoType>

Checks if a file or directory exists.

const exists = await sftp.exists('/remote/path/file.txt');
// Returns: false, 'd' (directory), '-' (file), or 'l' (symlink)

stat(path: string): Promise<FileStats>

Gets file or directory statistics.

const stats = await sftp.stat('/remote/path/file.txt');
console.log('Size:', stats.size);
console.log('Modified:', stats.modifyTime);

realPath(path: string): Promise<string>

Resolves the real path of a file or directory.

const realPath = await sftp.realPath('/remote/symlink');

cwd(): Promise<string>

Gets the current working directory.

const currentDir = await sftp.cwd();

delete(path: string, noErrorOK?: boolean): Promise<string>

Deletes a file.

await sftp.delete('/remote/path/file.txt');

rename(sourcePath: string, destinationPath: string): Promise<string>

Renames or moves a file or directory.

await sftp.rename('/remote/old-name.txt', '/remote/new-name.txt');

chmod(path: string, mode: number | string): Promise<string>

Changes file or directory permissions.

await sftp.chmod('/remote/path/file.txt', 0o644);
await sftp.chmod('/remote/path/file.txt', '644');

Type Definitions

FileInfo

interface FileInfo {
  type: FileInfoType; // 'd' | '-' | 'l' (directory, file, symlink)
  name: string;
  size: number;
  modifyTime: number;
  accessTime: number;
  rights: {
    user: string;
    group: string;
    other: string;
  };
  owner: number;
  group: number;
}

FileStats

interface FileStats {
  mode: number;
  uid: number;
  gid: number;
  size: number;
  accessTime: number;
  modifyTime: number;
  isDirectory: boolean;
  isFile: boolean;
  isBlockDevice: boolean;
  isCharacterDevice: boolean;
  isSymbolicLink: boolean;
  isFIFO: boolean;
  isSocket: boolean;
}

Directory Options

interface DirOptions {
  filter?: DirFilterFunction;
}

interface UploadDirOptions extends DirOptions {
  useFastput?: boolean;
}

interface DownloadDirOptions extends DirOptions {
  useFastget?: boolean;
}

Logging and Tracing

The Unnbound SFTP Client automatically creates spans for all operations and logs detailed information including:

  • Operation type and timing
  • File paths and sizes
  • Host information
  • Error details (if any)
  • File counts for directory operations
  • Content previews for file operations
  • Byte counts for transfers

Custom Logger

You can provide a custom logger instance:

import { UnnboundSftpClient } from 'unnbound-sftp-sdk';
import { logger } from 'unnbound-logger-sdk';

const sftp = new UnnboundSftpClient({
  host: 'sftp.example.com',
  username: 'user',
  password: 'pass',
  logger: logger, // Custom logger instance
});

Example Log Output

{"level":"info","spanId":"556c53e6-3bb8-4118-b3b8-570e41c27654","type":"sftp","sftp":{"host":"sftp.domain.com","operation":"connect"},"message":"SFTP connect started."}
{"level":"info","spanId":"556c53e6-3bb8-4118-b3b8-570e41c27654","type":"sftp","sftp":{"host":"sftp.domain.com","operation":"connect"},"duration":2771,"message":"SFTP connect completed."}
{"level":"info","spanId":"556c53e6-3bb8-4118-b3b8-570e41c27654","type":"sftp","sftp":{"host":"sftp.domain.com","operation":"put","path":"/uploads/file.txt","bytes":1024,"content":"Hello World"},"message":"SFTP put started."}
{"level":"info","spanId":"556c53e6-3bb8-4118-b3b8-570e41c27654","type":"sftp","sftp":{"host":"sftp.domain.com","operation":"put","path":"/uploads/file.txt","bytes":1024,"content":"Hello World"},"duration":150,"message":"SFTP put completed."}

Error Handling

All methods return promises that will reject with detailed error information:

try {
  await sftp.get('/non-existent-file.txt');
} catch (error) {
  console.error('SFTP operation failed:', error.message);
  // Error details are automatically logged with the span
}

Authentication Methods

Password Authentication

const sftp = new UnnboundSftpClient({
  host: 'sftp.example.com',
  username: 'myuser',
  password: 'mypassword',
});

Private Key Authentication

const sftp = new UnnboundSftpClient({
  host: 'sftp.example.com',
  username: 'myuser',
  privateKey: `-----BEGIN OPENSSH PRIVATE KEY-----
...your private key content...
-----END OPENSSH PRIVATE KEY-----`,
});

Private Key with Passphrase

const sftp = new UnnboundSftpClient({
  host: 'sftp.example.com',
  username: 'myuser',
  privateKey: 'your-private-key',
  passphrase: 'your-passphrase',
});

Private Key from Environment Variables

The client automatically normalizes private keys from environment variables by converting \n escape sequences to actual newlines:

// Environment variable: PRIVATE_KEY="-----BEGIN OPENSSH PRIVATE KEY-----\nMIIEpAIBAAKCAQEA...\n-----END OPENSSH PRIVATE KEY-----"

const sftp = new UnnboundSftpClient({
  host: 'sftp.example.com',
  username: 'myuser',
  privateKey: process.env.PRIVATE_KEY, // Automatically normalized
});

Requirements

  • Node.js >= 22.0.0
  • TypeScript (for TypeScript projects)

Dependencies

  • ssh2-sftp-client: Core SFTP functionality
  • unnbound-logger-sdk: Structured logging and tracing

Support

For support, please open an issue on the GitHub repository.