Skip to content

Try out v4.1 alpha#1096

Draft
cowboyd wants to merge 4 commits intov4from
v4-1-alpha
Draft

Try out v4.1 alpha#1096
cowboyd wants to merge 4 commits intov4from
v4-1-alpha

Conversation

@cowboyd
Copy link
Member

@cowboyd cowboyd commented Feb 3, 2026

Motivation

We've been accumulating features for Effection 4.1.0 that will feature both middleware and the inspector. This branch will be a clearing house for features that can be released to npm.

Approach

This creates an "experimental" export where we can release unstable apis and sets up NPM publishing to send preview releases to the next disc-tag.

Alpha PRS can be made onto this branch. Then, when we are satisfied, we can revive those PRs against the main v4 branch.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 3, 2026

Open in StackBlitz

npm i https://pkg.pr.new/thefrontside/effection@1096

commit: 15c5723

One of the most powerful patterns that we've uncovered in the past
couple of years of writing Effection code in production is the ability
to contextualize an API so that they can be decorated in order to
alter its behavior at any point. In other circles, this capability is
known as "Algebraic Effects" and "Contextual Effects".

With them, we can build all manner of constructs with a single primitive that
would otherwise require many unique mechanisms. These include things
like:

- dependency injection
- mocking inside tests with test doubles
- adding instrumentation such as OTEL spans and metrics colleciton to
- existing interfaces
- wrapping stuff in database transactions

This functionality was available as an external
extension (https://frontside.com/effection/x/context-api), but the
pattern has proven so powerful that we're bringing it directly into
Effection core. Among other things, this will allow us to provide the
type of orthogonal observability that we need to build the Effection
inspector without having to change the library itself in order to
accomodate it.

This change brings the context API functionality directly into
Effection. To create an API, call `createApi()` with the "core"
functionality, where the "core" is how it will behave without any
modification.

```ts
// logging.ts
export const Logging = createApi("Logging", {
  *log(...values: unknown[]) {
    console.log(...values);
  }
})

// export member operations so they can be use standalone
export const { log } = Logging.operations;
```

```ts
import { log } from "./logging.ts"

export function* example() {
 // do stuff
 yield* log("just did stuff");
}
```

```ts
// Override it contextually only inside this scope
yield* logging.around({
  *log(args, next) {
    yield* next(...args.map(v => `[CUSTOM] ${v}`));
  }
});
```

Apis can be enhanced directly from a `Scope` as well:

```ts
import { Logging } from "./logging.ts";

function enhanceLogging(scope: Scope) {
  scope.around(Logging, {
    *log(args, next) {
      yield* next(...args.map(v => `[CUSTOM] ${v}`));
    }
  });
}

```

As an example, and as the api necessary to implement the inspector,
this provides a Scope api which provides instrumentation for core
Effection operations. Such as create(), destroy(), set(), and delete()
for scopes.
In order to implement the inspector, we need to be able to wrap code
around the main function that will run around the main entry point.
This lets you do one time setup and one-time teardown.
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.

1 participant