Skip to content

FileSystem

The @effect/platform/FileSystem module provides a set of operations for reading and writing from/to the file system.

The module provides a single FileSystem tag, which acts as the gateway for interacting with the filesystem.

Example (Accessing File System Operations)

import {
import FileSystem
FileSystem
} from "@effect/platform"
import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const program: Effect.Effect<void, never, FileSystem.FileSystem>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Tag<FileSystem.FileSystem, FileSystem.FileSystem>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Tag<FileSystem.FileSystem, FileSystem.FileSystem>>, void, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const fs: FileSystem.FileSystem
fs
= yield*
import FileSystem
FileSystem
.
const FileSystem: Tag<FileSystem.FileSystem, FileSystem.FileSystem>

@since1.0.0

@since1.0.0

FileSystem
// Use `fs` to perform file system operations
})

The FileSystem interface includes the following operations:

OperationDescription
accessCheck if a file can be accessed. You can optionally specify the level of access to check for.
copyCopy a file or directory from fromPath to toPath. Equivalent to cp -r.
copyFileCopy a file from fromPath to toPath.
chmodChange the permissions of a file.
chownChange the owner and group of a file.
existsCheck if a path exists.
linkCreate a hard link from fromPath to toPath.
makeDirectoryCreate a directory at path. You can optionally specify the mode and whether to recursively create nested directories.
makeTempDirectoryCreate a temporary directory. By default, the directory will be created inside the system’s default temporary directory.
makeTempDirectoryScopedCreate a temporary directory inside a scope. Functionally equivalent to makeTempDirectory, but the directory will be automatically deleted when the scope is closed.
makeTempFileCreate a temporary file. The directory creation is functionally equivalent to makeTempDirectory. The file name will be a randomly generated string.
makeTempFileScopedCreate a temporary file inside a scope. Functionally equivalent to makeTempFile, but the file will be automatically deleted when the scope is closed.
openOpen a file at path with the specified options. The file handle will be automatically closed when the scope is closed.
readDirectoryList the contents of a directory. You can recursively list the contents of nested directories by setting the recursive option.
readFileRead the contents of a file.
readFileStringRead the contents of a file as a string.
readLinkRead the destination of a symbolic link.
realPathResolve a path to its canonicalized absolute pathname.
removeRemove a file or directory. By setting the recursive option to true, you can recursively remove nested directories.
renameRename a file or directory.
sinkCreate a writable Sink for the specified path.
statGet information about a file at path.
streamCreate a readable Stream for the specified path.
symlinkCreate a symbolic link from fromPath to toPath.
truncateTruncate a file to a specified length. If the length is not specified, the file will be truncated to length 0.
utimesChange the file system timestamps of the file at path.
watchWatch a directory or file for changes.
writeFileWrite data to a file at path.
writeFileStringWrite a string to a file at path.

Example (Reading a File as a String)

import {
import FileSystem
FileSystem
} from "@effect/platform"
import {
import NodeContext
NodeContext
,
import NodeRuntime
NodeRuntime
} from "@effect/platform-node"
import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// ┌─── Effect<void, PlatformError, FileSystem>
// ▼
const
const program: Effect.Effect<void, PlatformError, FileSystem.FileSystem>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Tag<FileSystem.FileSystem, FileSystem.FileSystem>> | YieldWrap<Effect.Effect<string, PlatformError, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const fs: FileSystem.FileSystem
fs
= yield*
import FileSystem
FileSystem
.
const FileSystem: Tag<FileSystem.FileSystem, FileSystem.FileSystem>

@since1.0.0

@since1.0.0

FileSystem
// Reading the content of the same file where this code is written
const
const content: string
content
= yield*
const fs: FileSystem.FileSystem
fs
.
FileSystem.readFileString: (path: string, encoding?: string) => Effect.Effect<string, PlatformError>

Read the contents of a file.

readFileString
("./index.ts", "utf8")
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
const content: string
content
)
})
// Provide the necessary context and run the program
import NodeRuntime
NodeRuntime
.
const runMain: RunMain
<PlatformError, void>(effect: Effect.Effect<void, PlatformError, never>, options?: {
readonly disableErrorReporting?: boolean | undefined;
readonly disablePrettyLogger?: boolean | undefined;
readonly teardown?: Teardown | undefined;
}) => void (+1 overload)

Helps you run a main effect with built-in error handling, logging, and signal management.

Details

This function launches an Effect as the main entry point, setting exit codes based on success or failure, handling interrupts (e.g., Ctrl+C), and optionally logging errors. By default, it logs errors and uses a "pretty" format, but both behaviors can be turned off. You can also provide custom teardown logic to finalize resources or produce different exit codes.

Options

An optional object that can include:

  • disableErrorReporting: Turn off automatic error logging.
  • disablePrettyLogger: Avoid adding the pretty logger.
  • teardown: Provide custom finalization logic.

When to Use

Use this function to run an Effect as your application’s main program, especially when you need structured error handling, log management, interrupt support, or advanced teardown capabilities.

