Skip to content

Capability

import * as Capabilities from '@dxos/app-framework/Capabilities';
import * as Capability from '@dxos/app-framework/Capability';

A capability is a typed slot that modules contribute values to and other modules read. Capabilities are how plugins extend each other without importing each other.

Capability.make declares a multi capability, which any number of modules contribute to. Capability.makeSingleton declares one with exactly one provider. Both take the value’s type and an NSID.

import * as
import Capability
Capability
from '@dxos/app-framework/Capability';
export type
type Exporter = {
readonly format: string;
readonly export: (text: string) => Uint8Array;
}
Exporter
= {
readonly
format: string
format
: string;
readonly
export: (text: string) => Uint8Array
export
: (
text: string
text
: string) =>
interface Uint8Array<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike>

A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the requested number of bytes could not be allocated an exception is raised.

Uint8Array
;
};
// A multi capability: any number of modules may contribute one.
export const
const Exporter: Capability.MultiTag<Exporter, "com.example.plugin.export.capability.exporter">
Exporter
=
import Capability
Capability
.
const make: <Exporter>() => <S>(identifier: NsidParam<S>) => Capability.MultiTag<Exporter, S> (+1 overload)
make
<
type Exporter = {
readonly format: string;
readonly export: (text: string) => Uint8Array;
}
Exporter
>()(
'com.example.plugin.export.capability.exporter',
);
// A singleton capability: exactly one module provides it.
export const
const Clock: Capability.Tag<() => Date, "com.example.plugin.export.capability.clock">
Clock
=
import Capability
Capability
.
const makeSingleton: <() => Date>() => <S>(identifier: NsidParam<S>) => Capability.Tag<() => Date, S> (+1 overload)
makeSingleton
<() =>
interface Date

Enables basic storage and retrieval of dates and times.

Date
>()(
'com.example.plugin.export.capability.clock',
);

Plugin.namespace derives the NSID from the plugin’s key, so a plugin’s capabilities share its prefix.

import * as
import Plugin
Plugin
from '@dxos/app-framework/Plugin';
const
const ExportNamespace: {
key: "com.example.plugin.export";
make: <T>() => <const N extends string>(name: N) => Capability.MultiTag<T, `com.example.plugin.export.capability.${N}`>;
makeSingleton: <T>() => <const N extends string>(name: N) => Capability.Tag<T, `com.example.plugin.export.capability.${N}`>;
}
ExportNamespace
=
import Plugin
Plugin
.
const namespace: <"com.example.plugin.export">(key: "com.example.plugin.export") => {
key: "com.example.plugin.export";
make: <T>() => <N>(name: N) => Capability.MultiTag<T, `com.example.plugin.export.capability.${N}`>;
makeSingleton: <T>() => <N>(name: N) => Capability.Tag<T, `com.example.plugin.export.capability.${N}`>;
}

A plugin's identity as a leaf module: its config and its capability tags both derive from it, so the config can list the tags its modules provide without the tags importing the config.

@example

// src/namespace.ts
export const MarkdownNamespace = Plugin.namespace('org.dxos.plugin.markdown');
// src/types/MarkdownCapabilities.ts
export const Settings = MarkdownNamespace.makeSingleton<Atom.Writable<Settings>>()('settings');
// dx.config.ts
Plugin.config({ plugin: { key: MarkdownNamespace.key, … }, modules: [ … ] });

namespace
('com.example.plugin.export');
export const
const Settings: Capability.Tag<{
defaultFormat: string;
}, "com.example.plugin.export.capability.settings">
Settings
=
const ExportNamespace: {
key: "com.example.plugin.export";
make: <T>() => <const N extends string>(name: N) => Capability.MultiTag<T, `com.example.plugin.export.capability.${N}`>;
makeSingleton: <T>() => <const N extends string>(name: N) => Capability.Tag<T, `com.example.plugin.export.capability.${N}`>;
}
ExportNamespace
.
makeSingleton: <{
defaultFormat: string;
}>() => <N>(name: N) => Capability.Tag<{
defaultFormat: string;
}, `com.example.plugin.export.capability.${N}`>

A singleton capability with identifier <key>.capability.<name>.

makeSingleton
<{
defaultFormat: string
defaultFormat
: string;
}>()('settings');

Contribute an implementation and request all implementations

Section titled “Contribute an implementation and request all implementations”

A module lists the capability in provides and returns Capability.contribute(tag, value).

