diff --git a/packages/opencode/src/bus/bus-event.ts b/packages/opencode/src/bus/bus-event.ts index bb9b3f497f..90a0668dba 100644 --- a/packages/opencode/src/bus/bus-event.ts +++ b/packages/opencode/src/bus/bus-event.ts @@ -23,16 +23,12 @@ export function define( properties: P, ): { type: Type; properties: P } export function define(type: string, properties: unknown) { - const zodProperties = isEffectSchema(properties) ? zod(properties) : (properties as ZodType) + const zodProperties = Schema.isSchema(properties) ? zod(properties) : (properties as ZodType) const result = { type, properties: zodProperties } registry.set(type, result as Definition) return result } -function isEffectSchema(value: unknown): value is Schema.Top { - return typeof value === "object" && value !== null && "ast" in value -} - export function payloads() { return registry .entries() diff --git a/packages/opencode/src/sync/index.ts b/packages/opencode/src/sync/index.ts index 6fdad16621..fdedff0366 100644 --- a/packages/opencode/src/sync/index.ts +++ b/packages/opencode/src/sync/index.ts @@ -117,7 +117,7 @@ export function define< } function toZodObject(value: ZodObject | Schema.Top): z.ZodObject { - if (typeof value === "object" && value !== null && "ast" in value) { + if (Schema.isSchema(value)) { return zod(value as Schema.Top) as unknown as z.ZodObject } return value as z.ZodObject diff --git a/packages/opencode/test/bus/bus.test.ts b/packages/opencode/test/bus/bus.test.ts index 3df179787d..7cde38a014 100644 --- a/packages/opencode/test/bus/bus.test.ts +++ b/packages/opencode/test/bus/bus.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test" +import { Schema } from "effect" import z from "zod" import { Bus } from "../../src/bus" import { BusEvent } from "../../src/bus/bus-event" @@ -10,6 +11,8 @@ const TestEvent = { Pong: BusEvent.define("test.pong", z.object({ message: z.string() })), } +const EffectTestEvent = BusEvent.define("test.effect-schema.ping", Schema.Struct({ value: Schema.Number })) + function withInstance(directory: string, fn: () => Promise) { return Instance.provide({ directory, fn }) } @@ -76,6 +79,22 @@ describe("Bus", () => { await Bus.publish(TestEvent.Ping, { value: 1 }) }) }) + + test("accepts Effect Schema event definitions", async () => { + await using tmp = await tmpdir() + const received: number[] = [] + + await withInstance(tmp.path, async () => { + Bus.subscribe(EffectTestEvent, (evt) => { + received.push(evt.properties.value) + }) + await Bun.sleep(10) + await Bus.publish(EffectTestEvent, { value: 42 }) + await Bun.sleep(10) + }) + + expect(received).toEqual([42]) + }) }) describe("unsubscribe", () => { diff --git a/packages/opencode/test/sync/index.test.ts b/packages/opencode/test/sync/index.test.ts index 866bcaa31a..81c78132ec 100644 --- a/packages/opencode/test/sync/index.test.ts +++ b/packages/opencode/test/sync/index.test.ts @@ -1,4 +1,5 @@ import { describe, test, expect, beforeEach, afterEach, afterAll } from "bun:test" +import { Schema } from "effect" import { tmpdir } from "../fixture/fixture" import z from "zod" import { Bus } from "../../src/bus" @@ -128,6 +129,51 @@ describe("SyncEvent", () => { }) }), ) + + test( + "accepts Effect Schema event definitions", + withInstance(async () => { + SyncEvent.reset() + try { + const Created = SyncEvent.define({ + type: "item.effect.created", + version: 1, + aggregate: "id", + schema: Schema.Struct({ id: Schema.String, name: Schema.String }), + }) + + SyncEvent.init({ + projectors: [SyncEvent.project(Created, () => {})], + }) + + const events: Array<{ + type: string + properties: { id: string; name: string } + }> = [] + const received = new Promise((resolve) => { + Bus.subscribeAll((event) => { + events.push(event) + resolve() + }) + }) + + SyncEvent.run(Created, { id: "evt_1", name: "schema" }) + + await received + expect(events).toEqual([ + { + type: "item.effect.created", + properties: { + id: "evt_1", + name: "schema", + }, + }, + ]) + } finally { + setup() + } + }), + ) }) describe("replay", () => {