Introduction to Effect Platform
Welcome to the documentation for @effect/platform
, a library designed for creating platform-independent abstractions (Node.js, Bun, browsers).
With @effect/platform
, you can incorporate abstract services like Terminal
, FileSystem
or Path
into your program.
Later, during the assembly of the final application, you can provide specific layers for the target platform using the corresponding packages:
@effect/platform-node
for Node.js@effect/platform-bun
for Bun@effect/platform-browser
for browsers
To install the beta version:
npm install @effect/platform
pnpm add @effect/platform
yarn add @effect/platform
bun add @effect/platform
Below is a simple example using the Path
module to create a file path. This program is compatible with multiple environments:
1import { import Path
Path } from "@effect/platform"2import { import Effect
Effect } from "effect"3
4const const program: Effect.Effect<void, never, Path.Path>
program = import Effect
Effect.const gen: <YieldWrap<Tag<Path.Path, Path.Path>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Tag<Path.Path, Path.Path>>, void, never>) => Effect.Effect<...> (+1 overload)
gen(function* () {5 const const path: Path.Path
path = yield* import Path
Path.namespace Path
const Path: Tag<Path.Path, Path.Path>
Path6
7 const const mypath: string
mypath = const path: Path.Path
path.(property) Path.join: (...paths: ReadonlyArray<string>) => string
join("tmp", "file.txt")8 namespace console
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`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). 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`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
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:
```js
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
```
console.(method) Console.log(message?: any, ...optionalParams: any[]): void
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)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
```js
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()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.
log(const mypath: string
mypath)9})
First, install the Node.js-specific package:
npm install @effect/platform-node
pnpm add @effect/platform-node
yarn add @effect/platform-node
Update the program to load the Node.js-specific context:
1import { import Path
Path } from "@effect/platform"2import { import Effect
Effect } from "effect"3import { import NodeContext
NodeContext, import NodeRuntime
NodeRuntime } from "@effect/platform-node"4
5const const program: Effect.Effect<void, never, Path.Path>
program = import Effect
Effect.const gen: <YieldWrap<Tag<Path.Path, Path.Path>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Tag<Path.Path, Path.Path>>, void, never>) => Effect.Effect<...> (+1 overload)
gen(function* () {6 const const path: Path.Path
path = yield* import Path
Path.namespace Path
const Path: Tag<Path.Path, Path.Path>
Path7
8 const const mypath: string
mypath = const path: Path.Path
path.(property) Path.join: (...paths: ReadonlyArray<string>) => string
join("tmp", "file.txt")9 namespace console
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`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). 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`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
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:
```js
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
```
console.(method) Console.log(message?: any, ...optionalParams: any[]): void
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)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
```js
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()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.
log(const mypath: string
mypath)10})11
12import NodeRuntime
NodeRuntime.const runMain: RunMain
<never, void>(effect: Effect.Effect<void, never, never>, options?: {
readonly disableErrorReporting?: boolean | undefined;
readonly disablePrettyLogger?: boolean | undefined;
readonly teardown?: Teardown | undefined;
}) => void (+1 overload)
runMain(const program: Effect.Effect<void, never, Path.Path>
program.(method) Pipeable.pipe<Effect.Effect<void, never, Path.Path>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, Path.Path>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe(import Effect
Effect.const provide: <NodeContext.NodeContext, never, never>(layer: Layer<NodeContext.NodeContext, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)
Splits the context into two parts, providing one part using the
specified layer/context/runtime and leaving the remainder `R0`
provide(import NodeContext
NodeContext.const layer: Layer<NodeContext.NodeContext, never, never>
layer)))
Finally, run the program in Node.js using tsx
:
npx tsx index.ts
pnpm dlx tsx index.ts
yarn dlx tsx index.ts
To run the same program in Bun, first install the Bun-specific package:
bun add @effect/platform-bun
Update the program to use the Bun-specific context:
1import { import Path
Path } from "@effect/platform"2import { import Effect
Effect } from "effect"3import { import BunContext
BunContext, import BunRuntime
BunRuntime } from "@effect/platform-bun"4
5const const program: Effect.Effect<void, never, Path.Path>
program = import Effect
Effect.const gen: <YieldWrap<Tag<Path.Path, Path.Path>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Tag<Path.Path, Path.Path>>, void, never>) => Effect.Effect<...> (+1 overload)
gen(function* () {6 const const path: Path.Path
path = yield* import Path
Path.namespace Path
const Path: Tag<Path.Path, Path.Path>
Path7
8 const const mypath: string
mypath = const path: Path.Path
path.(property) Path.join: (...paths: ReadonlyArray<string>) => string
join("tmp", "file.txt")9 namespace console
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`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). 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`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
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:
```js
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
```
console.(method) Console.log(message?: any, ...optionalParams: any[]): void
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)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
```js
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()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.
log(const mypath: string
mypath)10})11
12import BunRuntime
BunRuntime.const runMain: RunMain
<never, void>(effect: Effect.Effect<void, never, never>, options?: {
readonly disableErrorReporting?: boolean | undefined;
readonly disablePrettyLogger?: boolean | undefined;
readonly teardown?: Teardown | undefined;
}) => void (+1 overload)
runMain(const program: Effect.Effect<void, never, Path.Path>
program.(method) Pipeable.pipe<Effect.Effect<void, never, Path.Path>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, Path.Path>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe(import Effect
Effect.const provide: <BunContext.BunContext, never, never>(layer: Layer<BunContext.BunContext, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)
Splits the context into two parts, providing one part using the
specified layer/context/runtime and leaving the remainder `R0`
provide(import BunContext
BunContext.const layer: Layer<BunContext.BunContext, never, never>
layer)))
Run the program in Bun:
bun index.tstmp/file.txt