Download packages/core/test/effect/layer-node/layer-node.test.ts from SaylorTwift/opencode: direct link, hf CLI and curl.
- Browser
- Download file 10.6 kB
-
https://huggingface.co/SaylorTwift/opencode/resolve/main/packages/core/test/effect/layer-node/layer-node.test.ts
- Command line
-
hf download hf://SaylorTwift/opencode/packages/core/test/effect/layer-node/layer-node.test.ts
-
curl -L -o layer-node.test.ts https://huggingface.co/SaylorTwift/opencode/resolve/main/packages/core/test/effect/layer-node/layer-node.test.ts
10.6 kB
| import { describe, expect, test } from "bun:test" | |
| import { Context, Effect, Layer } from "effect" | |
| import { LayerNode } from "@opencode-ai/core/effect/layer-node" | |
| class Value extends Context.Service<Value, { readonly value: string }>()("test/LayerNodeValue") {} | |
| class Greeting extends Context.Service<Greeting, { readonly value: string }>()("test/LayerNodeGreeting") {} | |
| class Left extends Context.Service<Left, { readonly value: string }>()("test/LayerNodeLeft") {} | |
| class Right extends Context.Service<Right, { readonly value: string }>()("test/LayerNodeRight") {} | |
| class Database extends Context.Service<Database, { readonly name: string }>()("test/GraphDatabase") {} | |
| class Users extends Context.Service<Users, { readonly list: Effect.Effect<string[]> }>()("test/GraphUsers") {} | |
| class App extends Context.Service<App, { readonly run: Effect.Effect<string[]> }>()("test/GraphApp") {} | |
| const tags = LayerNode.tags({ app: [] }) | |
| const make = tags.make("app") | |
| const build = <A, E>(root: LayerNode.Node<A, E, any>, replacements?: readonly LayerNode.Replacement[]) => | |
| LayerNode.compile(root, replacements) as Layer.Layer<A, E> | |
| const valueLayer = Layer.succeed(Value, Value.of({ value: "production" })) | |
| const greetingLayer = Layer.effect( | |
| Greeting, | |
| Effect.map(Value, (value) => Greeting.of({ value: `hello ${value.value}` })), | |
| ) | |
| const value = make({ service: Value, layer: valueLayer, deps: [] }) | |
| const greeting = make({ service: Greeting, layer: greetingLayer, deps: [value] }) | |
| describe("layer node", () => { | |
| test("builds an untagged graph", async () => { | |
| const value = LayerNode.make({ service: Value, layer: valueLayer, deps: [] }) | |
| const greeting = LayerNode.make({ service: Greeting, layer: greetingLayer, deps: [value] }) | |
| const program = Effect.map(Greeting, (item) => item.value).pipe( | |
| Effect.provide(LayerNode.compile(LayerNode.group([greeting]))), | |
| ) | |
| expect(await Effect.runPromise(program)).toBe("hello production") | |
| }) | |
| test("builds a dependency graph", async () => { | |
| const program = Effect.map(Greeting, (item) => item.value).pipe(Effect.provide(build(LayerNode.group([greeting])))) | |
| expect(await Effect.runPromise(program)).toBe("hello production") | |
| }) | |
| test("exposes roots but hides transitive dependencies", () => { | |
| const layer = build(LayerNode.group([greeting])) | |
| const check: Layer.Layer<Greeting> = layer | |
| void check | |
| }) | |
| test("preserves branch-specific implementations across roots", async () => { | |
| const firstValue = make({ service: Value, layer: Layer.succeed(Value, Value.of({ value: "first" })), deps: [] }) | |
| const secondValue = make({ service: Value, layer: Layer.succeed(Value, Value.of({ value: "second" })), deps: [] }) | |
| const leftLayer = Layer.effect( | |
| Left, | |
| Effect.map(Value, (item) => Left.of({ value: item.value })), | |
| ) | |
| const rightLayer = Layer.effect( | |
| Right, | |
| Effect.map(Value, (item) => Right.of({ value: item.value })), | |
| ) | |
| const left = make({ service: Left, layer: leftLayer, deps: [firstValue] }) | |
| const right = make({ service: Right, layer: rightLayer, deps: [secondValue] }) | |
| const layer = build(LayerNode.group([left, right])) | |
| const program = Effect.gen(function* () { | |
| return [(yield* Left).value, (yield* Right).value] | |
| }).pipe(Effect.provide(layer)) | |
| expect(await Effect.runPromise(program)).toEqual(["first", "second"]) | |
| }) | |
| test("requires unbound nodes to be replaced before compilation", async () => { | |
| const unbound = LayerNode.unbound(Value, tags.values.app) | |
| const greeting = make({ service: Greeting, layer: greetingLayer, deps: [unbound] }) | |
| const tree = LayerNode.group([greeting]) | |
| expect(() => LayerNode.compile(tree)).toThrow("Unbound layer node: test/LayerNodeValue") | |
| const layer = LayerNode.compile(tree, [[unbound, value]]) as Layer.Layer<Greeting> | |
| const program = Effect.map(Greeting, (item) => item.value).pipe(Effect.provide(layer)) | |
| expect(await Effect.runPromise(program)).toBe("hello production") | |
| }) | |
| test("replaces a node with a closed layer", async () => { | |
| const replacement = Layer.succeed(Value, Value.of({ value: "simulation" })) | |
| const program = Effect.map(Greeting, (item) => item.value).pipe( | |
| Effect.provide(build(LayerNode.group([greeting]), [[value, replacement]])), | |
| ) | |
| expect(await Effect.runPromise(program)).toBe("hello simulation") | |
| }) | |
| test("replaces every use of the same layer", async () => { | |
| const leftLayer = Layer.effect( | |
| Left, | |
| Effect.map(Value, (item) => Left.of({ value: item.value })), | |
| ) | |
| const rightLayer = Layer.effect( | |
| Right, | |
| Effect.map(Value, (item) => Right.of({ value: item.value })), | |
| ) | |
| const left = make({ service: Left, layer: leftLayer, deps: [value] }) | |
| const right = make({ service: Right, layer: rightLayer, deps: [value] }) | |
| const replacement = Layer.succeed(Value, Value.of({ value: "replaced" })) | |
| const layer = build(LayerNode.group([left, right]), [[value, replacement]]) | |
| const program = Effect.gen(function* () { | |
| return [(yield* Left).value, (yield* Right).value] | |
| }).pipe(Effect.provide(layer)) | |
| expect(await Effect.runPromise(program)).toEqual(["replaced", "replaced"]) | |
| }) | |
| test("does not acquire an unused replacement", async () => { | |
| let acquisitions = 0 | |
| const other = make({ service: Left, layer: Layer.succeed(Left, Left.of({ value: "other" })), deps: [] }) | |
| const replacement = Layer.effect( | |
| Left, | |
| Effect.sync(() => { | |
| acquisitions++ | |
| return Left.of({ value: "replacement" }) | |
| }), | |
| ) | |
| await Effect.runPromise( | |
| Effect.map(Greeting, (item) => item.value).pipe( | |
| Effect.provide(build(LayerNode.group([greeting]), [[other, replacement]])), | |
| ), | |
| ) | |
| expect(acquisitions).toBe(0) | |
| }) | |
| test("replaces a node without acquiring its dependencies", async () => { | |
| let acquisitions = 0 | |
| const dependencyLayer = Layer.effect( | |
| Value, | |
| Effect.sync(() => { | |
| acquisitions++ | |
| return Value.of({ value: "dependency" }) | |
| }), | |
| ) | |
| const dependency = make({ service: Value, layer: dependencyLayer, deps: [] }) | |
| const original = make({ service: Greeting, layer: greetingLayer, deps: [dependency] }) | |
| const replacement = make({ | |
| service: Greeting, | |
| layer: Layer.succeed(Greeting, Greeting.of({ value: "replacement" })), | |
| deps: [], | |
| }) | |
| const program = Effect.map(Greeting, (item) => item.value).pipe( | |
| Effect.provide(build(LayerNode.group([original]), [[original, replacement]])), | |
| ) | |
| expect(await Effect.runPromise(program)).toBe("replacement") | |
| expect(acquisitions).toBe(0) | |
| }) | |
| test("applies later replacements inside earlier replacement nodes", async () => { | |
| const original = make({ service: Greeting, layer: greetingLayer, deps: [value] }) | |
| const replacement = make({ service: Greeting, layer: greetingLayer, deps: [value] }) | |
| const program = Effect.map(Greeting, (item) => item.value).pipe( | |
| Effect.provide( | |
| build(LayerNode.group([original]), [ | |
| [original, replacement], | |
| [value, Layer.succeed(Value, Value.of({ value: "replacement dependency" }))], | |
| ]), | |
| ), | |
| ) | |
| expect(await Effect.runPromise(program)).toBe("hello replacement dependency") | |
| }) | |
| test("hoists and compiles tagged graphs", async () => { | |
| const tags = LayerNode.tags({ location: ["global"], global: [] }) | |
| const global = tags.make("global") | |
| const location = tags.make("location") | |
| const database = global({ | |
| service: Database, | |
| layer: Layer.succeed(Database, Database.of({ name: "Alice" })), | |
| deps: [], | |
| }) | |
| const users = location({ | |
| service: Users, | |
| layer: Layer.effect( | |
| Users, | |
| Effect.gen(function* () { | |
| const db = yield* Database | |
| return Users.of({ list: Effect.succeed([db.name]) }) | |
| }), | |
| ), | |
| deps: [database], | |
| }) | |
| const app = location({ | |
| service: App, | |
| layer: Layer.effect( | |
| App, | |
| Effect.gen(function* () { | |
| const service = yield* Users | |
| return App.of({ run: service.list }) | |
| }), | |
| ), | |
| deps: [users], | |
| }) | |
| const result = LayerNode.hoist(LayerNode.group([app]), tags.values.global) | |
| expect(result.node.dependencies[0]?.dependencies[0]?.dependencies[0]).toMatchObject({ | |
| kind: "group", | |
| dependencies: [], | |
| }) | |
| expect(result.hoisted.dependencies).toEqual([database]) | |
| const layer = LayerNode.compile(result.node).pipe( | |
| Layer.provide(LayerNode.compile(result.hoisted)), | |
| ) as unknown as Layer.Layer<App> | |
| const program = Effect.gen(function* () { | |
| return yield* (yield* App).run | |
| }).pipe(Effect.provide(layer)) | |
| expect(await Effect.runPromise(program)).toEqual(["Alice"]) | |
| }) | |
| test("rejects conflicting hoisted implementations", () => { | |
| const tags = LayerNode.tags({ location: ["global"], global: [] }) | |
| const global = tags.make("global") | |
| const location = tags.make("location") | |
| const first = global({ | |
| service: Database, | |
| layer: Layer.succeed(Database, Database.of({ name: "first" })), | |
| deps: [], | |
| }) | |
| const second = global({ | |
| service: Database, | |
| layer: Layer.succeed(Database, Database.of({ name: "second" })), | |
| deps: [], | |
| }) | |
| const left = location({ | |
| service: Users, | |
| layer: Layer.effect(Users, Effect.as(Database, Users.of({ list: Effect.succeed([]) }))), | |
| deps: [first], | |
| }) | |
| const right = location({ | |
| service: App, | |
| layer: Layer.effect(App, Effect.as(Database, App.of({ run: Effect.succeed([]) }))), | |
| deps: [second], | |
| }) | |
| expect(() => LayerNode.hoist(LayerNode.group([left, right]), tags.values.global)).toThrow( | |
| "Tag global has conflicting implementations for test/GraphDatabase", | |
| ) | |
| }) | |
| test("treats dependency groups as transparent while hoisting", () => { | |
| const tags = LayerNode.tags({ location: ["global"], global: [] }) | |
| const global = tags.make("global") | |
| const location = tags.make("location") | |
| const database = global({ | |
| service: Database, | |
| layer: Layer.succeed(Database, Database.of({ name: "Alice" })), | |
| deps: [], | |
| }) | |
| const users = location({ | |
| service: Users, | |
| layer: Layer.effect(Users, Effect.as(Database, Users.of({ list: Effect.succeed([]) }))), | |
| deps: [LayerNode.group([database])], | |
| }) | |
| const result = LayerNode.hoist(LayerNode.group([users]), tags.values.global) | |
| expect(result.node.dependencies[0]?.dependencies[0]?.dependencies[0]).toMatchObject({ | |
| kind: "group", | |
| dependencies: [], | |
| }) | |
| }) | |
| }) | |