basic-ftp
Advanced tools
Comparing version 2.4.0 to 2.4.1
# Changelog | ||
## 2.4.1 | ||
- Improve introduction in README | ||
## 2.4.0 | ||
@@ -4,0 +8,0 @@ |
@@ -30,7 +30,7 @@ "use strict"; | ||
constructor(timeout = 0, encoding = "utf8") { | ||
// A timeout can be applied to the control connection. | ||
// Timeout applied to all connections. | ||
this._timeout = timeout; | ||
// The current task to be resolved or rejected. | ||
// Current task to be resolved or rejected. | ||
this._task = undefined; | ||
// A function that handles incoming messages and resolves or rejects a task. | ||
// Function that handles incoming messages and resolves or rejects a task. | ||
this._handler = undefined; | ||
@@ -52,3 +52,3 @@ // A multiline response might be received as multiple chunks. | ||
/** | ||
* Closes control and data sockets. | ||
* Close control and data connections. | ||
*/ | ||
@@ -61,2 +61,3 @@ close() { | ||
/** @type {Socket} */ | ||
get socket() { | ||
@@ -66,2 +67,7 @@ return this._socket; | ||
/** | ||
* Set the socket for the control connection. This will *not* close the former control socket automatically. | ||
* | ||
* @type {Socket} | ||
*/ | ||
set socket(socket) { | ||
@@ -80,2 +86,3 @@ if (this._socket) { | ||
/** @type {Socket} */ | ||
get dataSocket() { | ||
@@ -85,2 +92,7 @@ return this._dataSocket; | ||
/** | ||
* Set the socket for the data connection. This will automatically close the former data socket. | ||
* | ||
* @type {Socket} | ||
**/ | ||
set dataSocket(socket) { | ||
@@ -92,3 +104,4 @@ this._closeSocket(this._dataSocket); | ||
/** | ||
* Returns true if TLS is enabled for the control socket. | ||
* Return true if TLS is enabled for the control socket. | ||
* | ||
* @returns {boolean} | ||
@@ -142,3 +155,4 @@ */ | ||
/** | ||
* Logs message if client is verbose | ||
* Log message if set to be verbose. | ||
* | ||
* @param {string} message | ||
@@ -154,2 +168,3 @@ */ | ||
* Handle incoming data on the control socket. | ||
* | ||
* @private | ||
@@ -177,2 +192,3 @@ * @param {Buffer} data | ||
* or a socket event, like an error or timeout. | ||
* | ||
* @private | ||
@@ -189,2 +205,3 @@ * @param {Object} payload | ||
* Configure socket properties common to both control and data socket connections. | ||
* | ||
* @private | ||
@@ -215,2 +232,3 @@ * @param {Socket} socket | ||
* Close a socket. | ||
* | ||
* @private | ||
@@ -228,3 +246,3 @@ * @param {Socket} socket | ||
/** | ||
* A basic FTP client API. | ||
* An FTP client. | ||
*/ | ||
@@ -600,2 +618,7 @@ class Client { | ||
reject(task, reason) { | ||
this.ftp.dataSocket = undefined; | ||
task.reject(reason); | ||
} | ||
_tryResolve(task) { | ||
@@ -724,3 +747,2 @@ if (this.confirmed && this.result !== undefined) { | ||
ftp.dataSocket.once("end", () => { | ||
ftp.dataSocket = undefined; | ||
ftp.log(rawList); | ||
@@ -734,4 +756,3 @@ resolver.resolve(task, parseList(rawList)); | ||
else if (res.code >= 400 || res.error) { | ||
ftp.dataSocket = undefined; | ||
task.reject(res); | ||
resolver.reject(task, res); | ||
} | ||
@@ -756,5 +777,5 @@ }); | ||
if (res.code === 150 || res.code === 125) { // Ready to upload | ||
// If all data has been flushed, close the socket to signal | ||
// the FTP server that the transfer is complete. | ||
ftp.dataSocket.once("finish", () => { | ||
// If all data has been flushed, close the data socket explicitly | ||
// to signal the FTP server that the transfer is complete. | ||
ftp.dataSocket = undefined; | ||
@@ -769,4 +790,3 @@ resolver.confirm(task); | ||
else if (res.code >= 400 || res.error) { | ||
ftp.dataSocket = undefined; | ||
task.reject(res); | ||
resolver.reject(task, res); | ||
} | ||
@@ -802,4 +822,3 @@ }); | ||
else if (res.code >= 400 || res.error) { | ||
ftp.dataSocket = undefined; | ||
task.reject(res); | ||
resolver.reject(task, res); | ||
} | ||
@@ -806,0 +825,0 @@ }); |
{ | ||
"name": "basic-ftp", | ||
"version": "2.4.0", | ||
"version": "2.4.1", | ||
"description": "FTP/FTPS client library", | ||
@@ -5,0 +5,0 @@ "main": "./lib/ftp", |
@@ -9,8 +9,6 @@ # Basic FTP | ||
FTP is an old protocol, there are many features, quirks and server implementations. A response might not be as expected, a directory listing use yet another format. | ||
This library has two goals: Provide a solid foundation that covers most needs and make it easy to extend functionality if necessary. | ||
This library does not try to solve all possible issues. The main goal is to provide a solid foundation and a clean extension API for you to solve your specific issues without requiring a change in the library itself. | ||
FTP is an old protocol, there are many features, quirks and server implementations. It's not a goal to support all of them but it should be easy for you to solve your specific issues without changing the library. | ||
Non-goals are: Feature completeness, support for every FTP server, complete abstraction from FTP details. If you're not interested in how FTP works at all, this library might not be for you. | ||
## Dependencies | ||
@@ -20,5 +18,5 @@ | ||
## Example | ||
## Introduction | ||
The example below shows how to connect, upgrade to TLS, login, get a directory listing and upload a file. | ||
`Client` provides a convenience API to interact with an FTP server. The following example shows how to connect, upgrade to TLS, login, get a directory listing and upload a file. | ||
@@ -48,6 +46,22 @@ ```js | ||
The `Client` provides a minimal API to interact with an FTP server. Not all FTP commands are backed by a method. You're expected to use a number of them directly, for example `await client.send("CDUP")`. | ||
The example sets the client to be `verbose`. This will log out all communication, making it easier to spot an issue and address it. It's also a great way to learn about FTP. Why the setting is behind a property `.ftp` will be answered in the section about extending the library below. | ||
The example also sets the client to be `verbose`. This will log out every communication detail, making it easier to spot an issue and address it. It's also a great way to learn about FTP. Why the setting is behind a property `.ftp` will be answered in the section about extending the library below. | ||
Here is another example to show how to compose more complex operations like recursively removing all files and directories. This function is already part of the Client API. | ||
```js | ||
async clearWorkingDir() { | ||
for (const file of await this.list()) { | ||
if (file.isDirectory) { | ||
await this.cd(file.name); | ||
await this.clearWorkingDir(); | ||
await this.send("CDUP"); | ||
await this.send("RMD " + file.name); | ||
} | ||
else { | ||
await this.send("DELE " + file.name); | ||
} | ||
} | ||
} | ||
``` | ||
## Client API | ||
@@ -63,11 +77,11 @@ | ||
`connect(host, port)` | ||
`connect(host, port = 21)` | ||
Connect to an FTP server. | ||
`useTLS(options)` | ||
`useTLS([options])` | ||
Upgrade the existing control connection with TLS. You may provide options that are the same you'd use for `tls.connect()` in NodeJS. For example `rejectUnauthorized: false` if you must. Call this function before you log in. Subsequently created data connections will automatically be upgraded to TLS. | ||
`login(user, password)` | ||
`login(user = "guest", password = "anonymous")` | ||
@@ -82,7 +96,7 @@ Login with a username and a password. | ||
Send an FTP command. You can optionally choose to ignore error return codes. | ||
Send an FTP command. You can optionally choose to ignore error return codes. Other errors originating from the socket connections including timeouts will still throw an exception. | ||
`cd(remotePath)` | ||
Changes the working directory. | ||
Change the working directory. | ||
@@ -109,6 +123,2 @@ `pwd()` | ||
`removeDir(remoteDirPath)` | ||
Remove a directory at a given path, including all of its files and directories. | ||
`clearWorkingDir()` | ||
@@ -118,4 +128,8 @@ | ||
`uploadDir(localDirPath, remoteDirName = undefined)` | ||
`removeDir(remoteDirPath)` | ||
Remove all files and directories from a given directory, including the directory itself. | ||
`uploadDir(localDirPath, [remoteDirName])` | ||
Upload all files and directories of a local directory to the current working directory. If you specify a `remoteDirName` it will place the uploads inside a directory of the given name. | ||
@@ -135,7 +149,7 @@ | ||
FTP uses a dedicated socket connection for each single data transfer. Data transfers include directory listings, file uploads and downloads. This property holds the function that prepares this connection. Right now the library only offers Passive Mode over IPv4. The signature of the function is `(ftp: FTPContext) => Promise<void>`. The section below about extending functionality explains what `FTPContext` is. | ||
You can provide a custom function that prepares the data connection for a transfer. FTP uses a dedicated socket connection for each single data transfer. Data transfers include directory listings, file uploads and downloads. This property holds the function that prepares this connection. Right now the library only offers Passive Mode over IPv4. The signature of the function is `(ftp: FTPContext) => Promise<void>`. The section below about extending functionality explains what `FTPContext` is. | ||
`get/set client.parseList` | ||
You may optionally provide a custom parser to parse the listing data, for example to support the DOS format. This library only supports the Unix format for now. Parsing these list responses can be regarded as the central piece of every FTP client because there is no standard that all servers adhere to. The signature of the function is `(rawList: string) => FileInfo[]`. `FileInfo` is also exported by the library. | ||
You can provide a custom parser to parse directory listing data, for example to support the DOS format. This library only supports the Unix format for now. Parsing these list responses is a central part of every FTP client because there is no standard that all servers adhere to. The signature of the function is `(rawList: string) => FileInfo[]`. `FileInfo` is also exported by the library. | ||
@@ -164,3 +178,3 @@ ## Extend | ||
Get or 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. Possible values are `utf8`, `latin1`, `ascii`. Default is `utf8` because most modern servers support this and some of them don't even list this feature in the response of the FEAT command. | ||
Get or 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. Possible values are `utf8`, `latin1`, `ascii`. Default is `utf8` because most modern servers support this and some of them don't even list this feature in the response of the FEAT command. You can change this setting at any time. | ||
@@ -167,0 +181,0 @@ `handle(command, handler)` |
85420
1219
209