pure-js-sftp
Version:
A pure JavaScript SFTP client with revolutionary RSA-SHA2 compatibility fixes. Zero native dependencies, built on ssh2-streams with 100% SSH key support.
315 lines • 10 kB
TypeScript
/**
* Pure JS SFTP Client
* A pure JavaScript SFTP client with no native dependencies
* 100% API compatible with ssh2-sftp-client
*/
import { SFTPClientOptions, DirectoryEntry } from './sftp/ssh2-streams-client';
import { EventEmitter } from 'events';
import { Readable, Writable } from 'stream';
export interface FileInfo {
type: 'd' | '-' | 'l';
name: string;
size: number;
modifyTime: number;
accessTime: number;
rights: {
user: string;
group: string;
other: string;
};
owner: number;
group: number;
}
export type FileInfoType = 'd' | '-' | 'l';
export interface ActiveOperation {
id: string;
type: 'upload' | 'download' | 'list' | 'delete' | 'rename' | 'mkdir' | 'rmdir' | 'chmod' | 'stat' | 'other';
localPath?: string;
remotePath?: string;
startTime: number;
bytesTransferred?: number;
totalBytes?: number;
}
export interface ConcurrencyOptions {
maxConcurrentOps?: number;
queueOnLimit?: boolean;
}
export interface KeepaliveEvent {
type: 'ping';
success: boolean;
missed?: number;
}
export interface HealthCheckEvent {
type: 'ping' | 'realpath';
success: boolean;
healthy: boolean;
error?: Error;
}
export interface ReconnectAttemptEvent {
attempt: number;
maxAttempts: number;
delay: number;
}
export interface ReconnectSuccessEvent {
attempts: number;
}
export interface ReconnectErrorEvent {
attempt: number;
error: Error;
}
export interface ReconnectFailedEvent {
attempts: number;
maxAttempts: number;
lastError?: string;
}
export interface AutoReconnectEvent {
reason: 'operation_limit' | 'timeout_recovery';
operations: number;
bytesTransferred: number;
}
export interface EnhancedOperationEvent {
type: 'upload' | 'download' | 'list' | 'stat' | 'delete' | 'rename' | 'mkdir' | 'rmdir' | 'chmod';
operation_id: string;
remotePath: string;
localPath?: string;
totalBytes?: number;
bytesTransferred?: number;
percentage?: number;
fileName?: string;
startTime: number;
chunkSize?: number;
concurrency?: number;
duration?: number;
error?: Error;
isRetryable?: boolean;
}
export interface ConnectionStateEvent {
host?: string;
port?: number;
username?: string;
authType?: 'password' | 'key';
serverInfo?: any;
capabilities?: any;
error?: Error;
phase?: 'connect' | 'auth' | 'ready';
}
export interface PerformanceMetricsEvent {
throughput: number;
avgChunkTime: number;
concurrencyUtilization: number;
windowUtilization: number;
operation_id?: string;
}
export interface AdaptiveChangeEvent {
reason: 'chunk_size_increased' | 'chunk_size_decreased' | 'concurrency_reduced' | 'concurrency_increased' | 'server_limit_detected';
oldValue: number;
newValue: number;
parameter: 'chunkSize' | 'concurrency' | 'timeout';
operation_id?: string;
}
export interface OperationRetryEvent {
operation_id: string;
attempt: number;
maxAttempts: number;
reason: 'timeout' | 'connection_lost' | 'server_error' | 'network_error';
delay: number;
error?: Error;
}
export interface ServerLimitEvent {
limitType: 'max_operations' | 'rate_limit' | 'concurrent_limit';
detectedLimit: number;
adaptiveAction: 'reducing_concurrency' | 'reconnecting' | 'throttling';
operation_id?: string;
}
export interface BatchOperationEvent {
batchId: string;
operationCount: number;
totalBytes: number;
completedOperations?: number;
operations?: string[];
}
export interface EventOptions {
enableProgressEvents: boolean;
enablePerformanceEvents: boolean;
enableAdaptiveEvents: boolean;
progressThrottle: number;
maxEventHistory: number;
debugMode: boolean;
}
export type ErrorCategory = 'network' | 'authentication' | 'permission' | 'server' | 'timeout' | 'filesystem' | 'protocol';
export interface ClassifiedError extends Error {
category: ErrorCategory;
isUserActionable: boolean;
suggestedAction: 'retry' | 'check_permissions' | 'reconnect' | 'check_network' | 'contact_admin';
isRetryable: boolean;
}
export declare class SftpClient extends EventEmitter {
private client;
private config;
private activeOperations;
private operationCounter;
private concurrencyOptions;
private operationQueue;
private processingQueue;
private eventOptions;
private operationIdCounter;
private batchIdCounter;
private eventHistory;
private lastProgressEmit;
private performanceMetrics;
constructor(_name?: string, concurrencyOptions?: ConcurrencyOptions);
/**
* Configure event system options for VSCode and other applications
*/
setEventOptions(options: Partial<EventOptions>): void;
/**
* Get current event system configuration
*/
getEventOptions(): EventOptions;
/**
* Generate unique operation ID
*/
private generateOperationId;
/**
* Generate unique batch ID
*/
private generateBatchId;
/**
* Extract filename from path for display purposes
*/
private extractFileName;
/**
* Classify error for better user messaging
*/
private classifyError;
/**
* Add event to history for debugging and tracking
*/
private addToEventHistory;
/**
* Emit enhanced operation start event
*/
private emitOperationStart;
/**
* Emit enhanced operation progress event with throttling
*/
private emitOperationProgress;
/**
* Emit enhanced operation complete event
*/
private emitOperationComplete;
/**
* Emit enhanced operation error event
*/
private emitOperationError;
/**
* Emit connection state events
*/
private emitConnectionEvent;
/**
* Emit performance metrics event
*/
private emitPerformanceMetrics;
/**
* Emit adaptive change event
*/
private emitAdaptiveChange;
/**
* Emit operation retry event
*/
private emitOperationRetry;
/**
* Emit server limit detected event
*/
private emitServerLimitDetected;
/**
* Emit batch operation events
*/
private emitBatchOperation;
/**
* Get event history for debugging
*/
getEventHistory(): Array<{
timestamp: number;
event: string;
data: any;
}>;
/**
* Clear event history
*/
clearEventHistory(): void;
/**
* Get current performance metrics
*/
getPerformanceMetrics(): typeof this.performanceMetrics;
private checkConnection;
private createOperation;
private completeOperation;
private failOperation;
private updateOperationProgress;
private executeWithConcurrencyControl;
private processQueue;
getActiveOperations(): ActiveOperation[];
getActiveOperationCount(): number;
getQueuedOperationCount(): number;
cancelAllOperations(): void;
updateConcurrencyOptions(options: ConcurrencyOptions): void;
private executePipelinedOperation;
connect(config: SFTPClientOptions): Promise<void>;
list(remotePath: string, filter?: (fileInfo: FileInfo) => boolean): Promise<FileInfo[]>;
get(remotePath: string, dst?: string | Writable): Promise<string | Writable | Buffer>;
put(input: string | Buffer | Readable, remotePath: string, options?: {
chunkTimeout?: number;
usePipelined?: boolean;
maxConcurrentWrites?: number;
}): Promise<string>;
delete(remotePath: string): Promise<void>;
rename(oldPath: string, newPath: string): Promise<void>;
mkdir(remotePath: string, recursive?: boolean): Promise<void>;
rmdir(remotePath: string, recursive?: boolean): Promise<void>;
exists(remotePath: string): Promise<false | FileInfoType>;
stat(remotePath: string): Promise<import("./ssh/types").FileAttributes>;
fastGet(remotePath: string, localPath: string, options?: any): Promise<string>;
fastPut(localPath: string, remotePath: string, options?: {
chunkTimeout?: number;
}): Promise<string>;
append(input: string | Buffer, remotePath: string, options?: any): Promise<string>;
chmod(remotePath: string, mode: string | number): Promise<void>;
realPath(remotePath: string): Promise<string>;
uploadDir(srcDir: string, dstDir: string, options?: {
filter?: (path: string, isDirectory: boolean) => boolean;
chunkTimeout?: number;
}): Promise<void>;
downloadDir(srcDir: string, dstDir: string, options?: {
filter?: (path: string, isDirectory: boolean) => boolean;
}): Promise<void>;
end(gracefulTimeout?: number): Promise<void>;
listDirectory(path: string): Promise<DirectoryEntry[]>;
openFile(path: string, flags?: number): Promise<Buffer<ArrayBufferLike>>;
closeFile(handle: Buffer): Promise<void>;
readFile(handle: Buffer, offset: number, length: number): Promise<Buffer<ArrayBufferLike>>;
writeFile(handle: Buffer, offset: number, data: Buffer, timeoutMs?: number): Promise<void>;
/**
* Handle automatic reconnection when approaching server operation limits
*/
private handleAutoReconnection;
disconnect(): void;
isReady(): boolean;
/**
* Get connection health status
*/
getHealthStatus(): {
healthy: boolean;
connected: boolean;
ready: boolean;
};
}
export default SftpClient;
export * from './ssh/types';
export type { SFTPClientOptions, KeepaliveConfig, HealthCheckConfig, AutoReconnectConfig } from './sftp/ssh2-streams-client';
export type { SSH2StreamsConfig } from './ssh/ssh2-streams-transport';
export { SSH2StreamsSFTPClient } from './sftp/ssh2-streams-client';
export { SSH2StreamsTransport } from './ssh/ssh2-streams-transport';
export { enablePureJSSigningFix, disablePureJSSigningFix, isPureJSSigningFixEnabled } from './ssh/pure-js-signing-fix';
export { SFTPError } from './ssh/types';
//# sourceMappingURL=index.d.ts.map