Skip to content
This repository was archived by the owner on Jul 30, 2024. It is now read-only.

Add Fs.opendir and Fs.Dir #165

Merged
merged 1 commit into from
Feb 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions app/current/src/main/scala/io/scalajs/nodejs/fs/Fs.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.scalajs.nodejs
package fs

import com.thoughtworks.enableIf
import com.thoughtworks.{enableIf, enableMembersIf}
import io.scalajs.nodejs.buffer.Buffer
import io.scalajs.nodejs.events.IEventEmitter

Expand Down Expand Up @@ -559,6 +559,15 @@ trait Fs extends IEventEmitter with FSConstants {
@enableIf(io.scalajs.nodejs.internal.CompilerSwitches.gteNodeJs12)
def openSync(path: Path): FileDescriptor = js.native

@enableIf(io.scalajs.nodejs.internal.CompilerSwitches.gteNodeJs12)
def opendir(path: Path, options: OpendirOptions, callback: FsCallback1[Fs.Dir]): Unit = js.native

@enableIf(io.scalajs.nodejs.internal.CompilerSwitches.gteNodeJs12)
def opendir(path: Path, callback: FsCallback1[Fs.Dir]): Unit = js.native

@enableIf(io.scalajs.nodejs.internal.CompilerSwitches.gteNodeJs12)
def opendirSync(path: Path, options: OpendirOptions = js.native): Fs.Dir = js.native

/**
* Read data from the file specified by fd.
* @param fd is the file descriptor
Expand Down Expand Up @@ -1138,7 +1147,9 @@ object Fs extends Fs {
def mkdtemp(prefix: String, encoding: String = js.native): js.Promise[String] = js.native
def open(path: Path, flags: Flags, mode: FileMode = js.native): js.Promise[FileHandle] = js.native
@enableIf(io.scalajs.nodejs.internal.CompilerSwitches.gteNodeJs12)
def open(path: Path): js.Promise[FileHandle] = js.native
def open(path: Path): js.Promise[FileHandle] = js.native
@enableIf(io.scalajs.nodejs.internal.CompilerSwitches.gteNodeJs12)
def opendir(path: Path, options: OpendirOptions = js.native): js.Promise[Dir] = js.native
def readdir(path: Path, options: ReaddirOptions): js.Promise[js.Array[String] | js.Array[Dirent]] = js.native
def readdir(path: Path, options: String | FileEncodingOptions = js.native): js.Promise[js.Array[String]] = js.native
def readlink(path: Path): js.Promise[String] = js.native
Expand Down Expand Up @@ -1206,6 +1217,20 @@ object Fs extends Fs {
def isSymbolicLink(): Boolean = js.native
val name: String | Buffer = js.native
}

@enableMembersIf(io.scalajs.nodejs.internal.CompilerSwitches.gteNodeJs12)
@js.native
trait Dir extends js.Object {
def close(): js.Promise[Unit] = js.native
def close(callback: js.Function1[js.Error, Any]): Unit = js.native
def closeSync(): Unit = js.native
def path: String = js.native
def read(): js.Promise[Dirent] = js.native
def read(callback: js.Function2[js.Error, Dirent, Any]): Unit = js.native
def readSync(): Dirent = js.native

// TODO: Implement AsyncIterable[Dirent]
}
}

@js.native
Expand All @@ -1231,6 +1256,9 @@ class ReaddirOptions(var encoding: js.UndefOr[String] = js.undefined,
var withFileTypes: js.UndefOr[Boolean] = js.undefined)
extends js.Object

class OpendirOptions(var encoding: js.UndefOr[String] = js.undefined, var bufferSize: js.UndefOr[Double] = js.undefined)
extends js.Object

class ReadFileOptions(var flag: js.UndefOr[String] = js.undefined) extends js.Object

class FileInputOptions(var flags: js.UndefOr[String] = js.undefined,
Expand Down
36 changes: 36 additions & 0 deletions app/current/src/main/scala/io/scalajs/nodejs/fs/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ package object fs {

/**
* File System Extensions
*
* @param instance the given [[Fs file system]] instance
*/
implicit final class FsExtensions(private val instance: Fs) extends AnyVal {
Expand Down Expand Up @@ -194,6 +195,18 @@ package object fs {
promiseWithError1[FileIOError, FileDescriptor](instance.open(path, _))
}

@enableIf(io.scalajs.nodejs.internal.CompilerSwitches.gteNodeJs12)
@inline
def opendirFuture(path: Path, options: OpendirOptions): Future[Fs.Dir] = {
promiseWithError1[FileIOError, Fs.Dir](instance.opendir(path, options, _))
}

@enableIf(io.scalajs.nodejs.internal.CompilerSwitches.gteNodeJs12)
@inline
def opendirFuture(path: Path): Future[Fs.Dir] = {
promiseWithError1[FileIOError, Fs.Dir](instance.opendir(path, _))
}

@inline
def readFuture(fd: FileDescriptor,
buffer: Buffer,
Expand Down Expand Up @@ -447,4 +460,27 @@ package object fs {
)
}
}

/**
* Dir Extensions
*
* @param instance the given [[Fs.Dir]] instance
*/
implicit final class FsDirExtensions(private val instance: Fs.Dir) extends AnyVal {
@enableIf(io.scalajs.nodejs.internal.CompilerSwitches.gteNodeJs12)
@inline
def readFuture(): Future[Option[Fs.Dirent]] = {
promiseWithError1[js.Error, Option[Fs.Dirent]](f => {
instance.read((err, dir) => {
f(err, Option(dir))
})
})
}

@enableIf(io.scalajs.nodejs.internal.CompilerSwitches.gteNodeJs12)
@inline
def closeFuture(): Future[Unit] = {
promiseWithError0[js.Error](instance.close _)
}
}
}
21 changes: 21 additions & 0 deletions app/current/src/test/scala/io/scalajs/nodejs/fs/FsAsyncTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import org.scalatest.BeforeAndAfterEach
import scala.concurrent.ExecutionContext
import org.scalatest.funspec.AsyncFunSpec