import * as
import Effect
Effect
from 'effect/Effect';
import * as
import ActivationEvents
ActivationEvents
from '@dxos/app-framework/ActivationEvents';
import * as
import Capability
Capability
from '@dxos/app-framework/Capability';
export const
const TextExporterModule: Capability.Module<void>
TextExporterModule
=
import Capability
Capability
.
const inlineModule: <readonly [Capability.MultiTag<Exporter, "com.example.plugin.export.capability.exporter">], readonly [], void, void>(name: string, spec: ModuleSpec<readonly [Capability.MultiTag<Exporter, "com.example.plugin.export.capability.exporter">], readonly [], void, void>, activate: (props: void) => Effect.Effect<Capability.Contribution<Capability.CapabilityIdentifier<"com.example.plugin.export.capability.exporter", "multi">> | readonly Capability.Contribution<Capability.CapabilityIdentifier<"com.example.plugin.export.capability.exporter", "multi">>[], Error, Capability.Requirements<...>>) => Capability.Module<...>

Helper to define an eager module body with the same spec-carrying shape as

lazyModule

— for bodies that are plain values (translations, schema) or too small to justify a chunk, so plugin definitions stay a uniform chain of spec-carrying modules.

@param ― name The module name — used to auto-compute module IDs.

@param ― spec The requires/provides declaration.

@param ― activate The module body.

inlineModule
(
'TextExporter',
{
provides: readonly [Capability.MultiTag<Exporter, "com.example.plugin.export.capability.exporter">]
provides
: [
const Exporter: Capability.MultiTag<Exporter, "com.example.plugin.export.capability.exporter">
Exporter
],
activatesOn?: Events | undefined

Activates when this runtime event fires instead of during the dependency pass.

activatesOn
:
import ActivationEvents
ActivationEvents
.
const Startup: ActivationEvent

Fired when the app is started. Defined in core; see

ActivationEvent$.Startup

.

Startup
},
() =>
import Effect
Effect
.
const succeed: <Capability.Contribution<Capability.CapabilityIdentifier<"com.example.plugin.export.capability.exporter", "multi">>>(value: Capability.Contribution<Capability.CapabilityIdentifier<"com.example.plugin.export.capability.exporter", "multi">>) => Effect.Effect<Capability.Contribution<Capability.CapabilityIdentifier<"com.example.plugin.export.capability.exporter", "multi">>, never, never>

Creates an Effect that always succeeds with a given value.

When to use

Use when an effect should complete successfully with a specific value without any errors or external dependencies.

Example (Creating a successful effect)

import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)
Effect.runSync(success) // => 42

@see ― fail to create an effect that represents a failure.

@stability ― stable

@category ― constructors

@since ― 2.0.0

succeed
(
import Capability
Capability
.
const contribute: <Capability.MultiTag<Exporter, "com.example.plugin.export.capability.exporter">>(capability: Capability.MultiTag<Exporter, "com.example.plugin.export.capability.exporter">, implementation: Exporter) => Capability.Contribution<Capability.CapabilityIdentifier<"com.example.plugin.export.capability.exporter", "multi">> (+1 overload)
contribute
(
const Exporter: Capability.MultiTag<Exporter, "com.example.plugin.export.capability.exporter">
Exporter
, {
format: string
format
: 'text/plain',
export: (text: string) => Uint8Array
export
: (
text: string
text
) => new
var TextEncoder: new () => TextEncoder

The TextEncoder interface enables you to encode a JavaScript string using UTF-8.

MDN Reference

TextEncoder class is a global reference for import { TextEncoder } from 'node:util' https://nodejs.org/api/globals.html#textencoder

@since ― v11.0.0

TextEncoder
().
TextEncoder.encode(input?: string): Uint8Array<ArrayBuffer>

The TextEncoder.encode() method takes a string as input, and returns a Uint8Array containing the string encoded using UTF-8.

MDN Reference

encode
(
text: string
text
),
}),
),
);

A module that lists a capability in requires activates only after it is contributed, and reads it with yield*. Capability.getAll reads every contribution to a multi capability.

import * as
import Effect
Effect
from 'effect/Effect';
import * as
import Capability
Capability
from '@dxos/app-framework/Capability';
export const
const ExportMenuModule: Capability.Module<void>
ExportMenuModule
=
import Capability
Capability
.
const inlineModule: <readonly [], readonly [Capability.Tag<() => Date, "com.example.plugin.export.capability.clock">], void, void>(name: string, spec: ModuleSpec<readonly [], readonly [Capability.Tag<() => Date, "com.example.plugin.export.capability.clock">], void, void>, activate: (props: void) => Effect.Effect<void | readonly never[], Error, Capability.Requirements<readonly [Capability.Tag<() => Date, "com.example.plugin.export.capability.clock">]>>) => Capability.Module<void>

