Skip to content

Restore first-class Effect semantics for query builders#2

Merged
harrysolovay merged 1 commit intoharrysolovay:betafrom
hypervideo:dan/app-618-effect-query-effect
Mar 25, 2026
Merged

Restore first-class Effect semantics for query builders#2
harrysolovay merged 1 commit intoharrysolovay:betafrom
hypervideo:dan/app-618-effect-query-effect

Conversation

@danieljvdm
Copy link
Copy Markdown

Problem

During the Effect v4 migration, applyEffectWrapper() stopped making query builders real Effect values at runtime.

The types still say these builders are Effect.Effect<...>, but the wrapper only exposed asEffect() and Symbol.iterator. That left yield* query working while direct Effect combinators on the builder itself stopped working.

Broken before this change

const query = db.insert(users).values({ name: 'Ada' })

await Effect.runPromise(query.pipe(Effect.either))
await Effect.runPromise(Effect.map(query, (rows) => rows.length))

At runtime, this regressed because query.pipe was no longer defined on the builder.

The only working forms were the indirect ones:

const query = db.insert(users).values({ name: 'Ada' })

await Effect.runPromise(query.asEffect().pipe(Effect.either))
await Effect.runPromise(Effect.gen(function* () {
  return yield* query
}))

What this change does

This patch restores first-class Effect runtime semantics for wrapped query builders.

It adds the minimal Effect v4 runtime surface needed for builders to behave like real Effect values again:

  • the Effect type marker
  • pipe()
  • Symbol.iterator
  • an evaluation hook that delegates to execute()

asEffect() is preserved, and commit() is added as a compatibility alias to execute().

Result after this change

const query = db.insert(users).values({ name: 'Ada' })

await Effect.runPromise(query.pipe(Effect.either))
await Effect.runPromise(Effect.map(query, (rows) => rows.length))
await Effect.runPromise(query.asEffect().pipe(Effect.either))
await Effect.runPromise(Effect.gen(function* () {
  return yield* query
}))

Testing

  • pnpm --dir drizzle-orm exec vitest run tests/effect-query-effect.test.ts
  • added a focused regression test covering query.pipe(...), Effect.map(query, ...), query.asEffect().pipe(...), and yield* query

@harrysolovay
Copy link
Copy Markdown
Owner

harrysolovay commented Mar 22, 2026

[edit]

Apologies: I scanned through your changes too fast. Looks like you've already addressed my concern. Merging now!

@harrysolovay harrysolovay merged commit 600517f into harrysolovay:beta Mar 25, 2026
@danieljvdm
Copy link
Copy Markdown
Author

sweet, thanks dude!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants