@radish/effect-system@0.5.0Built and signed on GitHub ActionsBuilt and signed on GitHub Actions
The Radish effect system
Radish effect-system unlocks modularity, testability, simplicity, customizability.
- Modularity: Decouple effects descriptions from their interpretations
- Testability: Swap handlers in a test environment to easily mock deep side-effects without modifying your API for testing purposes
- Simplicity: Think in terms of operations. And avoiding the need to pass context objects or callbacks solely for testing makes code simpler and more focused, with thinner, single responsibility APIs
- Customizability: Consumers of your library or framework can override effect handlers to suit their needs
Powerful Handler Patterns
Handlers can be:
- synchronous or asynchronous
- partial or total
This flexibility enables powerful patterns like handler delegation, dynamic decoration and effect observation.
See handlerFor
AsyncState
In stateful async workflows, you can create AsyncState and take snapshots of HandlerScopes
, including their handlers and store, and later restore these scopes, states and handlers across async boundaries, without race conditions or context loss.
See Snapshot
and createState
Out-of-the-box Plugin API
As a bonus, you get a Plugin
API out-of-the-box: define your own effects and handlers, and allow consumers to extend and override them with their own handlers to suit their needs. This provides flexibility and a high level of control to your users.
Create a new effect
Create a new effect
Use createEffect
to create a new effect
import { createEffect } from "@radish/effect-system"; const fs = { read: createEffect<(path: string) => string>('fs/read'), transform: createEffect<(content: string)=> string>('fs/transform'), write: createEffect<(path: string, data: string)=> void>('fs/write'), }
Perform an effect
Perform an effect
We can already use the above effect without providing an implementation yet. This separates definition from implementation.
To perform an effect operation we await it. This allows the sequencing of effects in direct style.
// a sequence of effects const content = await fs.read("/path/to/input"); const transformed = await fs.transform(content); await fs.write("/path/to/output", transformed);
Create an effect handler
Create an effect handler
Use handlerFor
to create a handler for a given effect
import { handlerFor } from "@radish/effect-system"; const handleFSRead = handlerFor(fs.read, (path: string) => { return "my content"; }); const handleFSTransform = handlerFor(fs.transform, (content: string) => { return content.toUpperCase(); }); const handleFSWrite = handlerFor(fs.transform, (path: string, data: string) => { console.log(`writing to ${path}: ${data}`); });
Perform effects with handlers in scope
Perform effects with handlers in scope
Use HandlerScope
to create a new scope with handlers to run effects in.
{ using _ = new HandlerScope(handleFSRead, handleFSTransform, handleFSWrite); const content = await fs.read("/path/to/input"); const transformed = await fs.transform(content); await fs.write("/path/to/output", transformed); // logs "writing to /path/to/output: MY CONTENT" }
Create a plugin
Create a plugin
Export your handlers as a Plugin
for the reusability of related functionality. The HandlerScope
constructor also accepts plugins as arguments.
const pluginFS = { name: "plugin-fs", handlers: [handleFSRead, handleFSTransform, handleFSWrite] }; // Usage { using _ = new HandlerScope(pluginFS); const content = await fs.read("/path/to/input"); const transformed = await fs.transform(content); await fs.write("/path/to/output", transformed); // logs "writing to /path/to/output: MY CONTENT" }
Add Package
deno add jsr:@radish/effect-system
Import symbol
import * as effect_system from "@radish/effect-system";
Import directly with a jsr specifier
import * as effect_system from "jsr:@radish/effect-system";
Add Package
pnpm i jsr:@radish/effect-system
pnpm dlx jsr add @radish/effect-system
Import symbol
import * as effect_system from "@radish/effect-system";
Add Package
yarn add jsr:@radish/effect-system
yarn dlx jsr add @radish/effect-system
Import symbol
import * as effect_system from "@radish/effect-system";
Add Package
vlt install jsr:@radish/effect-system
Import symbol
import * as effect_system from "@radish/effect-system";
Add Package
npx jsr add @radish/effect-system
Import symbol
import * as effect_system from "@radish/effect-system";
Add Package
bunx jsr add @radish/effect-system
Import symbol
import * as effect_system from "@radish/effect-system";