diff --git a/bindings/nodejs/generated.d.ts b/bindings/nodejs/generated.d.ts index 9f45b248d15b..cb9e5e2fc502 100644 --- a/bindings/nodejs/generated.d.ts +++ b/bindings/nodejs/generated.d.ts @@ -28,6 +28,10 @@ export class ExternalObject { [K: symbol]: T } } +export interface ListOptions { + limit?: number + recursive?: boolean +} /** PresignedRequest is a presigned request return by `presign`. */ export interface PresignedRequest { /** HTTP method of this request. */ @@ -349,53 +353,6 @@ export class Operator { * ``` */ renameSync(from: string, to: string): void - /** - * List dir in flat way. - * - * This function will create a new handle to list entries. - * - * An error will be returned if given path doesn't end with /. - * - * ### Example - * - * ```javascript - * const lister = await op.scan("/path/to/dir/"); - * while (true) { - * const entry = await lister.next(); - * if (entry === null) { - * break; - * } - * let meta = await op.stat(entry.path); - * if (meta.is_file) { - * // do something - * } - * } - * ````` - */ - scan(path: string): Promise - /** - * List dir in flat way synchronously. - * - * This function will create a new handle to list entries. - * - * An error will be returned if given path doesn't end with /. - * - * ### Example - * ```javascript - * const lister = op.scan_sync(/path/to/dir/"); - * while (true) { - * const entry = lister.next(); - * if (entry === null) { - * break; - * } - * let meta = op.statSync(entry.path); - * if (meta.is_file) { - * // do something - * } - * } - * ````` - */ - scanSync(path: string): BlockingLister /** * Delete the given path. * @@ -444,41 +401,64 @@ export class Operator { /** * List given path. * - * This function will create a new handle to list entries. + * This function will return an array of entries. * * An error will be returned if given path doesn't end with `/`. * * ### Example + * * ```javascript - * const lister = await op.list("path/to/dir/"); - * while (true) { - * const entry = await lister.next(); - * if (entry === null) { - * break; + * const list = await op.list("path/to/dir/"); + * for (let entry of list) { + * let meta = await op.stat(entry.path); + * if (meta.isFile) { + * // do something * } + * } + * ``` + * + * #### List recursively + * + * With `recursive` option, you can list recursively. + * + * ```javascript + * const list = await op.list("path/to/dir/", { recursive: true }); + * for (let entry of list) { * let meta = await op.stat(entry.path); * if (meta.isFile) { * // do something * } * } * ``` + * */ - list(path: string): Promise + list(path: string, options?: ListOptions | undefined | null): Promise> /** * List given path synchronously. * - * This function will create a new handle to list entries. + * This function will return a array of entries. * * An error will be returned if given path doesn't end with `/`. * * ### Example + * * ```javascript - * const lister = op.listSync("path/to/dir/"); - * while (true) { - * const entry = lister.next(); - * if (entry === null) { - * break; + * const list = op.listSync("path/to/dir/"); + * for (let entry of list) { + * let meta = op.statSync(entry.path); + * if (meta.isFile) { + * // do something * } + * } + * ``` + * + * #### List recursively + * + * With `recursive` option, you can list recursively. + * + * ```javascript + * const list = op.listSync("path/to/dir/", { recursive: true }); + * for (let entry of list) { * let meta = op.statSync(entry.path); * if (meta.isFile) { * // do something @@ -486,7 +466,7 @@ export class Operator { * } * ``` */ - listSync(path: string): BlockingLister + listSync(path: string, options?: ListOptions | undefined | null): Array /** * Get a presigned request for read. * diff --git a/bindings/nodejs/src/lib.rs b/bindings/nodejs/src/lib.rs index ee05ee2cf457..f88a4d69fe4c 100644 --- a/bindings/nodejs/src/lib.rs +++ b/bindings/nodejs/src/lib.rs @@ -341,70 +341,6 @@ impl Operator { .map_err(format_napi_error) } - /// List dir in flat way. - /// - /// This function will create a new handle to list entries. - /// - /// An error will be returned if given path doesn't end with /. - /// - /// ### Example - /// - /// ```javascript - /// const lister = await op.scan("/path/to/dir/"); - /// while (true) { - /// const entry = await lister.next(); - /// if (entry === null) { - /// break; - /// } - /// let meta = await op.stat(entry.path); - /// if (meta.is_file) { - /// // do something - /// } - /// } - /// ````` - #[napi] - pub async fn scan(&self, path: String) -> Result { - Ok(Lister( - self.0 - .lister_with(&path) - .recursive(true) - .await - .map_err(format_napi_error)?, - )) - } - - /// List dir in flat way synchronously. - /// - /// This function will create a new handle to list entries. - /// - /// An error will be returned if given path doesn't end with /. - /// - /// ### Example - /// ```javascript - /// const lister = op.scan_sync(/path/to/dir/"); - /// while (true) { - /// const entry = lister.next(); - /// if (entry === null) { - /// break; - /// } - /// let meta = op.statSync(entry.path); - /// if (meta.is_file) { - /// // do something - /// } - /// } - /// ````` - #[napi] - pub fn scan_sync(&self, path: String) -> Result { - Ok(BlockingLister( - self.0 - .blocking() - .lister_with(&path) - .recursive(true) - .call() - .map_err(format_napi_error)?, - )) - } - /// Delete the given path. /// /// ### Notes @@ -460,45 +396,80 @@ impl Operator { /// List given path. /// - /// This function will create a new handle to list entries. + /// This function will return an array of entries. /// /// An error will be returned if given path doesn't end with `/`. /// /// ### Example + /// /// ```javascript - /// const lister = await op.list("path/to/dir/"); - /// while (true) { - /// const entry = await lister.next(); - /// if (entry === null) { - /// break; + /// const list = await op.list("path/to/dir/"); + /// for (let entry of list) { + /// let meta = await op.stat(entry.path); + /// if (meta.isFile) { + /// // do something /// } + /// } + /// ``` + /// + /// #### List recursively + /// + /// With `recursive` option, you can list recursively. + /// + /// ```javascript + /// const list = await op.list("path/to/dir/", { recursive: true }); + /// for (let entry of list) { /// let meta = await op.stat(entry.path); /// if (meta.isFile) { /// // do something /// } /// } /// ``` + /// #[napi] - pub async fn list(&self, path: String) -> Result { - Ok(Lister( - self.0.lister(&path).await.map_err(format_napi_error)?, - )) + pub async fn list(&self, path: String, options: Option) -> Result> { + let mut l = self.0.list_with(&path); + if let Some(options) = options { + if let Some(limit) = options.limit { + l = l.limit(limit as usize); + } + if let Some(recursive) = options.recursive { + l = l.recursive(recursive); + } + } + + Ok(l.await + .map_err(format_napi_error)? + .iter() + .map(|e| Entry(e.to_owned())) + .collect()) } /// List given path synchronously. /// - /// This function will create a new handle to list entries. + /// This function will return a array of entries. /// /// An error will be returned if given path doesn't end with `/`. /// /// ### Example + /// /// ```javascript - /// const lister = op.listSync("path/to/dir/"); - /// while (true) { - /// const entry = lister.next(); - /// if (entry === null) { - /// break; + /// const list = op.listSync("path/to/dir/"); + /// for (let entry of list) { + /// let meta = op.statSync(entry.path); + /// if (meta.isFile) { + /// // do something /// } + /// } + /// ``` + /// + /// #### List recursively + /// + /// With `recursive` option, you can list recursively. + /// + /// ```javascript + /// const list = op.listSync("path/to/dir/", { recursive: true }); + /// for (let entry of list) { /// let meta = op.statSync(entry.path); /// if (meta.isFile) { /// // do something @@ -506,14 +477,22 @@ impl Operator { /// } /// ``` #[napi] - pub fn list_sync(&self, path: String) -> Result { - Ok(BlockingLister( - self.0 - .blocking() - .lister_with(&path) - .call() - .map_err(format_napi_error)?, - )) + pub fn list_sync(&self, path: String, options: Option) -> Result> { + let mut l = self.0.blocking().list_with(&path); + if let Some(options) = options { + if let Some(limit) = options.limit { + l = l.limit(limit as usize); + } + if let Some(recursive) = options.recursive { + l = l.recursive(recursive); + } + } + + Ok(l.call() + .map_err(format_napi_error)? + .iter() + .map(|e| Entry(e.to_owned())) + .collect()) } /// Get a presigned request for read. @@ -656,6 +635,12 @@ impl Metadata { } } +#[napi(object)] +pub struct ListOptions { + pub limit: Option, + pub recursive: Option, +} + /// BlockingReader is designed to read data from given path in an blocking /// manner. #[napi] diff --git a/bindings/nodejs/upgrade.md b/bindings/nodejs/upgrade.md index 749610fdb2c6..f697f599c480 100644 --- a/bindings/nodejs/upgrade.md +++ b/bindings/nodejs/upgrade.md @@ -2,4 +2,11 @@ ## Breaking change +### Services + Because of [a TLS lib issue](https://github.com/apache/incubator-opendal/issues/3650), we temporarily disable the `services-ftp` feature. + +### Public API + +Now, the `list` operation returns `Array` instead of a lister. +Also, we removed `scan`, you can use `list('some/path', {recursive: true})`/`listSync('some/path', {recursive: true})` instead of `scan('some/path')`/`scanSync('some/path')`.