Helper to define an eager module body with the same spec-carrying shape as

lazyModule

— for bodies that are plain values (translations, schema) or too small to justify a chunk, so plugin definitions stay a uniform chain of spec-carrying modules.

@param ― name The module name — used to auto-compute module IDs.

@param ― spec The requires/provides declaration.

@param ― activate The module body.

inlineModule
(
'ExportMenu',
{
requires?: readonly [Capability.Tag<() => Date, "com.example.plugin.export.capability.clock">] | undefined
requires
: [
const Clock: Capability.Tag<() => Date, "com.example.plugin.export.capability.clock">
Clock
],
provides: readonly []
provides
: [] },
() =>
import Effect
Effect
.
const gen: <Effect.Effect<() => Date, never, Capability.CapabilityIdentifier<"com.example.plugin.export.capability.clock", "single">> | Effect.Effect<Exporter[], never, Capability.Service>, void>(f: () => Generator<Effect.Effect<() => Date, never, Capability.CapabilityIdentifier<"com.example.plugin.export.capability.clock", "single">> | Effect.Effect<Exporter[], never, Capability.Service>, void, never>) => Effect.Effect<void, never, Capability.CapabilityIdentifier<...> | Capability.Service> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to use

Use when you want to write effectful code that looks and behaves like synchronous code, while still handling asynchronous tasks, errors, and complex control flow such as loops and conditions.

Generator functions work similarly to async/await but keep errors, requirements, and interruption in the Effect type. You can yield* values from effects and return the final result at the end.

Example (Sequencing effects with generators)

import { Data, Effect } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function*() {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})
await Effect.runPromise(program) // => "Final amount to charge: 96"

@stability ― stable

@category ― constructors

@since ― 2.0.0

gen
(function* () {
const
const now: () => Date
now
= yield*
const Clock: Capability.Tag<() => Date, "com.example.plugin.export.capability.clock">
Clock
;
const
const exporters: Exporter[]
exporters
= yield*
import Capability
Capability
.
const getAll: <Exporter>(interfaceDef: Capability.InterfaceDef<Exporter>) => Effect.Effect<Exporter[], never, Capability.Service>

Get all capabilities from the capability manager for a given interface.

@param ― interfaceDef The interface definition of the capability.

@returns ― An array of capability implementations.

getAll
(
const Exporter: Capability.MultiTag<Exporter, "com.example.plugin.export.capability.exporter">
Exporter
);
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@see ― source

console
.
Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@since ― v0.1.100

log
(
const now: () => Date
now
(),
const exporters: Exporter[]
exporters
.
Array<Exporter>.map<string>(callbackfn: (value: Exporter, index: number, array: Exporter[]) => string, thisArg?: any): string[]

Calls a defined callback function on each element of an array, and returns an array that contains the results.

@param ― callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.

@param ― thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.

map
((
exporter: Exporter
exporter
) =>
exporter: Exporter
exporter
.
format: string
format
),
);
}),
);

Capabilities holds the capabilities the framework itself defines. The ones most plugins touch:

Capability What a plugin does with it
ReactSurface Contributes surface components. See Surface.
OperationHandler Contributes operation handlers. See Operation.
OperationInvoker Reads it to invoke operations outside a handler.
ReactContext, ReactRoot Wraps the app in a provider, or adds a root-level component.
AtomRegistry Reads and writes atoms outside React.

The App Toolkit’s capabilities, such as settings and App Graph, are in App capabilities.

import * as
import Effect
Effect
from 'effect/Effect';
import * as
import Capabilities
Capabilities
from '@dxos/app-framework/Capabilities';
import * as
import Capability
Capability
from '@dxos/app-framework/Capability';
// Built-in capabilities are tags like any other: a singleton yields its one
// implementation.
export const
const ReportModule: Capability.Module<void>
ReportModule
=
import Capability
Capability
.
const inlineModule: <readonly [], readonly [Capability.Tag<OperationInvoker, "org.dxos.app-framework.capability.operationInvoker">], void, void>(name: string, spec: ModuleSpec<readonly [], readonly [Capability.Tag<OperationInvoker, "org.dxos.app-framework.capability.operationInvoker">], void, void>, activate: (props: void) => Effect.Effect<void | readonly never[], Error, Capability.Requirements<readonly [Capability.Tag<OperationInvoker, "org.dxos.app-framework.capability.operationInvoker">]>>) => Capability.Module<...>