import scala.scalajs.js.JavaScriptException

class FsAsyncTest extends AsyncFunSpec with BeforeAndAfterEach {
override implicit val executionContext = ExecutionContext.Implicits.global

Expand Down Expand Up @@ -54,5 +56,24 @@ class FsAsyncTest extends AsyncFunSpec with BeforeAndAfterEach {
assert(!dirExistsAfterRmdir)
}
}

it("support opendir") {
for {
dir <- Fs.opendirFuture("core/src")
maybeFirstEntry <- dir.readFuture()
maybeSecondEntry <- dir.readFuture()
_ <- dir.closeFuture()
} yield {
assert(dir.path === "core/src")
assert(maybeFirstEntry.map(_.name) === Some("main"))
assert(maybeSecondEntry === None)

val ex = intercept[JavaScriptException] {
assert(dir.readSync() === null)
}
assert(ex.getMessage().contains("ERR_DIR_CLOSED"))
}
}

}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package io.scalajs.nodejs.fs

import io.scalajs.nodejs.fs
import org.scalatest.funspec.AnyFunSpec

import scala.scalajs.js.JavaScriptException

/**
* File System (Fs) Tests
*
Expand All @@ -12,4 +15,22 @@ class FsClassesTest extends AnyFunSpec {
assert(new ReadStream("package.json").pending)
}
}

describe("opendir") {
it("returns Dir") {
val dir = fs.Fs.opendirSync("core/src")
assert(dir.path === "core/src")
val firstEntry = dir.readSync()
assert(firstEntry.name === "main")
assert(firstEntry.isDirectory())

assert(dir.readSync() === null)

dir.closeSync()
val ex = intercept[JavaScriptException] {
assert(dir.readSync() === null)
}
assert(ex.getMessage().contains("ERR_DIR_CLOSED"))
}
}
}