FileSystem
探索 Effect 中用于读取、写入和管理文件与目录的文件系统操作。
effect/FileSystem 模块提供了一组用于从文件系统读取以及向文件系统写入的操作。
基本用法
该模块只提供一个 FileSystem service key,它是与文件系统交互的入口。
示例(访问文件系统操作)
import { Effect, FileSystem } from "effect"
const program = Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem
// Use `fs` to perform file system operations
})
Effect.isEffect(program) // => true
FileSystem 接口包含以下操作:
| 操作 | 说明 |
|---|---|
| access | 检查文件是否可以被访问。你可以选择性地指定要检查的访问级别。 |
| copy | 将文件或目录从 fromPath 复制到 toPath。等价于 cp -r。 |
| copyFile | 将文件从 fromPath 复制到 toPath。 |
| chmod | 更改文件的权限。 |
| chown | 更改文件的所有者和所属组。 |
| exists | 检查某个路径是否存在。 |
| link | 从 fromPath 到 toPath 创建硬链接。 |
| makeDirectory | 在 path 处创建目录。你可以选择性地指定权限模式以及是否递归创建嵌套目录。 |
| makeTempDirectory | 创建一个临时目录。默认情况下,该目录会创建在系统的默认临时目录中。 |
| makeTempDirectoryScoped | 在 scope 内创建一个临时目录。功能上等价于 makeTempDirectory,但当 scope 关闭时该目录会被自动删除。 |
| makeTempFile | 创建一个临时文件。其目录创建方式在功能上等价于 makeTempDirectory。文件名将是一个随机生成的字符串。 |
| makeTempFileScoped | 在 scope 内创建一个临时文件。功能上等价于 makeTempFile,但当 scope 关闭时该文件会被自动删除。 |
| open | 以指定的 options 打开 path 处的文件。当 scope 关闭时,文件句柄会被自动关闭。 |
| readDirectory | 列出目录的内容。你可以通过设置 recursive 选项来递归列出嵌套目录的内容。 |
| readFile | 读取文件的内容。 |
| readFileString | 以字符串形式读取文件的内容。 |
| readLink | 读取符号链接的目标。 |
| realPath | 将路径解析为规范化的绝对路径名。 |
| remove | 删除文件或目录。通过将 recursive 选项设为 true,你可以递归删除嵌套目录。 |
| rename | 重命名文件或目录。 |
| sink | 为指定的 path 创建一个可写的 Sink。 |
| stat | 获取 path 处文件的信息。 |
| stream | 为指定的 path 创建一个可读的 Stream。 |
| symlink | 从 fromPath 到 toPath 创建符号链接。 |
| truncate | 将文件截断到指定长度。如果未指定 length,文件将被截断为长度 0。 |
| utimes | 更改 path 处文件的文件系统时间戳。 |
| watch | 监视目录或文件的变化。 |
| writeFile | 将数据写入 path 处的文件。 |
| writeFileString | 将字符串写入 path 处的文件。 |
示例(将文件读取为字符串)
import { Effect, FileSystem } from "effect"
import { NodeServices, NodeRuntime } from "@effect/platform-node"
// ┌─── Effect<void, PlatformError, FileSystem>
// ▼
const program = Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem
// Reading the content of the same file where this code is written
const content = yield* fs.readFileString("./index.ts", "utf8")
console.log(content)
})
// Provide the necessary context and run the program
NodeRuntime.runMain(program.pipe(Effect.provide(NodeServices.layer)))
Mock 文件系统
在测试环境中,你可能希望 mock 文件系统,以避免执行真实的磁盘操作。FileSystem.layerNoop 提供了 FileSystem service 的空操作实现。
FileSystem.layerNoop 中的大多数操作会返回 failure(例如对缺失文件返回 Effect.fail)或 defect(例如对未实现的功能返回 Effect.die)。
不过,你可以通过向 FileSystem.layerNoop 传入一个对象,为选定的方法定义自定义返回值,从而覆盖特定的行为。
示例(以自定义行为 Mock 文件系统)
import { Effect, FileSystem } from "effect"
const program = Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem
const exists = yield* fs.exists("/some/path")
console.log(exists)
exists // => true
const content = yield* fs.readFileString("/some/path")
console.log(content)
content // => "mocked content"
})
// ┌─── Layer<FileSystem.FileSystem, never, never>
// ▼
const customMock = FileSystem.layerNoop({
readFileString: () => Effect.succeed("mocked content"),
exists: (path) => Effect.succeed(path === "/some/path"),
})
// Provide the customized FileSystem mock implementation
Effect.runPromise(program.pipe(Effect.provide(customMock)))