Fs.FileWrite
eff FileWriteSourceAn effect used to write files, append to files, truncate files, and create directories.
Operations
def append(data: { str = String }, f: String): Result[IoError, Unit] \ FileWrite
SourceAppends str to the given file f.
Creates the file f if it does not exist.
def appendBytes(data: Vector[Int8], f: String): Result[IoError, Unit] \ FileWrite
SourceAppends data to the given file f.
Creates the file f if it does not exist.
def appendLines(data: { lines = List[String] }, f: String): Result[IoError, Unit] \ FileWrite
SourceAppends lines to the given file f.
Creates the file f if it does not exist.
def copyWith(src: { src = String }, dst: String, opts: Set[CopyOption]): Result[IoError, Unit] \ FileWrite
SourceCopies the file src to dst with the given options.
def delete(f: String): Result[IoError, Unit] \ FileWrite
SourceDeletes the given file f.
Fails if the file does not exist.
def mkDir(d: String): Result[IoError, Unit] \ FileWrite
SourceCreates the directory d.
def mkDirs(d: String): Result[IoError, Unit] \ FileWrite
SourceCreates the directory d and all its parent directories.
def mkTempDir(prefix: String): Result[IoError, String] \ FileWrite
SourceCreates a new temporary directory with the given prefix.
Returns the path to the directory.
def moveWith(src: { src = String }, dst: String, opts: Set[MoveOption]): Result[IoError, Unit] \ FileWrite
SourceMoves (renames) the file or directory src to dst with the given options.
def truncate(f: String): Result[IoError, Unit] \ FileWrite
SourceTruncates the given file f.
def write(data: { str = String }, f: String): Result[IoError, Unit] \ FileWrite
SourceWrites str to the given file f.
Creates file f if it does not exist. Overwrites it if it exists.
def writeBytes(data: Vector[Int8], f: String): Result[IoError, Unit] \ FileWrite
SourceWrites data to the given file f.
Creates file f if it does not exist. Overwrites it if it exists.
def writeLines(data: { lines = List[String] }, f: String): Result[IoError, Unit] \ FileWrite
SourceWrites lines to the given file f.
Creates f if it does not exist. Overwrites it if it exists.
Definitions
def copy(src: { src = String }, dst: String): Result[IoError, Unit] \ FileWrite
SourceConvenience function: copies src to dst with no options.
def handle(f: a -> b \ ef): a -> b \ (ef - FileWrite) + IO
SourceHandles the FileWrite effect of the given function f.
In other words, re-interprets the FileWrite effect using the IO effect.
def move(src: { src = String }, dst: String): Result[IoError, Unit] \ FileWrite
SourceConvenience function: moves src to dst with no options.
def runWithFileSystem(f: Unit -> a \ ef): a \ (ef - FileWrite) + FileSystem
SourceHandles the FileWrite effect of the given function f using the FileSystem effect.
@DefaultHandler def runWithIO(f: Unit -> a \ ef): a \ (ef - FileWrite) + IO
SourceRuns the FileWrite effect of the given function f.
In other words, re-interprets the FileWrite effect using the IO effect.
def withAllowGlob(patterns: Nel[String], f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite
SourceMiddleware that intercepts the FileWrite effect, validating that all file paths
match at least one of the given glob patterns. Rejects paths that do not match
with a PermissionDenied error.
The mkTempDir operation is blocked since the temp directory location cannot be verified.
def withAllowList(allowedDirs: Nel[String], f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite
SourceMiddleware that intercepts the FileWrite effect, validating that all file paths
resolve within one of the given allowedDirs. Rejects paths outside the
allow list with a PermissionDenied error.
The mkTempDir operation is blocked since the temp directory location cannot be verified.
def withAtomicWrite(f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite
SourceMiddleware that intercepts the FileWrite effect, making write,
writeLines, and writeBytes atomic. Data is first written to a
temporary file in the same directory, then atomically moved into place.
On failure the temporary file is cleaned up.
All other operations (append, truncate, copy, move, delete, mkdir) are passed through unchanged.
def withBackup(suffix: String, f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite
SourceMiddleware that intercepts the FileWrite effect, creating a backup
of existing files before destructive operations. Before write,
writeLines, writeBytes, truncate, and delete, the existing
file is copied to file + suffix (e.g., "data.txt.bak" when
suffix is ".bak").
For copyWith and moveWith, the destination file is backed up.
If the file does not exist, no backup is created and the operation proceeds normally. If the backup fails for any other reason, the original operation is aborted and the backup error is returned.
If a backup file already exists, it is overwritten. Only the most recent previous version of each file is preserved.
Append, mkdir, and mkTempDir operations are passed through unchanged.
def withBaseDir(baseDir: String, f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite
SourceMiddleware that intercepts the FileWrite effect, resolving all file paths
relative to the given baseDir using Java's Path.resolve semantics.
Absolute paths are passed through unchanged. The mkTempDir prefix is not resolved.
def withChecksum(hash: Vector[Int8] -> Vector[Int8], sidecar: String, f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite + FileRead
SourceMiddleware that intercepts the FileWrite effect, computing checksums
after write operations and storing them as sidecar files.
hash is a pure function from file bytes to digest bytes.
sidecar is the file suffix (e.g., ".sha256").
After write, writeLines, writeBytes, append, appendLines,
appendBytes, truncate, and copyWith, the file is re-read and
its checksum sidecar is updated.
After moveWith, the source's sidecar is moved to the destination path.
After delete, the sidecar file is also removed.
mkDir, mkDirs, and mkTempDir are passed through unchanged.
def withChroot(chrootDir: String, f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite
SourceMiddleware that intercepts the FileWrite effect, validating that all file paths
resolve within the given chrootDir. Rejects paths that escape the chroot with
a PermissionDenied error.
The mkTempDir operation is blocked since it creates directories outside the chroot.
def withConflictCheck(f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite + FileStat
SourceMiddleware that intercepts the FileWrite effect, tracking file modification
times across writes and checking for external modifications before each write.
Before write, writeLines, writeBytes, append, appendLines,
appendBytes, and truncate, the file's current modification time is
compared against the last recorded snapshot. If they differ, a Conflict
error is returned. After a successful write, the modification time is
re-snapshotted for subsequent checks.
For copyWith and moveWith, the conflict check is applied to the
destination path.
After delete, the snapshot for that file is removed.
mkDir, mkDirs, and mkTempDir are passed through unchanged.
Note: Unlike the FileSystem version, this middleware does not snapshot
on read operations. Conflict detection begins after the first write to
each file, catching write-write conflicts from external processes.
def withDenyGlob(patterns: Nel[String], f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite
SourceMiddleware that intercepts the FileWrite effect, validating that all file paths
do not match any of the given glob patterns. Rejects paths that match a denied
pattern with a PermissionDenied error.
The mkTempDir operation is allowed since deny globs are default-allow.
def withDenyList(deniedDirs: Nel[String], f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite
SourceMiddleware that intercepts the FileWrite effect, validating that all file paths
do not resolve within any of the given deniedDirs. Rejects paths inside a
denied directory with a PermissionDenied error.
The mkTempDir operation is allowed since deny lists are default-allow.
def withDryRun(f: Unit -> a \ ef): a \ (ef - FileWrite) + Logger
SourceMiddleware that intercepts the FileWrite effect, logging each write
operation via the Logger effect at Debug level without performing
the actual filesystem modification. All write operations return Ok(());
mkTempDir returns Ok("<dry-run>").
def withFollowLinks(f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite
SourceMiddleware that intercepts the FileWrite effect, resolving all file paths
to their real filesystem targets by following symlinks.
Action ops (write, append, copy, etc.): resolve path with fallback to original.
mkTempDir: passed through unchanged (no path to resolve).
def withLogging(f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite + Logger
SourceMiddleware that intercepts the FileWrite effect, logging each operation
and its result via the Logger effect.
Successful operations are logged at Debug level; errors at Warn.
def withMkParentDirs(f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite
SourceMiddleware that intercepts the FileWrite effect, automatically creating
parent directories before write, append, copy, and move operations.
Before write, writeLines, writeBytes, append, appendLines,
appendBytes, copyWith, and moveWith, the parent directory of the
target file is created via mkDirs. If the parent directory already
exists, this is a no-op.
If parent directory creation fails, the original operation is aborted and the error is returned.
truncate, delete, mkDir, mkDirs, and mkTempDir are passed
through unchanged.
def withReadOnly(f: Unit -> a \ ef): a \ ef - FileWrite
SourceMiddleware that intercepts the FileWrite effect, blocking all write
operations with a PermissionDenied error. This is useful for
sandboxing code that should only observe the filesystem.
def withSizeRotation(maxSize: Size, maxFiles: Int32, f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite + FileStat
SourceMiddleware that intercepts the FileWrite effect, automatically rotating
files when they reach a size threshold before append operations.
Before append, appendLines, and appendBytes, the target file's size
is checked via FileStat.size. If it meets or exceeds maxSize, existing
rotated files are shifted (file.1 → file.2, etc.), the oldest
(file.{maxFiles}) is deleted, and the current file is moved to file.1.
The append then writes to the now-absent original path.
All other operations are passed through unchanged.
def withTransferLimit(maxSize: Size, f: Unit -> a \ ef): a \ (ef - FileWrite) + FileWrite + FileStat
SourceMiddleware that intercepts the FileWrite effect, rejecting write and
append operations where the payload exceeds maxBytes. For copyWith,
the source file size is checked via FileStat.size.
String-based operations estimate byte count as charCount * 4 (the
maximum bytes per character in UTF-8). Use writeBytes/appendBytes
for exact enforcement.
Operations that don't transfer data (truncate, moveWith, delete,
mkDir, mkDirs, mkTempDir) are passed through unchanged.