diff --git a/packages/core/src/file-mutation.ts b/packages/core/src/file-mutation.ts index a3c6f519a31..25f30e51e5a 100644 --- a/packages/core/src/file-mutation.ts +++ b/packages/core/src/file-mutation.ts @@ -3,6 +3,7 @@ export * as FileMutation from "./file-mutation" import { Context, Effect, Layer, Schema } from "effect" import { dirname } from "path" import { KeyedMutex } from "./effect/keyed-mutex" +import { LayerNode } from "./effect/layer-node" import { FSUtil } from "./fs-util" export interface Target { @@ -171,6 +172,8 @@ export const layer = Layer.effect( }), ) +export const node = LayerNode.make(layer, [FSUtil.node]) + function splitBom(text: string) { const stripped = text.replace(/^\uFEFF+/, "") return { bom: stripped.length !== text.length, text: stripped } diff --git a/packages/core/src/location-mutation.ts b/packages/core/src/location-mutation.ts index a620c66e31f..d137d581401 100644 --- a/packages/core/src/location-mutation.ts +++ b/packages/core/src/location-mutation.ts @@ -2,6 +2,7 @@ export * as LocationMutation from "./location-mutation" import path from "path" import { Context, Effect, Layer, Schema } from "effect" +import { LayerNode } from "./effect/layer-node" import { FSUtil } from "./fs-util" import { Location } from "./location" @@ -153,3 +154,5 @@ export const layer = Layer.effect( ) export const locationLayer = layer + +export const node = (location: LayerNode.Node) => LayerNode.make(layer, [FSUtil.node, location]) diff --git a/packages/core/test/file-mutation.test.ts b/packages/core/test/file-mutation.test.ts index ba12d7c13cb..4629c0ec77c 100644 --- a/packages/core/test/file-mutation.test.ts +++ b/packages/core/test/file-mutation.test.ts @@ -2,6 +2,7 @@ import fs from "fs/promises" import path from "path" import { describe, expect } from "bun:test" import { Deferred, Effect, Fiber, Layer } from "effect" +import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { FileMutation } from "@opencode-ai/core/file-mutation" import { FSUtil } from "@opencode-ai/core/fs-util" import { Location } from "@opencode-ai/core/location" @@ -11,14 +12,16 @@ import { location } from "./fixture/location" import { tmpdir } from "./fixture/tmpdir" import { it } from "./lib/effect" -function provide(directory: string, filesystem = FSUtil.defaultLayer) { - const activeLocation = Layer.succeed( - Location.Service, - Location.Service.of(location({ directory: AbsolutePath.make(directory) })), +function provide(directory: string, filesystem?: LayerNode.Replacement) { + const activeLocation = LayerNode.make( + Layer.succeed(Location.Service, Location.Service.of(location({ directory: AbsolutePath.make(directory) }))), + [], + ) + return Effect.provide( + LayerNode.buildLayer(LayerNode.group([LocationMutation.node(activeLocation), FileMutation.node]), { + replacements: filesystem ? [filesystem] : [], + }), ) - const resolution = LocationMutation.layer.pipe(Layer.provide(filesystem), Layer.provide(activeLocation)) - const mutation = FileMutation.layer.pipe(Layer.provide(filesystem)) - return Effect.provide(Layer.mergeAll(resolution, mutation)) } function withTmp(f: (directory: string) => Effect.Effect) { @@ -347,17 +350,20 @@ describe("FileMutation", () => { }) function instrumentWrites(run: (write: Effect.Effect, target: string) => Effect.Effect) { - return Layer.effect( - FSUtil.Service, - Effect.gen(function* () { - const filesystem = yield* FSUtil.Service - return FSUtil.Service.of({ - ...filesystem, - writeWithDirs: (target, content, mode) => run(filesystem.writeWithDirs(target, content, mode), target), - writeFile: (target, content, options) => run(filesystem.writeFile(target, content, options), target), - writeFileString: (target, content, options) => - run(filesystem.writeFileString(target, content, options), target), - }) - }), - ).pipe(Layer.provide(FSUtil.defaultLayer)) + return LayerNode.replace( + FSUtil.node, + Layer.effect( + FSUtil.Service, + Effect.gen(function* () { + const filesystem = yield* FSUtil.Service + return FSUtil.Service.of({ + ...filesystem, + writeWithDirs: (target, content, mode) => run(filesystem.writeWithDirs(target, content, mode), target), + writeFile: (target, content, options) => run(filesystem.writeFile(target, content, options), target), + writeFileString: (target, content, options) => + run(filesystem.writeFileString(target, content, options), target), + }) + }), + ).pipe(Layer.provide(LayerNode.buildLayer(FSUtil.node))), + ) }