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

basic-ftp

Package Overview
Dependencies
Maintainers
1
Versions
112
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

basic-ftp - npm Package Compare versions

Comparing version 4.4.1 to 4.5.0

5

CHANGELOG.md
# Changelog
## 4.5.0
- Added: Directory listings are included in transfer progress tracking.
- Fixed: Possible edge case where socket is disconnected but client still says it's open.
## 4.4.1

@@ -4,0 +9,0 @@

2

dist/Client.d.ts

@@ -66,3 +66,3 @@ /// <reference types="node" />

*/
readonly closed: boolean;
get closed(): boolean;
/**

@@ -69,0 +69,0 @@ * Connect (or reconnect) to an FTP server.

@@ -7,3 +7,2 @@ "use strict";

const FtpContext_1 = require("./FtpContext");
const nullObject_1 = require("./nullObject");
const parseList_1 = require("./parseList");

@@ -360,3 +359,9 @@ const ProgressTracker_1 = require("./ProgressTracker");

// and removes the event listener for the source stream too early.
return await transfer_1.upload(this.ftp, this._progressTracker, source, command, validPath);
return await transfer_1.uploadFrom(source, {
ftp: this.ftp,
tracker: this._progressTracker,
command,
remotePath: validPath,
type: "upload"
});
}

@@ -423,6 +428,11 @@ finally {

await this.prepareTransfer(this.ftp);
const command = startAt > 0 ? `REST ${startAt}` : `RETR ${validPath}`;
// Keep the keyword `await` or the `finally` clause below runs too early
// and removes the event listener for the source stream too early.
return await transfer_1.download(this.ftp, this._progressTracker, destination, command, validPath);
return await transfer_1.downloadTo(destination, {
ftp: this.ftp,
tracker: this._progressTracker,
command: startAt > 0 ? `REST ${startAt}` : `RETR ${validPath}`,
remotePath: validPath,
type: "download"
});
}

@@ -466,4 +476,9 @@ finally {

const writable = new StringWriter_1.StringWriter();
const noTracker = nullObject_1.createNullObject(); // Don't track progress of list transfers.
await transfer_1.download(this.ftp, noTracker, writable, command);
await transfer_1.downloadTo(writable, {
ftp: this.ftp,
tracker: this._progressTracker,
command,
remotePath: "",
type: "list"
});
const text = writable.getText(this.ftp.encoding);

@@ -470,0 +485,0 @@ this.ftp.log(text);

@@ -71,5 +71,5 @@ export declare enum FileType {

constructor(name: string);
readonly isDirectory: boolean;
readonly isSymbolicLink: boolean;
readonly isFile: boolean;
get isDirectory(): boolean;
get isSymbolicLink(): boolean;
get isFile(): boolean;
/**

@@ -79,3 +79,4 @@ * Deprecated, legacy API. Use `rawModifiedAt` instead.

*/
date: string;
get date(): string;
set date(rawModifiedAt: string);
}

@@ -76,3 +76,3 @@ /// <reference types="node" />

*/
readonly closed: boolean;
get closed(): boolean;
/**

@@ -85,24 +85,27 @@ * Reset this contex and all of its state.

*/
get socket(): Socket | TLSSocket;
/**
* Set the socket for the control connection. This will only close the current control socket
* if the new one is not an upgrade to the current one.
*/
socket: Socket | TLSSocket;
* Set the socket for the control connection. This will only close the current control socket
* if the new one is not an upgrade to the current one.
*/
set socket(socket: Socket | TLSSocket);
/**
* Get the current FTP data connection if present.
*/
get dataSocket(): Socket | TLSSocket | undefined;
/**
* Set the socket for the data connection. This will automatically close the former data socket.
*/
dataSocket: Socket | TLSSocket | undefined;
* Set the socket for the data connection. This will automatically close the former data socket.
*/
set dataSocket(socket: Socket | TLSSocket | undefined);
/**
* Get the currently used encoding.
*/
get encoding(): string;
/**
* Set the encoding used for the control socket.
*
* See https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings for what encodings
* are supported by Node.
*/
encoding: string;
* Set the encoding used for the control socket.
*
* See https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings for what encodings
* are supported by Node.
*/
set encoding(encoding: string);
/**

@@ -130,3 +133,3 @@ * Send an FTP command without waiting for or handling the result.

*/
readonly hasTLS: boolean;
get hasTLS(): boolean;
/**

@@ -133,0 +136,0 @@ * Removes reference to current task and handler. This won't resolve or reject the task.

@@ -80,3 +80,3 @@ "use strict";

get closed() {
return this.socket.remoteAddress === undefined;
return this.socket.remoteAddress === undefined || this._closingError !== undefined;
}

@@ -83,0 +83,0 @@ /**

/// <reference types="node" />
import { Socket } from "net";
export declare type ProgressType = "upload" | "download" | "list";
/**

@@ -10,3 +11,3 @@ * Describes progress of file transfer.

/** The type of transfer, typically "upload" or "download". */
readonly type: string;
readonly type: ProgressType;
/** Transferred bytes in current transfer. */

