Skip to main content

Overview

ff-effect is a utilities package that provides Effect.ts-first wrappers for popular libraries:
  • AI SDK - Effectful wrappers for AI SDK’s generateText, streamText, and tool with automatic callback bridging
  • Drizzle - Type-safe database operations with built-in transaction support
  • Inngest - Background job orchestration with Effect-based function handlers
  • oRPC - RPC procedures backed by Effect
All integrations preserve Effect’s composability, type-safety, and structured concurrency while making it seamless to use these libraries in an Effect-first codebase.

Installation

npm install ff-effect effect

Peer Dependencies

Depending on which integrations you use, install the corresponding peer dependencies:
# For AI SDK integration
bun add ai

# For Drizzle integration
bun add drizzle-orm

# For Inngest integration
bun add inngest

# For oRPC integration
bun add @orpc/server @orpc/contract

Core Utilities

The package exports three core utilities:

extract

Extract services from an Effect function to move dependencies up the stack. This is particularly useful when building service containers that expose methods requiring services.
import { extract } from 'ff-effect';
import { Effect } from 'effect';

class MyService extends Effect.Service<MyService>()('MyService', {
  effect: Effect.gen(function* () {
    return {
      // Extract moves ServiceA dependency from getVal to Container
      getVal: yield* extract(function* () {
        return (yield* ServiceA).value;
      })
    };
  })
}) {}

runPromiseUnwrapped

Run an Effect as a Promise, automatically unwrapping errors from Cause to throw them directly.
import { runPromiseUnwrapped } from 'ff-effect';
import { Effect } from 'effect';

const result = await runPromiseUnwrapped(
  Effect.succeed('hello')
); // 'hello'

wrapClient

Wrap any Promise-based client with consistent Effect error handling.
import { wrapClient } from 'ff-effect';

class MyError extends Error {}

const wrap = wrapClient({
  client: myApiClient,
  error: ({ cause, message }) => new MyError(message)
});

const result = yield* wrap(
  (client) => client.fetchData(),
  { errorMessage: 'Failed to fetch data' }
);

Integration Modules

Each integration is available under a separate export path:
import { generateText, tool } from 'ff-effect/for/ai';
import { createDrizzle } from 'ff-effect/for/drizzle';
import { createInngest } from 'ff-effect/for/inngest';
import { createHandler } from 'ff-effect/for/orpc';
Explore the individual integration pages to learn more:

Type Safety

All utilities preserve full type inference and provide compile-time safety:
  • Service dependencies are tracked in the R type parameter
  • Errors are represented in the E type parameter
  • Success values flow through the A type parameter

Next Steps