Effection Logo
@effectionx/scope-evalv0.1.0thefrontside/effectionx
NPM Badge with published version
import { } from "@effectionx/scope-eval"

@effectionx/scope-eval

Evaluate Effection operations in a scope while retaining resources.

While Scope.run and Scope.spawn can evaluate operations in isolated scopes, resources are torn down once operations return. useEvalScope allows you to invoke operations in an existing scope, receive the result of evaluations, while retaining resources for the lifecycle of that scope.

Usage

useEvalScope

Create a scope that evaluates operations and retains their resources:

import { main, createContext } from "effection";
import { useEvalScope } from "@effectionx/scope-eval";

await main(function*() {
  const context = createContext<string>("my-context");

  const evalScope = yield* useEvalScope();

  // Context not set yet
  evalScope.scope.get(context); // => undefined

  // Evaluate an operation that sets context
  yield* evalScope.eval(function*() {
    yield* context.set("Hello World!");
  });

  // Now the context is visible via the scope
  evalScope.scope.get(context); // => "Hello World!"
});

Error Handling

Operations are executed safely and return a Result<T>:

import { main } from "effection";
import { useEvalScope } from "@effectionx/scope-eval";

await main(function*() {
  const evalScope = yield* useEvalScope();

  const result = yield* evalScope.eval(function*() {
    throw new Error("something went wrong");
  });

  if (result.ok) {
    console.log("Success:", result.value);
  } else {
    console.log("Error:", result.error.message);
  }
});

box / unbox

Utilities for capturing operation results as values:

import { main } from "effection";
import { box, unbox } from "@effectionx/scope-eval";

await main(function*() {
  // Capture success or error as a Result
  const result = yield* box(function*() {
    return 42;
  });

  // Extract value (throws if error)
  const value = unbox(result); // => 42
});

API

useEvalScope(): Operation<EvalScope>

Creates an isolated scope for evaluating operations.

Returns an EvalScope with:

  • scope: Scope - The underlying Effection scope for inspecting context
  • eval<T>(op: () => Operation<T>): Operation<Result<T>> - Evaluate an operation

box<T>(content: () => Operation<T>): Operation<Result<T>>

Execute an operation and capture its result (success or error) as a Result<T>.

unbox<T>(result: Result<T>): T

Extract the value from a Result<T>, throwing if it's an error.

Use Cases

  • Testing: Evaluate operations and inspect context/state without teardown
  • Resource retention: Keep resources alive across multiple evaluations
  • Error boundaries: Safely execute operations that might fail

API Reference

function* useEvalScope(): Operation<EvalScope>

Create an isolated scope for evaluating operations.

This spawns a child scope that processes operations sent to it via a channel. The key benefit is that you can access the scope object directly, allowing you to inspect context values that were set by evaluated operations.

Examples

Example 1
import { createContext } from "effection";
import { useEvalScope } from "@effectionx/scope-eval";

const context = createContext<string>("my-context");

const evalScope = yield* useEvalScope();

// Context not set yet
evalScope.scope.get(context); // => undefined

// Evaluate an operation that sets context
yield* evalScope.eval(function*() {
  yield* context.set("Hello World!");
});

// Now the context is visible
evalScope.scope.get(context); // => "Hello World!"

Return Type

Operation<EvalScope>

An EvalScope with access to the scope and an eval function

interface EvalScope

An isolated scope that can evaluate operations and expose their side effects.

This is useful for testing scenarios where you need to:

  • Evaluate operations in a separate scope
  • Access context values set by those operations
  • Inspect the scope's state from outside

Properties

scope: Scope

The underlying Effection scope. Use this to inspect context values set by evaluated operations.

Methods

eval
<T>(op: () => Operation<T>): Operation<Result<T>>

Evaluate an operation within this scope.

The operation runs in the spawned scope, so any context values it sets will be visible via scope.get(context).

function box<T>(content: () => Operation<T>): Operation<Result<T>>

Execute an operation and capture its result (success or error) as a Result<T>.

This is useful when you want to handle errors as values rather than exceptions.

Examples

Example 1
const result = yield* box(function*() {
  return yield* someOperation();
});

if (result.ok) {
  console.log("Success:", result.value);
} else {
  console.log("Error:", result.error);
}

Type Parameters

T

Parameters

content: () => Operation<T>

  • A function returning the operation to execute

Return Type

Operation<Result<T>>

An operation that yields Ok(value) on success or Err(error) on failure

function unbox<T>(result: Result<T>): T

Extract the value from a Result<T>, throwing if it's an error.

Examples

Example 1
const result = yield* box(function*() {
  return "hello";
});

const value = unbox(result); // "hello"

Type Parameters

T

Parameters

result: Result<T>

  • The result to unbox

Return Type

T

The success value