(fileSystem: Partial<FileSystem>): FileSystemCreates a stub FileSystem implementation for tests.
Details
By default, exists returns false, remove succeeds, many file operations
fail with PlatformError NotFound, and temporary-directory/file operations
die as not implemented. Pass method overrides to provide the behavior needed
by a specific test without touching the real file system.
Example (Creating a no-op FileSystem)
import { Effect, FileSystem, PlatformError } from "effect"
// Create a test filesystem that only allows reading specific files
const testFs = FileSystem.makeNoop({
readFileString: (path) => {
if (path === "test-config.json") {
return Effect.succeed("{\"test\": true}")
}
return Effect.fail(
PlatformError.systemError({
_tag: "NotFound",
module: "FileSystem",
method: "readFileString",
description: "File not found",
pathOrDescriptor: path
})
)
},
exists: (path) => Effect.succeed(path === "test-config.json")
})
// Use in tests
const program = Effect.gen(function*() {
const content = yield* testFs.readFileString("test-config.json")
// Will succeed with mocked content
})
// Test with the no-op filesystem
const testProgram = Effect.provideService(
program,
FileSystem.FileSystem,
testFs
)export const const makeNoop: (
fileSystem: Partial<FileSystem>
) => FileSystem
Creates a stub FileSystem implementation for tests.
Details
By default, exists returns false, remove succeeds, many file operations
fail with PlatformError NotFound, and temporary-directory/file operations
die as not implemented. Pass method overrides to provide the behavior needed
by a specific test without touching the real file system.
Example (Creating a no-op FileSystem)
import { Effect, FileSystem, PlatformError } from "effect"
// Create a test filesystem that only allows reading specific files
const testFs = FileSystem.makeNoop({
readFileString: (path) => {
if (path === "test-config.json") {
return Effect.succeed("{\"test\": true}")
}
return Effect.fail(
PlatformError.systemError({
_tag: "NotFound",
module: "FileSystem",
method: "readFileString",
description: "File not found",
pathOrDescriptor: path
})
)
},
exists: (path) => Effect.succeed(path === "test-config.json")
})
// Use in tests
const program = Effect.gen(function*() {
const content = yield* testFs.readFileString("test-config.json")
// Will succeed with mocked content
})
// Test with the no-op filesystem
const testProgram = Effect.provideService(
program,
FileSystem.FileSystem,
testFs
)
makeNoop = (fileSystem: Partial<FileSystem>fileSystem: type Partial<T> = {
[P in keyof T]?: T[P] | undefined
}
Make all properties in T optional
Partial<FileSystem>): FileSystem =>
const FileSystem: Context.Service<
FileSystem,
FileSystem
>
const FileSystem: {
key: string;
Service: {
access: (path: string, options?: { readonly ok?: boolean | undefined; readonly readable?: boolean | undefined; readonly writable?: boolean | undefined }) => Effect.Effect<void, PlatformError>;
copy: (fromPath: string, toPath: string, options?: { readonly overwrite?: boolean | undefined; readonly preserveTimestamps?: boolean | undefined }) => Effect.Effect<void, PlatformError>;
copyFile: (fromPath: string, toPath: string) => Effect.Effect<void, PlatformError>;
chmod: (path: string, mode: number) => Effect.Effect<void, PlatformError>;
chown: (path: string, uid: number, gid: number) => Effect.Effect<void, PlatformError>;
glob: (pattern: string, options?: { readonly root?: string | undefined; readonly exclude?: ReadonlyArray<string> | undefined }) => Effect.Effect<Array<string>, PlatformError>;
exists: (path: string) => Effect.Effect<boolean, PlatformError>;
link: (fromPath: string, toPath: string) => Effect.Effect<void, PlatformError>;
makeDirectory: (path: string, options?: { readonly recursive?: boolean | undefined; readonly mode?: number | undefined }) => Effect.Effect<void, PlatformError>;
makeTempDirectory: (options?: { readonly directory?: string | undefined; readonly prefix?: string | undefined }) => Effect.Effect<string, PlatformError>;
makeTempDirectoryScoped: (options?: { readonly directory?: string | undefined; readonly prefix?: string | undefined }) => Effect.Effect<string, PlatformError, Scope>;
makeTempFile: (options?: { readonly directory?: string | undefined; readonly prefix?: string | undefined; readonly suffix?: string | undefined }) => Effect.Effect<string, PlatformError>;
makeTempFileScoped: (options?: { readonly directory?: string | undefined; readonly prefix?: string | undefined; readonly suffix?: string | undefined }) => Effect.Effect<string, PlatformError, Scope>;
open: (path: string, options?: { readonly flag?: OpenFlag | undefined; readonly mode?: number | undefined }) => Effect.Effect<File, PlatformError, Scope>;
readDirectory: (path: string, options?: { readonly recursive?: boolean | undefined }) => Effect.Effect<Array<string>, PlatformError>;
readFile: (path: string) => Effect.Effect<Uint8Array, PlatformError>;
readFileString: (path: string, encoding?: string) => Effect.Effect<string, PlatformError>;
readLink: (path: string) => Effect.Effect<string, PlatformError>;
realPath: (path: string) => Effect.Effect<string, PlatformError>;
remove: (path: string, options?: { readonly recursive?: boolean | undefined; readonly force?: boolean | undefined }) => Effect.Effect<void, PlatformError>;
rename: (oldPath: string, newPath: string) => Effect.Effect<void, PlatformError>;
sink: (path: string, options?: { readonly flag?: OpenFlag | undefined; readonly mode?: number | undefined }) => Sink.Sink<void, Uint8Array, never, PlatformError>;
stat: (path: string) => Effect.Effect<File.Info, PlatformError>;
stream: (path: string, options?: { readonly bytesToRead?: SizeInput | undefined; readonly chunkSize?: SizeInput | undefined; readonly offset?: SizeInput | undefined }) => Stream.Stream<Uint8Array, PlatformError>;
symlink: (fromPath: string, toPath: string) => Effect.Effect<void, PlatformError>;
truncate: (path: string, length?: SizeInput) => Effect.Effect<void, PlatformError>;
utimes: (path: string, atime: Date | number, mtime: Date | number) => Effect.Effect<void, PlatformError>;
watch: (path: string) => Stream.Stream<WatchEvent, PlatformError>;
writeFile: (path: string, data: Uint8Array, options?: { readonly flag?: OpenFlag | undefined; readonly mode?: number | undefined }) => Effect.Effect<void, PlatformError>;
writeFileString: (path: string, data: string, options?: { readonly flag?: OpenFlag | undefined; readonly mode?: number | undefined }) => Effect.Effect<void, PlatformError>;
};
of: (this: void, self: FileSystem) => FileSystem;
context: (self: FileSystem) => Context.Context<FileSystem>;
use: (f: (service: FileSystem) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, FileSystem | R>;
useSync: (f: (service: FileSystem) => A) => Effect.Effect<A, never, FileSystem>;
Identifier: Identifier;
stack: string | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
Core interface for file system operations in Effect.
Details
The FileSystem interface provides a comprehensive set of file and directory operations
that work cross-platform. All operations return Effect values that can be composed,
transformed, and executed safely with proper error handling.
Example (Accessing file system operations)
import { Console, Effect, FileSystem } from "effect"
const program = Effect.gen(function*() {
const fs = yield* FileSystem.FileSystem
// Basic file operations
const exists = yield* fs.exists("./config.json")
if (!exists) {
yield* fs.writeFileString("./config.json", "{\"env\": \"development\"}")
}
// Directory operations
yield* fs.makeDirectory("./logs", { recursive: true })
// File information
const stats = yield* fs.stat("./config.json")
yield* Console.log(`File size: ${stats.size} bytes`)
// Streaming operations
const content = yield* fs.readFileString("./config.json")
yield* Console.log("Config:", content)
})
Service tag for platform file-system operations.
When to use
Use to access or provide operations for files, directories, permissions,
streams, and sinks through the Effect context.
Details
This key is used to provide and access the FileSystem service in the Effect context.
Example (Accessing and providing FileSystem)
import { Effect, FileSystem } from "effect"
// Access the FileSystem service
const program = Effect.gen(function*() {
const fs = yield* FileSystem.FileSystem
const exists = yield* fs.exists("./data.txt")
if (exists) {
const content = yield* fs.readFileString("./data.txt")
yield* Effect.log("File content:", content)
}
})
// Provide a custom FileSystem implementation
declare const platformImpl: Omit<
FileSystem.FileSystem,
"exists" | "readFileString" | "stream" | "sink" | "writeFileString"
>
const customFs = FileSystem.make(platformImpl)
const withCustomFs = Effect.provideService(
program,
FileSystem.FileSystem,
customFs
)
FileSystem.of({
[const TypeId: "~effect/platform/FileSystem"TypeId]: const TypeId: "~effect/platform/FileSystem"TypeId,
function access(path: any): anyaccess(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("access", path: anypath))
},
function chmod(path: any): anychmod(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("chmod", path: anypath))
},
function chown(path: any): anychown(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("chown", path: anypath))
},
function copy(path: any): anycopy(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("copy", path: anypath))
},
function copyFile(path: any): anycopyFile(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("copyFile", path: anypath))
},
function glob(pattern: any): anyglob(pattern: anypattern) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("glob", pattern: anypattern))
},
function exists(): anyexists() {
return import EffectEffect.succeed(false)
},
function link(path: any): anylink(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("link", path: anypath))
},
function makeDirectory(): anymakeDirectory() {
return import EffectEffect.die("not implemented")
},
function makeTempDirectory(): anymakeTempDirectory() {
return import EffectEffect.die("not implemented")
},
function makeTempDirectoryScoped(): anymakeTempDirectoryScoped() {
return import EffectEffect.die("not implemented")
},
function makeTempFile(): anymakeTempFile() {
return import EffectEffect.die("not implemented")
},
function makeTempFileScoped(): anymakeTempFileScoped() {
return import EffectEffect.die("not implemented")
},
function open(path: any): anyopen(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("open", path: anypath))
},
function readDirectory(path: any): anyreadDirectory(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("readDirectory", path: anypath))
},
function readFile(path: any): anyreadFile(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("readFile", path: anypath))
},
function readFileString(path: any): anyreadFileString(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("readFileString", path: anypath))
},
function readLink(path: any): anyreadLink(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("readLink", path: anypath))
},
function realPath(path: any): anyrealPath(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("realPath", path: anypath))
},
function remove(): anyremove() {
return import EffectEffect.void
},
function rename(oldPath: any): anyrename(oldPath: anyoldPath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("rename", oldPath: anyoldPath))
},
function sink(path: any): Sink.Sink<never, unknown, never, PlatformError, never>sink(path: anypath) {
return import SinkSink.const fail: <E>(
e: E
) => Sink<never, unknown, never, E>
A sink that always fails with the specified error.
Example (Failing with an error)
import { Effect, Sink, Stream } from "effect"
// Create a sink that always fails
const sink = Sink.fail(new Error("Sink failed"))
// Use it with a stream
const stream = Stream.make(1, 2, 3)
const program = Stream.run(stream, sink)
Effect.runPromise(program).catch(console.log)
// Output: Error: Sink failed
fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("sink", path: anypath))
},
function stat(path: any): anystat(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("stat", path: anypath))
},
function stream(path: any): Stream.Stream<never, PlatformError, never>stream(path: anypath) {
return import StreamStream.const fail: <E>(
error: E
) => Stream<never, E>
Terminates with the specified error.
Example (Failing a stream)
import { Console, Effect, Stream } from "effect"
const program = Effect.gen(function*() {
const stream = Stream.fail("Uh oh!")
const exit = yield* Effect.exit(Stream.runCollect(stream))
yield* Console.log(exit)
// Output: { _id: 'Exit', _tag: 'Failure', cause: { _id: 'Cause', _tag: 'Fail', failure: 'Uh oh!' } }
})
Effect.runPromise(program)
fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("stream", path: anypath))
},
function symlink(fromPath: any): anysymlink(fromPath: anyfromPath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("symlink", fromPath: anyfromPath))
},
function truncate(path: any): anytruncate(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("truncate", path: anypath))
},
function utimes(path: any): anyutimes(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("utimes", path: anypath))
},
function watch(path: any): Stream.Stream<never, PlatformError, never>watch(path: anypath) {
return import StreamStream.const fail: <E>(
error: E
) => Stream<never, E>
Terminates with the specified error.
Example (Failing a stream)
import { Console, Effect, Stream } from "effect"
const program = Effect.gen(function*() {
const stream = Stream.fail("Uh oh!")
const exit = yield* Effect.exit(Stream.runCollect(stream))
yield* Console.log(exit)
// Output: { _id: 'Exit', _tag: 'Failure', cause: { _id: 'Cause', _tag: 'Fail', failure: 'Uh oh!' } }
})
Effect.runPromise(program)
fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("watch", path: anypath))
},
function writeFile(path: any): anywriteFile(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("writeFile", path: anypath))
},
function writeFileString(path: any): anywriteFileString(path: anypath) {
return import EffectEffect.fail(const notFound: (
method: string,
path: string
) => PlatformError
notFound("writeFileString", path: anypath))
},
...fileSystem: Partial<FileSystem>fileSystem
})