Skip to content
Open
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
87 changes: 46 additions & 41 deletions scripting/node-fs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Currently the file directory is composed of two folder:
└── tmp/ # Temporary directory, R/W access
```

You can create directories where you want as permissions are not enforced yet.
You can create directories anywhere. Permissions are enforced for the owner (user) but not for group or others.
All files are opened in `w+`.

<Info>
Expand Down Expand Up @@ -99,62 +99,34 @@ behave differently from traditional Node.js environments.

### Symbolic Links and Hard Links

Symbolic links and hard links are not supported in the EdgeScripting runtime
yet.
Symbolic links are supported. `symlink()`, `symlinkSync()`, `readlink()`, `readlinkSync()`, and `lstat()` work as expected.

<Warning>
The following operations will throw errors or behave unexpectedly:
- `symlink()`, `symlinkSync()` - Creating symbolic links
- `readlink()`, `readlinkSync()` - Reading symbolic links
- `link()`, `linkSync()` - Creating hard links
- `lstat()` may not distinguish between files and symlinks correctly
Hard links are not supported. `link()` and `linkSync()` will throw errors.
</Warning>

**Workaround:** Use `copyFile()` instead of creating links, or restructure
your application to avoid link dependencies.

### File Statistics - Timestamps

File modification and access times are not reliably available yet.

<Warning>
The following `Stats` object properties may return incorrect or placeholder values:
- `atime` - Last access time
- `mtime` - Last modification time
- `ctime` - Last status change time
- `atimeMs`, `mtimeMs`, `ctimeMs` - Millisecond timestamps
- `birthtime`, `birthtimeMs` - File creation time
</Warning>
All `Stats` timestamp properties are supported and return correct values:

**Reliable Stats properties:**
- `size` - File size in bytes
- `isFile()` - Check if entry is a file
- `isDirectory()` - Check if entry is a directory

**Example of unreliable usage:**
```typescript
// DON'T rely on timestamps
const stats = await fs.stat("file.txt");
console.log(stats.mtime); // May be incorrect!

// DO rely on size and type checks
console.log(stats.size); // Reliable
console.log(stats.isFile()); // Reliable
```
- `atime` - Last access time
- `mtime` - Last modification time
- `ctime` - Last status change time
- `atimeMs`, `mtimeMs`, `ctimeMs` - Millisecond timestamps
- `birthtime` - File creation time

### File and Directory Permissions

All files and directories effectively have read/write permissions in the
sandboxed environment (`644`) and are owned by the current (non root) user
(uid=1000, gid=1000).
File and directory permissions are supported for the **owner (user)** bits. `chmod()` and `chmodSync()` work, and `Stats.mode` reflects the permissions you set. `access()` respects owner-level read, write, and execute bits.

<Info>
Permission-related operations have limited effect:
- `chmod()`, `chmodSync()` - Not supported
- `chown()`, `chownSync()` - Not supported
- `Stats.mode` - Won't reflect actual permissions
- Permission checks via `access()` - Will mostly tell you if a file exists or
not.
**Group and others** permission bits are accepted but have no effect: the sandboxed environment always runs as the file owner (uid=1000, gid=1000), so only the user/owner bits matter.

`chown()` and `chownSync()` have no effect; ownership is fixed to uid=1000, gid=1000.
</Info>


Expand Down Expand Up @@ -466,6 +438,39 @@ BunnySDK.net.http.serve(async (request: Request) => {
});
```

### Example 6: Symbolic Links

```typescript
import * as fs from "node:fs/promises";
import * as BunnySDK from "@bunny.net/edgescript-sdk";

BunnySDK.net.http.serve(async (request: Request) => {
const original = "/tmp/original.txt";
const link = "/tmp/link.txt";

try {
await fs.writeFile(original, "hello from original", "utf-8");

// Create a symbolic link pointing to the original file
await fs.symlink(original, link);

// Reading through the symlink is transparent
const content = await fs.readFile(link, "utf-8");

// lstat inspects the link itself, not the target
const linkStats = await fs.lstat(link);
const target = await fs.readlink(link);

return new Response(
JSON.stringify({ content, isSymlink: linkStats.isSymbolicLink(), target }),
{ headers: { "content-type": "application/json" } }
);
} catch (error) {
return new Response(`Error: ${error.message}`, { status: 500 });
}
});
```

## References

- [Node.js File System Documentation](https://nodejs.org/api/fs.html) - Complete Node.js fs module reference
Expand Down