@@ -37,3 +38,3 @@ readonly bytes: number;

*/
start(socket: Socket, name: string, type: string): void;
start(socket: Socket, name: string, type: ProgressType): void;
/**

@@ -40,0 +41,0 @@ * Stop tracking transfer progress.

/// <reference types="node" />
import { Writable, Readable } from "stream";
import { FTPContext, FTPResponse } from "./FtpContext";
import { ProgressTracker } from "./ProgressTracker";
import { ProgressTracker, ProgressType } from "./ProgressTracker";
export declare type UploadCommand = "STOR" | "APPE";

@@ -26,11 +26,10 @@ /**

export declare function connectForPassiveTransfer(host: string, port: number, ftp: FTPContext): Promise<void>;
/**
* Upload stream data as a file. For example:
*
* `upload(ftp, fs.createReadStream(localFilePath), remoteFilename)`
*/
export declare function upload(ftp: FTPContext, progress: ProgressTracker, source: Readable, command: UploadCommand, remoteFilename: string): Promise<FTPResponse>;
/**
* Download data from the data connection. Used for downloading files and directory listings.
*/
export declare function download(ftp: FTPContext, progress: ProgressTracker, destination: Writable, command: string, remoteFilename?: string): Promise<FTPResponse>;
export interface TransferConfig {
command: string;
remotePath: string;
type: ProgressType;
ftp: FTPContext;
tracker: ProgressTracker;
}
export declare function uploadFrom(source: Readable, config: TransferConfig): Promise<FTPResponse>;
export declare function downloadTo(destination: Writable, config: TransferConfig): Promise<FTPResponse>;

