Skip to content

Commit

Permalink
feat: implement statSync, writeFileSync (#278)
Browse files Browse the repository at this point in the history
Refs: #249
  • Loading branch information
fredbonin committed Mar 18, 2024
1 parent c838c96 commit 49b8a75
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 16 deletions.
2 changes: 2 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ Available globally
[readFileSync](https://nodejs.org/api/fs.html#fsreadfilesyncpath-options)
[rmdirSync](https://nodejs.org/api/fs.html#fsrmdirsyncpath-options)
[rmSync](https://nodejs.org/api/fs.html#fsrmsyncpath-options)
[statSync](https://nodejs.org/api/fs.html#fsstatsyncpath-options)
[writeFileSync](https://nodejs.org/api/fs.html#fswritefilesyncfile-data-options)

## fs/promises

Expand Down
6 changes: 6 additions & 0 deletions src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ use self::stats::{stat_fn, Stat};
use self::write_file::write_file;
use crate::fs::mkdir::{mkdir, mkdir_sync, mkdtemp, mkdtemp_sync};
use crate::fs::rm::{rmdir_sync, rmfile_sync};
use crate::fs::stats::stat_fn_sync;
use crate::fs::write_file::write_file_sync;

pub const CONSTANT_F_OK: u32 = 0;
pub const CONSTANT_R_OK: u32 = 4;
Expand Down Expand Up @@ -79,6 +81,8 @@ impl ModuleDef for FsModule {
declare.declare("readFileSync")?;
declare.declare("rmdirSync")?;
declare.declare("rmSync")?;
declare.declare("statSync")?;
declare.declare("writeFileSync")?;

declare.declare("default")?;

Expand All @@ -101,6 +105,8 @@ impl ModuleDef for FsModule {
default.set("readFileSync", Func::from(read_file_sync))?;
default.set("rmdirSync", Func::from(rmdir_sync))?;
default.set("rmSync", Func::from(rmfile_sync))?;
default.set("statSync", Func::from(stat_fn_sync))?;
default.set("writeFileSync", Func::from(write_file_sync))?;

Ok(())
})
Expand Down
9 changes: 9 additions & 0 deletions src/fs/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,12 @@ pub async fn stat_fn(ctx: Ctx<'_>, path: String) -> Result<Stat> {

Ok(stats)
}

pub fn stat_fn_sync(ctx: Ctx<'_>, path: String) -> Result<Stat> {
let metadata =
std::fs::metadata(&path).or_throw_msg(&ctx, &format!("Can't stat \"{}\"", &path))?;

let stats = Stat::new(metadata);

Ok(stats)
}
8 changes: 8 additions & 0 deletions src/fs/write_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ pub async fn write_file<'js>(ctx: Ctx<'js>, path: String, data: Value<'js>) -> R

Ok(())
}

pub fn write_file_sync<'js>(ctx: Ctx<'js>, path: String, data: Value<'js>) -> Result<()> {
let bytes = get_bytes(&ctx, data)?;

std::fs::write(&path, bytes).or_throw_msg(&ctx, &format!("Can't write \"{}\"", &path))?;

Ok(())
}
45 changes: 29 additions & 16 deletions tests/unit/fs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,24 +164,21 @@ describe("mkdtemp", () => {
});

describe("mkdtempSync", () => {
it("should create a temporary directory with a given prefix synchronously", async () => {
it("should create a temporary directory with a given prefix synchronously", () => {
// Create a temporary directory with the given prefix
const prefix = "test-";
const dirPath = defaultFsImport.mkdtempSync(path.join(os.tmpdir(), prefix));

// Check that the directory exists
const dirExists = await fs
.stat(dirPath)
.then(() => true)
.catch(() => false);
const dirExists = defaultFsImport.statSync(dirPath)
expect(dirExists).toBeTruthy();

// Check that the directory has the correct prefix
const dirPrefix = path.basename(dirPath).slice(0, prefix.length);
expect(dirPrefix).toStrictEqual(prefix);

// Clean up the temporary directory
await defaultFsImport.rmdirSync(dirPath);
defaultFsImport.rmdirSync(dirPath);
});
});

Expand All @@ -207,7 +204,7 @@ describe("mkdir", () => {
});

describe("mkdirSync", () => {
it("should create a directory with the given path synchronously", async () => {
it("should create a directory with the given path synchronously", () => {
const dirPath = defaultFsImport.mkdtempSync(
path.join(os.tmpdir(), "test/test-")
);
Expand All @@ -218,10 +215,7 @@ describe("mkdirSync", () => {
defaultFsImport.mkdirSync(dirPath, { recursive: true });

// Check that the directory exists
const dirExists = await fs
.stat(dirPath)
.then(() => true)
.catch(() => false);
const dirExists = defaultFsImport.statSync(dirPath)
expect(dirExists).toBeTruthy();

// Clean up the directory
Expand All @@ -244,6 +238,21 @@ describe("writeFile", () => {
});
});

describe("writeFile synchronously", () => {
it("should write a file", () => {
const tmpDir = defaultFsImport.mkdtempSync(path.join(os.tmpdir(), "test-"));
const filePath = path.join(tmpDir, "test");
const fileContents = "hello";
defaultFsImport.writeFileSync(filePath, fileContents);

const contents = defaultFsImport.readFileSync(filePath).toString();

expect(fileContents).toEqual(contents);

defaultFsImport.rmdirSync(tmpDir, { recursive: true });
});
});

describe("rm", () => {
it("should delete file and directory", async () => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "test-"));
Expand All @@ -257,14 +266,14 @@ describe("rm", () => {
// Should delete file
await fs.rm(filePath, { recursive: true });
await expect(fs.access(filePath)).rejects.toThrow(
/[Nn]o such file or directory/
/[Nn]o such file or directory/
);

// Check dir still exists and then delete it
await fs.access(tmpDir);
await fs.rm(tmpDir, { recursive: true });
await expect(fs.access(filePath)).rejects.toThrow(
/[Nn]o such file or directory/
/[Nn]o such file or directory/
);
});
it("should throw an error if file does not exists", async () => {
Expand All @@ -280,7 +289,7 @@ describe("rm", () => {
const filePath = path.join(tmpDir, "test");

await expect(fs.access(filePath)).rejects.toThrow(
/[Nn]o such file or directory/
/[Nn]o such file or directory/
);

// Should not throw an exception since it does not exists
Expand Down Expand Up @@ -340,12 +349,16 @@ describe("access", () => {

it("should throw if not proper permissions", async () => {
const filePath = "fixtures/hello.txt";
await expect(fs.access(filePath, fs.constants.X_OK)).rejects.toThrow(/[pP]ermission denied/);
await expect(fs.access(filePath, fs.constants.X_OK)).rejects.toThrow(
/[pP]ermission denied/
);
});

it("should throw if not exists", async () => {
const filePath = "fixtures/nothing";
await expect(fs.access(filePath)).rejects.toThrow(/[nN]o such file or directory/);
await expect(fs.access(filePath)).rejects.toThrow(
/[nN]o such file or directory/
);
});

it("should access a file using default import", async () => {
Expand Down

0 comments on commit 49b8a75

Please sign in to comment.