Files

138 lines
4.7 KiB
TypeScript
Raw Permalink Normal View History

// SFTP Types
export type SftpFilenameEncoding = 'auto' | 'utf-8' | 'gb18030';
export interface SftpFileEntry {
name: string;
type: 'file' | 'directory' | 'symlink';
size: number;
sizeFormatted: string;
lastModified: number;
lastModifiedFormatted: string;
permissions?: string;
owner?: string;
group?: string;
linkTarget?: 'file' | 'directory' | null; // For symlinks: the type of the target, or null if broken
hidden?: boolean; // Windows hidden attribute (only set for local Windows filesystem)
}
export interface SftpConnection {
id: string;
hostId: string;
hostLabel: string;
isLocal: boolean;
status: 'connecting' | 'connected' | 'disconnected' | 'error';
error?: string;
currentPath: string;
homeDir?: string;
/** True when this SFTP connection reuses an existing terminal SSH session */
reusedConnection?: boolean;
/** Terminal session whose confirmed SSH transport backs this connection. */
sourceSessionId?: string;
fileProtocol?: 'auto' | 'sftp' | 'scp';
}
export type TransferStatus =
| 'pending'
| 'queued'
| 'transferring'
| 'pausing'
| 'paused'
| 'attention'
| 'interrupted'
| 'completed'
| 'failed'
| 'cancelled';
export type TransferDirection = 'upload' | 'download' | 'remote-to-remote' | 'local-copy';
export type TransferOrigin = 'manual' | 'drag-drop' | 'editor-sync' | 'agent' | 'internal';
export type TransferPhase = 'scanning' | 'compressing' | 'uploading' | 'transferring' | 'extracting' | 'verifying';
export type TransferControlKind = 'stream' | 'compressed-upload';
export interface DirectoryResumeCheckpoint {
/** Version 1 used a full SHA-256 digest for every appended entry. Version 2
* keeps the SHA-256 compression state so adding another fixed-width identity
* is still cryptographically chained without re-hashing string wrappers. */
version: 1 | 2;
/** Traversal prefix whose source/target metadata is covered by manifestHash. */
coveredEntries: number;
/** Covered entries already completed and compacted out of the task array. */
completedEntries: number;
/** Fixed-size chained SHA-256 value of the covered traversal prefix. */
manifestHash: string;
}
export interface TransferTask {
id: string;
batchId?: string;
fileName: string;
originalFileName?: string;
sourcePath: string;
targetPath: string;
sourceConnectionId: string;
targetConnectionId: string;
targetHostId?: string;
/** Full endpoint key (hostId:hostname:port:protocol) for distinguishing
* same-hostId uploads with different session-time overrides. */
targetConnectionKey?: string;
direction: TransferDirection;
status: TransferStatus;
totalBytes: number;
transferredBytes: number;
speed: number; // bytes per second
error?: string;
startTime: number;
endTime?: number;
isDirectory: boolean;
progressMode?: 'bytes' | 'files';
childTasks?: string[]; // For directory transfers
parentTaskId?: string;
sourceLastModified?: number; // Cached from file list to avoid redundant stat
skipConflictCheck?: boolean; // Skip conflict check for replace operations
replaceExistingTarget?: boolean; // Delete the existing target before transferring
retryable?: boolean; // False for task types that cannot be safely replayed through generic retry
ownerId?: string;
sourceHostId?: string;
sourceHostLabel?: string;
targetHostLabel?: string;
origin?: TransferOrigin;
background?: boolean;
phase?: TransferPhase;
/** Selects the background job API used by the global transfer center. */
controlKind?: TransferControlKind;
/** Monotonic backend lifecycle version. Newer pause/resume truth wins over stale progress or panel snapshots. */
lifecycleEpoch?: number;
resumable?: boolean;
checkpointBytes?: number;
resumeStage?: 'direct' | 'download' | 'upload';
downloadCheckpointBytes?: number;
uploadCheckpointBytes?: number;
priority?: number;
updatedAt?: number;
pauseUnavailableReason?: string;
conflict?: FileConflict;
stagedTargetPath?: string;
sourceFingerprint?: string;
reconnectRequired?: boolean;
/** Stable position and identity used to compact completed directory children. */
directoryEntryIndex?: number;
directoryEntryIdentity?: string;
/** Fixed-size resume record stored only on a top-level directory task. */
directoryResumeCheckpoint?: DirectoryResumeCheckpoint;
}
export type FileConflictAction = 'stop' | 'skip' | 'replace' | 'duplicate' | 'merge';
export interface FileConflict {
transferId: string;
batchId?: string;
fileName: string;
sourcePath: string;
targetPath: string;
isDirectory: boolean;
existingType?: 'file' | 'directory' | 'symlink';
applyToAllCount?: number;
existingSize: number;
newSize: number;
existingModified: number;
newModified: number;
}