Skip to content

Commit

Permalink
feat(binding/nodejs): align list api (#3784)
Browse files Browse the repository at this point in the history
  • Loading branch information
suyanhanx authored Dec 20, 2023
1 parent e3070e6 commit 144214c
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 149 deletions.
102 changes: 41 additions & 61 deletions bindings/nodejs/generated.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -444,49 +401,72 @@ 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
* }
* }
* ```
*/
listSync(path: string): BlockingLister
listSync(path: string, options?: ListOptions | undefined | null): Array<Entry>
/**
* Get a presigned request for read.
*
Expand Down
161 changes: 73 additions & 88 deletions bindings/nodejs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -460,60 +396,103 @@ 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
/// }
/// }
/// ```
#[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.
Expand Down Expand Up @@ -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]
Expand Down
7 changes: 7 additions & 0 deletions bindings/nodejs/upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -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')`.

0 comments on commit 144214c

Please sign in to comment.