runMain
(
const program: Effect.Effect<void, PlatformError, FileSystem.FileSystem>
program
.
Pipeable.pipe<Effect.Effect<void, PlatformError, FileSystem.FileSystem>, Effect.Effect<void, PlatformError, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <NodeContext.NodeContext, never, never>(layer: Layer<NodeContext.NodeContext, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Provides necessary dependencies to an effect, removing its environmental requirements.

Details

This function allows you to supply the required environment for an effect. The environment can be provided in the form of one or more Layers, a Context, a Runtime, or a ManagedRuntime. Once the environment is provided, the effect can run without requiring external dependencies.

You can compose layers to create a modular and reusable way of setting up the environment for effects. For example, layers can be used to configure databases, logging services, or any other required dependencies.

@seeprovideService for providing a service to an effect.

@example

import { Context, Effect, Layer } from "effect"
class Database extends Context.Tag("Database")<
Database,
{ readonly query: (sql: string) => Effect.Effect<Array<unknown>> }
>() {}
const DatabaseLive = Layer.succeed(
Database,
{
// Simulate a database query
query: (sql: string) => Effect.log(`Executing query: ${sql}`).pipe(Effect.as([]))
}
)
// ┌─── Effect<unknown[], never, Database>
// ▼
const program = Effect.gen(function*() {
const database = yield* Database
const result = yield* database.query("SELECT * FROM users")
return result
})
// ┌─── Effect<unknown[], never, never>
// ▼
const runnable = Effect.provide(program, DatabaseLive)
// Effect.runPromise(runnable).then(console.log)
// Output:
// timestamp=... level=INFO fiber=#0 message="Executing query: SELECT * FROM users"
// []

@since2.0.0

provide
(
import NodeContext
NodeContext
.
const layer: Layer<NodeContext.NodeContext, never, never>

@since1.0.0

layer
)))

In testing environments, you may want to mock the file system to avoid performing actual disk operations. The FileSystem.layerNoop provides a no-operation implementation of the FileSystem service.

Most operations in FileSystem.layerNoop return a failure (e.g., Effect.fail for missing files) or a defect (e.g., Effect.die for unimplemented features). However, you can override specific behaviors by passing an object to FileSystem.layerNoop to define custom return values for selected methods.

Example (Mocking File System with Custom Behavior)

import {
import FileSystem
FileSystem
} from "@effect/platform"
import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const program: Effect.Effect<void, PlatformError, FileSystem.FileSystem>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Tag<FileSystem.FileSystem, FileSystem.FileSystem>> | YieldWrap<Effect.Effect<boolean, PlatformError, never>> | YieldWrap<...>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const fs: FileSystem.FileSystem
fs
= yield*
import FileSystem
FileSystem
.
const FileSystem: Tag<FileSystem.FileSystem, FileSystem.FileSystem>

@since1.0.0

@since1.0.0

FileSystem
const
const exists: boolean
exists
= yield*
const fs: FileSystem.FileSystem
fs
.
FileSystem.exists: (path: string) => Effect.Effect<boolean, PlatformError>

Check if a path exists.

exists
("/some/path")
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
const exists: boolean
exists
)
const
const content: string
content
= yield*
const fs: FileSystem.FileSystem
fs
.
FileSystem.readFileString: (path: string, encoding?: string) => Effect.Effect<string, PlatformError>

Read the contents of a file.

readFileString
("/some/path")
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
const content: string
content
)
})
// ┌─── Layer<FileSystem.FileSystem, never, never>
// ▼
const
const customMock: Layer<FileSystem.FileSystem, never, never>
customMock
=
import FileSystem
FileSystem
.
const layerNoop: (fileSystem: Partial<FileSystem.FileSystem>) => Layer<FileSystem.FileSystem>

Create a no-op file system that can be used for testing.

@since1.0.0

layerNoop
({
readFileString?: (path: string, encoding?: string) => Effect.Effect<string, PlatformError>

Read the contents of a file.

readFileString
: () =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <string>(value: string) => Effect.Effect<string, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
("mocked content"),
exists?: (path: string) => Effect.Effect<boolean, PlatformError>

Check if a path exists.

exists
: (
path: string
path
) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <boolean>(value: boolean) => Effect.Effect<boolean, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(
path: string
path
=== "/some/path")
})
// Provide the customized FileSystem mock implementation
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <void, PlatformError>(effect: Effect.Effect<void, PlatformError, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<...>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
// Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

// Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<void, PlatformError, FileSystem.FileSystem>
program
.
Pipeable.pipe<Effect.Effect<void, PlatformError, FileSystem.FileSystem>, Effect.Effect<void, PlatformError, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <FileSystem.FileSystem, never, never>(layer: Layer<FileSystem.FileSystem, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Provides necessary dependencies to an effect, removing its environmental requirements.

Details

This function allows you to supply the required environment for an effect. The environment can be provided in the form of one or more Layers, a Context, a Runtime, or a ManagedRuntime. Once the environment is provided, the effect can run without requiring external dependencies.

You can compose layers to create a modular and reusable way of setting up the environment for effects. For example, layers can be used to configure databases, logging services, or any other required dependencies.

@seeprovideService for providing a service to an effect.

@example

import { Context, Effect, Layer } from "effect"
class Database extends Context.Tag("Database")<
Database,
{ readonly query: (sql: string) => Effect.Effect<Array<unknown>> }
>() {}
const DatabaseLive = Layer.succeed(
Database,
{
// Simulate a database query
query: (sql: string) => Effect.log(`Executing query: ${sql}`).pipe(Effect.as([]))
}
)
// ┌─── Effect<unknown[], never, Database>
// ▼
const program = Effect.gen(function*() {
const database = yield* Database
const result = yield* database.query("SELECT * FROM users")
return result
})
// ┌─── Effect<unknown[], never, never>
// ▼
const runnable = Effect.provide(program, DatabaseLive)
// Effect.runPromise(runnable).then(console.log)
// Output:
// timestamp=... level=INFO fiber=#0 message="Executing query: SELECT * FROM users"
// []

@since2.0.0

provide
(
const customMock: Layer<FileSystem.FileSystem, never, never>
customMock
)))
/*
Output:
true
mocked content
*/