Helper to define an eager module body with the same spec-carrying shape as

lazyModule

— for bodies that are plain values (translations, schema) or too small to justify a chunk, so plugin definitions stay a uniform chain of spec-carrying modules.

@param ― name The module name — used to auto-compute module IDs.

@param ― spec The requires/provides declaration.

@param ― activate The module body.

inlineModule
(
'Report',
{
requires?: readonly [Capability.Tag<OperationInvoker, "org.dxos.app-framework.capability.operationInvoker">] | undefined
requires
: [
import Capabilities
Capabilities
.
const OperationInvoker: Capability.Tag<OperationInvoker, "org.dxos.app-framework.capability.operationInvoker">

Operation invoker backed by the process manager. Spawns a process per operation invocation; see ProcessOperationInvoker in @dxos/compute-runtime.

Operation invoker - provided by the process-manager capability.

@category ― Capability

OperationInvoker
],
provides: readonly []
provides
: [] },
() =>
import Effect
Effect
.
const gen: <Effect.Effect<OperationInvoker, never, Capability.CapabilityIdentifier<"org.dxos.app-framework.capability.operationInvoker", "single">>, void>(f: () => Generator<Effect.Effect<OperationInvoker, never, Capability.CapabilityIdentifier<"org.dxos.app-framework.capability.operationInvoker", "single">>, void, never>) => Effect.Effect<void, never, Capability.CapabilityIdentifier<"org.dxos.app-framework.capability.operationInvoker", "single">> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to use

Use when you want to write effectful code that looks and behaves like synchronous code, while still handling asynchronous tasks, errors, and complex control flow such as loops and conditions.

Generator functions work similarly to async/await but keep errors, requirements, and interruption in the Effect type. You can yield* values from effects and return the final result at the end.

Example (Sequencing effects with generators)

import { Data, Effect } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function*() {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})
await Effect.runPromise(program) // => "Final amount to charge: 96"

@stability ― stable

@category ― constructors

@since ― 2.0.0

gen
(function* () {
const
const invoker: OperationInvoker
invoker
= yield*
import Capabilities
Capabilities
.
const OperationInvoker: Capability.Tag<OperationInvoker, "org.dxos.app-framework.capability.operationInvoker">

Operation invoker backed by the process manager. Spawns a process per operation invocation; see ProcessOperationInvoker in @dxos/compute-runtime.

Operation invoker - provided by the process-manager capability.

@category ― Capability

OperationInvoker
;
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@see ― source

console
.
Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@since ― v0.1.100

log
(typeof
const invoker: OperationInvoker
invoker
.
OperationInvoker.invokePromise: <I, O>(op: Definition<I, O>, ...args: void extends I ? [input?: I, options?: InvokeOptions] : [input: I, options?: InvokeOptions]) => Promise<{
data?: O;
error?: Error;
}>
invokePromise
);
}),
);

React to capabilities that arrive after startup

Section titled “React to capabilities that arrive after startup”

Contributions change as people turn plugins on and off. Capability.contributions returns a live view with get and subscribe; Capability.atom returns the same as an atom for reactive code.

import * as
import Effect
Effect
from 'effect/Effect';
import * as
import Capability
Capability
from '@dxos/app-framework/Capability';
// Contributions that arrive after startup, for example from a plugin the user
// turns on later.
// The view is live: a module subscribes, and the finalizer unsubscribes when
// the module deactivates.
export const
const ExportListModule: Capability.Module<void>
ExportListModule
=
import Capability
Capability
.
const inlineModule: <readonly [], readonly [], void, void>(name: string, spec: ModuleSpec<readonly [], readonly [], void, void>, activate: (props: void) => Effect.Effect<void | readonly never[], Error, Capability.Requirements<readonly []>>) => Capability.Module<void>

Helper to define an eager module body with the same spec-carrying shape as

lazyModule

— for bodies that are plain values (translations, schema) or too small to justify a chunk, so plugin definitions stay a uniform chain of spec-carrying modules.

@param ― name The module name — used to auto-compute module IDs.

@param ― spec The requires/provides declaration.

@param ― activate The module body.

