From 42d4a2d09cd38d60a6ec1bb48eab421ebf639c78 Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Sat, 24 Aug 2024 12:50:21 +0800 Subject: [PATCH 1/4] fix: fixes "url" argument must be of type string with nodejs 20 node:internal/errors:541 throw error; ^ TypeError [ERR_INVALID_ARG_TYPE]: The "url" argument must be of type string. Received undefined at Url.parse (node:url:170:3) at Object.urlParse [as parse] (node:url:141:13) at new FtpServer (C:\work\xemu\xemu-bsp-list\ftp-srv\src\index.js:34:24) at startFtpServer (C:\work\xemu\xemu-bsp-list\ftp-srv\bin\index.js:133:21) at Object. (C:\work\xemu\xemu-bsp-list\ftp-srv\bin\index.js:11:1) at Module._compile (node:internal/modules/cjs/loader:1369:14) at Module._extensions..js (node:internal/modules/cjs/loader:1427:10) at Module.load (node:internal/modules/cjs/loader:1206:32) at Module._load (node:internal/modules/cjs/loader:1022:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12) at node:internal/main/run_main_module:28:49 { code: 'ERR_INVALID_ARG_TYPE' } Node.js v20.12.0 --- src/index.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/index.js b/src/index.js index 859540d..ff36f73 100644 --- a/src/index.js +++ b/src/index.js @@ -25,8 +25,7 @@ class FtpServer extends EventEmitter { greeting: null, tls: false, timeout: 0 - }, options); - + }, _.pickBy(options, v => v !== undefined)); this._greeting = this.setupGreeting(this.options.greeting); this._features = this.setupFeaturesMessage(); @@ -52,7 +51,7 @@ class FtpServer extends EventEmitter { socket.once('close', () => { this.emit('disconnect', {connection, id: connection.id, newConnectionCount: Object.keys(this.connections).length}); }) - + this.emit('connect', {connection, id: connection.id, newConnectionCount: Object.keys(this.connections).length}); const greeting = this._greeting || []; @@ -67,7 +66,7 @@ class FtpServer extends EventEmitter { this.log.error(err, '[Event] error'); this.emit('server-error', {error: err}); }); - + const quit = _.debounce(this.quit.bind(this), 100); process.on('SIGTERM', quit); @@ -138,7 +137,7 @@ class FtpServer extends EventEmitter { } catch (err) { this.log.error(err, 'Error closing connection', {id}); } - + resolve('Disconnected'); }); } From e69c3537790976ef0eb2b4f7fea0d90ab1ccb3d7 Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Sat, 24 Aug 2024 14:56:30 +0800 Subject: [PATCH 2/4] feat: getting ftp-srv.js match ftp-srv.d.ts Signed-off-by: Yonggang Luo --- ftp-srv.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ftp-srv.js b/ftp-srv.js index b700858..7393db2 100644 --- a/ftp-srv.js +++ b/ftp-srv.js @@ -1,8 +1,14 @@ -const FtpSrv = require('./src'); +const FtpServer = require('./src'); +const FtpConnection = require('./src/connection'); const FileSystem = require('./src/fs'); const errors = require('./src/errors'); -module.exports = FtpSrv; -module.exports.FtpSrv = FtpSrv; +module.exports = FtpServer; +module.exports.FtpSrv = FtpServer; +module.exports.FtpServer = FtpServer; module.exports.FileSystem = FileSystem; -module.exports.ftpErrors = errors; +module.exports.GeneralError = errors.GeneralError; +module.exports.SocketError = errors.SocketError; +module.exports.FileSystemError = errors.FileSystemError; +module.exports.ConnectorError = errors.ConnectorError; +module.exports.FtpConnection = FtpConnection; From 8fd7136fadd6e502fe4ae0ef9fe6475f1f6d7aad Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Sat, 24 Aug 2024 20:14:47 +0800 Subject: [PATCH 3/4] fix: indent ftp-srv.d.ts with 2 space --- ftp-srv.d.ts | 259 +++++++++++++++++++++++++++------------------------ 1 file changed, 139 insertions(+), 120 deletions(-) diff --git a/ftp-srv.d.ts b/ftp-srv.d.ts index 4b3231f..2bc5556 100644 --- a/ftp-srv.d.ts +++ b/ftp-srv.d.ts @@ -1,44 +1,60 @@ -import * as tls from 'tls' -import { Stats } from 'fs' -import { EventEmitter } from 'events'; +import * as tls from "tls"; +import { Stats } from "fs"; +import { EventEmitter } from "events"; export class FileSystem { - - readonly connection: FtpConnection; - readonly root: string; - readonly cwd: string; - - constructor(connection: FtpConnection, {root, cwd}?: { - root: any; - cwd: any; - }); - - currentDirectory(): string; - - get(fileName: string): Promise; - - list(path?: string): Promise; - - chdir(path?: string): Promise; - - write(fileName: string, {append, start}?: { - append?: boolean; - start?: any; - }): any; - - read(fileName: string, {start}?: { - start?: any; - }): Promise; - - delete(path: string): Promise; - - mkdir(path: string): Promise; - - rename(from: string, to: string): Promise; - - chmod(path: string, mode: string): Promise; - - getUniqueName(fileName: string): string; + readonly connection: FtpConnection; + readonly root: string; + readonly cwd: string; + + constructor( + connection: FtpConnection, + { + root, + cwd, + }?: { + root: any; + cwd: any; + } + ); + + currentDirectory(): string; + + get(fileName: string): Promise; + + list(path?: string): Promise; + + chdir(path?: string): Promise; + + write( + fileName: string, + { + append, + start, + }?: { + append?: boolean; + start?: any; + } + ): any; + + read( + fileName: string, + { + start, + }?: { + start?: any; + } + ): Promise; + + delete(path: string): Promise; + + mkdir(path: string): Promise; + + rename(from: string, to: string): Promise; + + chmod(path: string, mode: string): Promise; + + getUniqueName(fileName: string): string; } export class GeneralError extends Error { @@ -74,93 +90,96 @@ export class ConnectorError extends Error { } export class FtpConnection extends EventEmitter { - server: FtpServer; - id: string; - log: any; - transferType: string; - encoding: string; - bufferSize: boolean; - readonly ip: string; - restByteCount: number | undefined; - secure: boolean - - close (code: number, message: number): Promise - login (username: string, password: string): Promise - reply (options: number | Object, ...letters: Array): Promise - + server: FtpServer; + id: string; + log: any; + transferType: string; + encoding: string; + bufferSize: boolean; + readonly ip: string; + restByteCount: number | undefined; + secure: boolean; + + close(code: number, message: number): Promise; + login(username: string, password: string): Promise; + reply(options: number | Object, ...letters: Array): Promise; } export interface FtpServerOptions { - url?: string, - pasv_min?: number, - pasv_max?: number, - pasv_url?: string, - greeting?: string | string[], - tls?: tls.SecureContextOptions | false, - anonymous?: boolean, - blacklist?: Array, - whitelist?: Array, - file_format?: (stat: Stats) => string | Promise | "ls" | "ep", - log?: any, - timeout?: number + url?: string; + pasv_min?: number; + pasv_max?: number; + pasv_url?: string; + greeting?: string | string[]; + tls?: tls.SecureContextOptions | false; + anonymous?: boolean; + blacklist?: Array; + whitelist?: Array; + file_format?: (stat: Stats) => string | Promise | "ls" | "ep"; + log?: any; + timeout?: number; } export class FtpServer extends EventEmitter { - constructor(options?: FtpServerOptions); - - readonly isTLS: boolean; - - listen(): any; - - emitPromise(action: any, ...data: any[]): Promise; - - // emit is exported from super class - - setupTLS(_tls: boolean): boolean | { - cert: string; - key: string; - ca: string - }; - - setupGreeting(greet: string): string[]; - - setupFeaturesMessage(): string; - - disconnectClient(id: string): Promise; - - close(): any; - - on(event: "login", listener: ( - data: { - connection: FtpConnection, - username: string, - password: string - }, - resolve: (config: { - fs?: FileSystem, - root?: string, - cwd?: string, - blacklist?: Array, - whitelist?: Array - }) => void, - reject: (err?: Error) => void - ) => void): this; - - on(event: "disconnect", listener: ( - data: { - connection: FtpConnection, - id: string - } - ) => void): this; - - on(event: "client-error", listener: ( - data: { - connection: FtpConnection, - context: string, - error: Error, - } - ) => void): this; + constructor(options?: FtpServerOptions); + + readonly isTLS: boolean; + + listen(): any; + + emitPromise(action: any, ...data: any[]): Promise; + + // emit is exported from super class + + setupTLS(_tls: boolean): + | boolean + | { + cert: string; + key: string; + ca: string; + }; + + setupGreeting(greet: string): string[]; + + setupFeaturesMessage(): string; + + disconnectClient(id: string): Promise; + + close(): any; + + on( + event: "login", + listener: ( + data: { + connection: FtpConnection; + username: string; + password: string; + }, + resolve: (config: { + fs?: FileSystem; + root?: string; + cwd?: string; + blacklist?: Array; + whitelist?: Array; + }) => void, + reject: (err?: Error) => void + ) => void + ): this; + + on( + event: "disconnect", + listener: (data: { connection: FtpConnection; id: string }) => void + ): this; + + on( + event: "client-error", + listener: (data: { + connection: FtpConnection; + context: string; + error: Error; + }) => void + ): this; } -export {FtpServer as FtpSrv}; +export { FtpServer as FtpSrv }; export default FtpServer; From 90b61fcbdf6cb6db35be8cdc75c61e585979403b Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Sat, 24 Aug 2024 21:18:42 +0800 Subject: [PATCH 4/4] feat: revise ftp-srv.d.ts support connect --- ftp-srv.d.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ftp-srv.d.ts b/ftp-srv.d.ts index 2bc5556..60b9c2e 100644 --- a/ftp-srv.d.ts +++ b/ftp-srv.d.ts @@ -166,9 +166,14 @@ export class FtpServer extends EventEmitter { ) => void ): this; + on( + event: "connect", + listener: (data: { connection: FtpConnection; id: string; newConnectionCount: number }) => void + ): this; + on( event: "disconnect", - listener: (data: { connection: FtpConnection; id: string }) => void + listener: (data: { connection: FtpConnection; id: string; newConnectionCount: number }) => void ): this; on(