This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git
The following commit(s) were added to refs/heads/main by this push:
new 144214cbd feat(binding/nodejs): align list api (#3784)
144214cbd is described below
commit 144214cbd1cbabf1387fde7c8a2b266c94d7f4b6
Author: Suyan <[email protected]>
AuthorDate: Wed Dec 20 20:39:39 2023 +0800
feat(binding/nodejs): align list api (#3784)
---
bindings/nodejs/generated.d.ts | 102 +++++++++++---------------
bindings/nodejs/src/lib.rs | 161 +++++++++++++++++++----------------------
bindings/nodejs/upgrade.md | 7 ++
3 files changed, 121 insertions(+), 149 deletions(-)
diff --git a/bindings/nodejs/generated.d.ts b/bindings/nodejs/generated.d.ts
index 9f45b248d..cb9e5e2fc 100644
--- a/bindings/nodejs/generated.d.ts
+++ b/bindings/nodejs/generated.d.ts
@@ -28,6 +28,10 @@ export class ExternalObject<T> {
[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<Lister>
- /**
- * 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<Lister>
+ list(path: string, options?: ListOptions | undefined | null):
Promise<Array<Entry>>
/**
* 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<Entry>
/**
* Get a presigned request for read.
*
diff --git a/bindings/nodejs/src/lib.rs b/bindings/nodejs/src/lib.rs
index ee05ee2cf..f88a4d69f 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<Lister> {
- 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<BlockingLister> {
- 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<Lister> {
- Ok(Lister(
- self.0.lister(&path).await.map_err(format_napi_error)?,
- ))
+ pub async fn list(&self, path: String, options: Option<ListOptions>) ->
Result<Vec<Entry>> {
+ 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<BlockingLister> {
- Ok(BlockingLister(
- self.0
- .blocking()
- .lister_with(&path)
- .call()
- .map_err(format_napi_error)?,
- ))
+ pub fn list_sync(&self, path: String, options: Option<ListOptions>) ->
Result<Vec<Entry>> {
+ 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<u32>,
+ pub recursive: Option<bool>,
+}
+
/// 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 749610fdb..f697f599c 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<Entry>` 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')`.