inlineModule
(
'ExportList',
{
provides: readonly []
provides
: [] },
() =>
import Effect
Effect
.
const gen: <Effect.Effect<Capability.Contributions<Exporter>, never, Capability.Service> | Effect.Effect<void, never, Scope>, void>(f: () => Generator<Effect.Effect<Capability.Contributions<Exporter>, never, Capability.Service> | Effect.Effect<void, never, Scope>, void, never>) => Effect.Effect<void, never, Capability.Service | Scope> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to use

Use when you want to write effectful code that looks and behaves like synchronous code, while still handling asynchronous tasks, errors, and complex control flow such as loops and conditions.

Generator functions work similarly to async/await but keep errors, requirements, and interruption in the Effect type. You can yield* values from effects and return the final result at the end.

Example (Sequencing effects with generators)

import { Data, Effect } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function*() {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})
await Effect.runPromise(program) // => "Final amount to charge: 96"

@stability ― stable

@category ― constructors

@since ― 2.0.0

gen
(function* () {
const
const exporters: Capability.Contributions<Exporter>
exporters
= yield*
import Capability
Capability
.
const contributions: <Exporter>(capability: Capability.InterfaceDef<Exporter> | Capability.MultiTag<Exporter, any>) => Effect.Effect<Capability.Contributions<Exporter>, never, Capability.Service>

Get the live contributions view for a multi capability.

@param ― capability The multi capability tag.

@returns ― The live, reactive Contributions collection.

contributions
(
const Exporter: Capability.MultiTag<Exporter, "com.example.plugin.export.capability.exporter">
Exporter
);
const
const unsubscribe: () => void
unsubscribe
=
const exporters: Capability.Contributions<Exporter>
exporters
.
Contributions<Exporter>.subscribe(cb: (values: readonly Exporter[]) => void): () => void

Subscribe to changes.

@returns ― Unsubscribe function.

subscribe
((
current: readonly Exporter[]
current
) =>
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@see ― source

console
.
Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@since ― v0.1.100

log
(
current: readonly Exporter[]
current
.
ReadonlyArray<Exporter>.map<string>(callbackfn: (value: Exporter, index: number, array: readonly Exporter[]) => string, thisArg?: any): string[]

Calls a defined callback function on each element of an array, and returns an array that contains the results.

@param ― callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.

@param ― thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.

map
((
exporter: Exporter
exporter
) =>
exporter: Exporter
exporter
.
format: string
format
)),
);
yield*
import Effect
Effect
.
const addFinalizer: <never>(finalizer: (exit: Exit<unknown, unknown>) => Effect.Effect<void, never, never>) => Effect.Effect<void, never, Scope>

Adds a finalizer to the current scope.

When to use

Use to register low-level cleanup in the current scope.

Details

The finalizer runs when the surrounding scope is closed and receives the Exit value used to close the scope.

Example (Registering scope finalizers)

import { Effect, Exit } from "effect"
const output: Array<unknown> = []
const program = Effect.scoped(
Effect.gen(function*() {
// Add a finalizer that runs when the scope closes
yield* Effect.addFinalizer((exit) =>
Effect.sync(() => { output.push(
Exit.isSuccess(exit)
? "Cleanup: Operation completed successfully"
: "Cleanup: Operation failed, cleaning up resources"
) })
)
yield* Effect.sync(() => { output.push("Performing main operation...") })
// This could succeed or fail
return "operation result"
})
)
void output.push(Effect.runSync(program))
output // => ["Performing main operation...", "Cleanup: Operation completed successfully", "operation result"]

@see ― acquireRelease for resource acquisition with a release finalizer

@see ― ensuring for attaching a finalizer to one effect

@stability ― stable

@category ― resource management

@since ― 2.0.0

addFinalizer
(() =>
import Effect
Effect
.
const sync: <void>(thunk: LazyArg<void>) => Effect.Effect<void, never, never>

Creates an Effect that represents a synchronous side-effectful computation.

When to use

Use when you need to wrap a synchronous side-effectful operation that is not expected to throw.

Details

The provided function is evaluated lazily when the effect runs.

Gotchas

The function must not throw. If it throws, the thrown value is treated as a defect, not as a typed failure. Use try when throwing is expected.

Example (Capturing synchronous logging in an Effect)

import { Effect } from "effect"
const output: Array<unknown> = []
const log = (message: string) =>
Effect.sync(() => {
void output.push(message) // side effect
})
// ┌─── Effect<void, never, never>
// ▼
const program = log("Hello, World!")
Effect.runSync(program)
output // => ["Hello, World!"]

@see ― try_try for a version that can handle failures.

@stability ― stable

@category ― constructors

@since ― 2.0.0

sync
(
const unsubscribe: () => void
unsubscribe
));
}),
);

In React, useCapabilities re-renders on each change. See React.

Page What it covers
Plugin Modules and how they declare provides and requires.
App capabilities The app-level capabilities the App Toolkit defines.