@@ -213,11 +213,6 @@ "use strict";

}
/**
* Upload stream data as a file. For example:
*
* `upload(ftp, fs.createReadStream(localFilePath), remoteFilename)`
*/
function upload(ftp, progress, source, command, remoteFilename) {
const resolver = new TransferResolver(ftp, progress);
const fullCommand = `${command} ${remoteFilename}`;
return ftp.handle(fullCommand, (res, task) => {
function uploadFrom(source, config) {
const resolver = new TransferResolver(config.ftp, config.tracker);
const fullCommand = `${config.command} ${config.remotePath}`;
return config.ftp.handle(fullCommand, (res, task) => {
if (res instanceof Error) {

@@ -227,3 +222,3 @@ resolver.onError(task, res);

else if (res.code === 150 || res.code === 125) { // Ready to upload
const dataSocket = ftp.dataSocket;
const dataSocket = config.ftp.dataSocket;
if (!dataSocket || !dataSocket.remoteAddress) {

@@ -237,4 +232,4 @@ resolver.onError(task, new Error("Upload should begin but no data connection is available."));

onConditionOrEvent(canUpload, dataSocket, "secureConnect", () => {
ftp.log(`Uploading to ${netUtils_1.describeAddress(dataSocket)} (${netUtils_1.describeTLS(dataSocket)})`);
resolver.onDataStart(remoteFilename, "upload");
config.ftp.log(`Uploading to ${netUtils_1.describeAddress(dataSocket)} (${netUtils_1.describeTLS(dataSocket)})`);
resolver.onDataStart(config.remotePath, config.type);
source.pipe(dataSocket).once("finish", () => {

@@ -255,8 +250,5 @@ dataSocket.destroy(); // Explicitly close/destroy the socket to signal the end.

}
exports.upload = upload;
/**
* Download data from the data connection. Used for downloading files and directory listings.
*/
function download(ftp, progress, destination, command, remoteFilename = "") {
if (!ftp.dataSocket) {
exports.uploadFrom = uploadFrom;
function downloadTo(destination, config) {
if (!config.ftp.dataSocket) {
throw new Error("Download will be initiated but no data connection is available.");

@@ -266,5 +258,5 @@ }

// receives the announcement. Start listening for data immediately.
ftp.dataSocket.pipe(destination);
const resolver = new TransferResolver(ftp, progress);
return ftp.handle(command, (res, task) => {
config.ftp.dataSocket.pipe(destination);
const resolver = new TransferResolver(config.ftp, config.tracker);
return config.ftp.handle(config.command, (res, task) => {
if (res instanceof Error) {

@@ -274,3 +266,3 @@ resolver.onError(task, res);

else if (res.code === 150 || res.code === 125) { // Ready to download
const dataSocket = ftp.dataSocket;
const dataSocket = config.ftp.dataSocket;
if (!dataSocket || !dataSocket.remoteAddress) {

@@ -280,8 +272,8 @@ resolver.onError(task, new Error("Download should begin but no data connection is available."));

}
ftp.log(`Downloading from ${netUtils_1.describeAddress(dataSocket)} (${netUtils_1.describeTLS(dataSocket)})`);
resolver.onDataStart(remoteFilename, "download");
config.ftp.log(`Downloading from ${netUtils_1.describeAddress(dataSocket)} (${netUtils_1.describeTLS(dataSocket)})`);
resolver.onDataStart(config.remotePath, config.type);
onConditionOrEvent(destination.destroyed || destination.writableFinished, destination, "finish", () => resolver.onDataDone(task));
}
else if (res.code === 350) { // Restarting at startAt.
ftp.send("RETR " + remoteFilename);
config.ftp.send("RETR " + config.remotePath);
}

@@ -297,3 +289,3 @@ else if (parseControlResponse_1.positiveCompletion(res.code)) { // Transfer complete

}
exports.download = download;
exports.downloadTo = downloadTo;
/**

@@ -300,0 +292,0 @@ * Calls a function immediately if a condition is met or subscribes to an event and calls

{
"name": "basic-ftp",
"version": "4.4.1",
"version": "4.5.0",
"description": "FTP client for Node.js, supports explicit FTPS over TLS, IPv6, Async/Await, and Typescript.",

@@ -39,12 +39,12 @@ "main": "dist/index",

"devDependencies": {
"@types/node": "12.11.7",
"@typescript-eslint/eslint-plugin": "2.5.0",
"@typescript-eslint/parser": "2.5.0",
"@types/node": "12.12.6",
"@typescript-eslint/eslint-plugin": "2.6.1",
"@typescript-eslint/parser": "2.6.1",
"eslint": "6.6.0",
"js-yaml": ">=3.13.1",
"mocha": "6.2.2",
"mock-fs": "4.10.2",
"mock-fs": "4.10.3",
"rimraf": "3.0.0",
"typescript": "3.6.4"
"typescript": "3.7.2"
}
}

@@ -168,3 +168,3 @@ # Basic FTP

Set a callback function with `client.trackProgress` to track the progress of all uploads and downloads. To disable progress reporting, call `trackProgress` with an undefined handler.
Set a callback function with `client.trackProgress` to track the progress of any transfer. Transfers are uploads, downloads or directory listings. To disable progress reporting, call `trackProgress` with an undefined handler.

@@ -192,3 +192,3 @@ ```js

For each transfer, the callback function will receive the filename, transfer type (upload/download) and number of bytes transferred. The function will be called at a regular interval during a transfer.
For each transfer, the callback function will receive the filename, transfer type (`upload`, `download` or `list`) and number of bytes transferred. The function will be called at a regular interval during a transfer.

@@ -237,10 +237,6 @@ There is also a counter for all bytes transferred since the last time `trackProgress` was called. This is useful when downloading a directory with multiple files where you want to show the total bytes downloaded so far.

Set the encoding applied to all incoming and outgoing messages of the control connection. This encoding is also used when parsing a list response from a data connection. Node supports `utf8`, `latin1` and `ascii`. Default is `utf8` because it's backwards-compatible with `ascii` and many modern servers support it, some of them without mentioning it when requesting features.
Set the encoding applied to all incoming and outgoing messages of the control connection. This encoding is also used when parsing a list response from a data connection. See https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings for what encodings are supported by Node.js. Default is `utf8` because most modern servers support it, some of them without mentioning it when requesting features.
`get/set ipFamily`
Set the preferred version of the IP stack: `4` (IPv4), `6` (IPv6) or `undefined` (Node.js default). Set to `undefined` by default.
## Acknowledgment
This library uses parts of the [directory listing parsers](https://github.com/apache/commons-net/tree/master/src/main/java/org/apache/commons/net/ftp/parser) written by The Apache Software Foundation. They've been made available under the Apache 2.0 license. See the [included notice](NOTICE.txt) and headers in the respective files containing the original copyright texts and a description of changes.
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