@effectionx/effect-ts 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright 2024 The Frontside Software, Inc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,266 @@
1
+ # Effect-TS
2
+
3
+ Bidirectional interop between [Effect-TS](https://effect.website/) and [Effection](https://frontside.com/effection).
4
+
5
+ ## Why?
6
+
7
+ Effect and Effection are both powerful libraries for managing side effects in TypeScript,
8
+ but they have different philosophies and strengths:
9
+
10
+ | Feature | Effect | Effection |
11
+ |---------|--------|-----------|
12
+ | **Concurrency Model** | Fiber-based with supervision | Structured concurrency with scopes |
13
+ | **Error Handling** | Type-safe errors in signature | JavaScript throw/catch |
14
+ | **Dependencies** | Context/Layer system | Context API |
15
+ | **Syntax** | Generator or pipe-based | Generator-based |
16
+ | **Resource Management** | Scope with finalizers | Automatic cleanup on scope exit |
17
+
18
+ This package lets you use both together:
19
+
20
+ - **Use Effect inside Effection** when you want Effect's type-safe error handling
21
+ or need to use Effect-based libraries within Effection's structured concurrency
22
+ - **Use Effection inside Effect** when you want Effection's simple generator syntax
23
+ or need to use Effection-based libraries within an Effect application
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ npm install @effectionx/effect-ts
29
+ ```
30
+
31
+ **Peer dependencies:** Both `effect` (^3) and `effection` (^3 || ^4) must be installed.
32
+
33
+ ## Effection Host - Effect Guest
34
+
35
+ Use `makeEffectRuntime()` to run Effect programs inside Effection operations.
36
+
37
+ ### Basic Usage
38
+
39
+ ```ts
40
+ import { main } from "effection";
41
+ import { Effect } from "effect";
42
+ import { makeEffectRuntime } from "@effectionx/effect-ts";
43
+
44
+ await main(function* () {
45
+ // Create the Effect runtime (automatically disposed when scope ends)
46
+ const runtime = yield* makeEffectRuntime();
47
+
48
+ // Run Effect programs
49
+ const result = yield* runtime.run(
50
+ Effect.succeed(42).pipe(Effect.map(n => n * 2))
51
+ );
52
+
53
+ console.log(result); // 84
54
+ });
55
+ ```
56
+
57
+ ### Error Handling
58
+
59
+ Effect failures are thrown as JavaScript errors when using `run()`:
60
+
61
+ ```ts
62
+ import { main } from "effection";
63
+ import { Effect } from "effect";
64
+ import { makeEffectRuntime } from "@effectionx/effect-ts";
65
+
66
+ await main(function* () {
67
+ const runtime = yield* makeEffectRuntime();
68
+
69
+ try {
70
+ yield* runtime.run(Effect.fail(new Error("boom")));
71
+ } catch (error) {
72
+ console.log(error.message); // "boom"
73
+ }
74
+ });
75
+ ```
76
+
77
+ For type-safe error handling, use `runExit()` which returns an `Exit<A, E>`:
78
+
79
+ ```ts
80
+ import { main } from "effection";
81
+ import { Effect, Exit } from "effect";
82
+ import { makeEffectRuntime } from "@effectionx/effect-ts";
83
+
84
+ await main(function* () {
85
+ const runtime = yield* makeEffectRuntime();
86
+
87
+ const exit = yield* runtime.runExit(Effect.fail(new Error("boom")));
88
+
89
+ if (Exit.isFailure(exit)) {
90
+ // Access the full Cause<E> with error details
91
+ console.log(exit.cause);
92
+ } else {
93
+ // Access the success value
94
+ console.log(exit.value);
95
+ }
96
+ });
97
+ ```
98
+
99
+ ### With Effect Services
100
+
101
+ You can provide an Effect Layer to pre-configure services:
102
+
103
+ ```ts
104
+ import { main } from "effection";
105
+ import { Effect, Context, Layer } from "effect";
106
+ import { makeEffectRuntime } from "@effectionx/effect-ts";
107
+
108
+ // Define a service
109
+ class Logger extends Context.Tag("Logger")<Logger, {
110
+ log: (msg: string) => Effect.Effect<void>
111
+ }>() {}
112
+
113
+ const LoggerLive = Layer.succeed(Logger, {
114
+ log: (msg) => Effect.sync(() => console.log(msg))
115
+ });
116
+
117
+ await main(function* () {
118
+ // Provide layer to the runtime
119
+ const runtime = yield* makeEffectRuntime(LoggerLive);
120
+
121
+ // Effects can now use Logger without explicit provide
122
+ yield* runtime.run(
123
+ Effect.gen(function* () {
124
+ const logger = yield* Logger;
125
+ yield* logger.log("Hello!");
126
+ })
127
+ );
128
+ });
129
+ ```
130
+
131
+ Compose multiple layers using Effect's primitives:
132
+
133
+ ```ts
134
+ const AppLayer = Layer.mergeAll(DatabaseLive, LoggerLive, CacheLive);
135
+ const runtime = yield* makeEffectRuntime(AppLayer);
136
+ ```
137
+
138
+ ### Cancellation
139
+
140
+ When an Effection scope is halted, any running Effect programs are interrupted:
141
+
142
+ ```ts
143
+ import { main, spawn, sleep } from "effection";
144
+ import { Effect } from "effect";
145
+ import { makeEffectRuntime } from "@effectionx/effect-ts";
146
+
147
+ await main(function* () {
148
+ const runtime = yield* makeEffectRuntime();
149
+
150
+ const task = yield* spawn(function* () {
151
+ yield* runtime.run(
152
+ Effect.gen(function* () {
153
+ yield* Effect.addFinalizer(() => Effect.log("Effect interrupted!"));
154
+ yield* Effect.sleep("10 seconds");
155
+ }).pipe(Effect.scoped)
156
+ );
157
+ });
158
+
159
+ yield* sleep(100);
160
+ // Task is automatically halted when main scope ends
161
+ // Effect finalizer runs: "Effect interrupted!"
162
+ });
163
+ ```
164
+
165
+ ## Effect Host - Effection Guest
166
+
167
+ Use `makeEffectionRuntime()` to run Effection operations inside Effect programs.
168
+
169
+ ### Basic Usage
170
+
171
+ ```ts
172
+ import { Effect } from "effect";
173
+ import { sleep } from "effection";
174
+ import { makeEffectionRuntime, EffectionRuntime } from "@effectionx/effect-ts";
175
+
176
+ const program = Effect.gen(function* () {
177
+ const runtime = yield* EffectionRuntime;
178
+
179
+ const result = yield* runtime.run(function* () {
180
+ yield* sleep(100);
181
+ return "hello from effection";
182
+ });
183
+
184
+ return result.toUpperCase();
185
+ });
186
+
187
+ const result = await Effect.runPromise(
188
+ program.pipe(
189
+ Effect.provide(makeEffectionRuntime()),
190
+ Effect.scoped
191
+ )
192
+ );
193
+
194
+ console.log(result); // "HELLO FROM EFFECTION"
195
+ ```
196
+
197
+ ### Error Handling
198
+
199
+ Errors thrown in Effection operations become `UnknownException` in Effect:
200
+
201
+ ```ts
202
+ import { Effect, Exit } from "effect";
203
+ import { makeEffectionRuntime, EffectionRuntime } from "@effectionx/effect-ts";
204
+
205
+ const program = Effect.gen(function* () {
206
+ const runtime = yield* EffectionRuntime;
207
+
208
+ return yield* runtime.run(function* () {
209
+ throw new Error("boom");
210
+ });
211
+ });
212
+
213
+ const exit = await Effect.runPromiseExit(
214
+ program.pipe(
215
+ Effect.provide(makeEffectionRuntime()),
216
+ Effect.scoped
217
+ )
218
+ );
219
+
220
+ // exit is Exit.Failure with UnknownException containing the error
221
+ if (Exit.isFailure(exit)) {
222
+ console.log("Failed:", exit.cause);
223
+ }
224
+ ```
225
+
226
+ ### Cancellation
227
+
228
+ When the Effect scope ends or is interrupted, the Effection scope is closed:
229
+
230
+ ```ts
231
+ import { Effect, Fiber } from "effect";
232
+ import { suspend } from "effection";
233
+ import { makeEffectionRuntime, EffectionRuntime } from "@effectionx/effect-ts";
234
+
235
+ const program = Effect.gen(function* () {
236
+ const runtime = yield* EffectionRuntime;
237
+
238
+ const fiber = yield* runtime.run(function* () {
239
+ try {
240
+ yield* suspend();
241
+ } finally {
242
+ console.log("Effection cleanup!");
243
+ }
244
+ }).pipe(Effect.fork);
245
+
246
+ yield* Effect.sleep("100 millis");
247
+ yield* Fiber.interrupt(fiber);
248
+ // Logs: "Effection cleanup!"
249
+ });
250
+
251
+ await Effect.runPromise(
252
+ program.pipe(
253
+ Effect.provide(makeEffectionRuntime()),
254
+ Effect.scoped
255
+ )
256
+ );
257
+ ```
258
+
259
+ ## Comparison
260
+
261
+ | Aspect | Effection Host | | Effect Host |
262
+ |--------|----------------|---|-------------|
263
+ | **Method** | `EffectRuntime.run()` | `EffectRuntime.runExit()` | `EffectionRuntime.run()` |
264
+ | **Error Handling** | Throws JS error | Returns `Exit<A, E>` | Returns `UnknownException` |
265
+ | **Use When** | Simple cases | Need typed errors | Using Effection in Effect |
266
+ | **Cancellation** | Effection halt → Effect interrupt | Same | Effect interrupt → Effection halt |
@@ -0,0 +1,96 @@
1
+ import { type Effect, type Exit, Layer } from "effect";
2
+ import { type Operation } from "effection";
3
+ /**
4
+ * A runtime for executing Effect programs inside Effection operations.
5
+ *
6
+ * @typeParam R - The services/context provided by this runtime (from the layer)
7
+ */
8
+ export interface EffectRuntime<R = never> {
9
+ /**
10
+ * Run an Effect program and return its result as an Effection Operation.
11
+ *
12
+ * Effect failures will be thrown as JavaScript errors.
13
+ *
14
+ * @param effect - The Effect program to run
15
+ * @returns An Operation that yields the Effect's success value
16
+ * @throws The Effect's error `E` if it fails
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const runtime = yield* makeEffectRuntime();
21
+ * const result = yield* runtime.run(Effect.succeed(42));
22
+ * // result = 42
23
+ * ```
24
+ */
25
+ run<A, E>(effect: Effect.Effect<A, E, R>): Operation<A>;
26
+ /**
27
+ * Run an Effect program and return its Exit (success or failure).
28
+ *
29
+ * Unlike `run()`, this does not throw on failure. Instead, it returns
30
+ * an `Exit<A, E>` that you can inspect to determine success or failure.
31
+ * This preserves Effect's full error model including the Cause.
32
+ *
33
+ * @param effect - The Effect program to run
34
+ * @returns An Operation that yields the Effect's Exit
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * const runtime = yield* makeEffectRuntime();
39
+ * const exit = yield* runtime.runExit(Effect.fail(new Error("boom")));
40
+ * if (Exit.isFailure(exit)) {
41
+ * console.log(exit.cause); // Full Cause<E> with error details
42
+ * } else {
43
+ * console.log(exit.value); // Success value
44
+ * }
45
+ * ```
46
+ */
47
+ runExit<A, E>(effect: Effect.Effect<A, E, R>): Operation<Exit.Exit<A, E>>;
48
+ }
49
+ /**
50
+ * Create an EffectRuntime resource that manages an Effect ManagedRuntime.
51
+ *
52
+ * The ManagedRuntime is automatically disposed when the Effection scope ends,
53
+ * ensuring proper cleanup of Effect resources.
54
+ *
55
+ * @param layer - Optional Effect Layer to provide services. Defaults to `Layer.empty`.
56
+ * Users can compose multiple layers using Effect's `Layer.merge()`,
57
+ * `Layer.mergeAll()`, or `Layer.provide()` before passing.
58
+ * @returns An Operation that yields the EffectRuntime
59
+ *
60
+ * @example Basic usage
61
+ * ```ts
62
+ * import { run } from "effection";
63
+ * import { Effect } from "effect";
64
+ * import { makeEffectRuntime } from "@effectionx/effect";
65
+ *
66
+ * await run(function* () {
67
+ * const runtime = yield* makeEffectRuntime();
68
+ * const result = yield* runtime.run(Effect.succeed(42));
69
+ * console.log(result); // 42
70
+ * });
71
+ * ```
72
+ *
73
+ * @example With services
74
+ * ```ts
75
+ * import { Layer, Context, Effect } from "effect";
76
+ *
77
+ * class Logger extends Context.Tag("Logger")<Logger, { log: (msg: string) => Effect.Effect<void> }>() {}
78
+ * const LoggerLive = Layer.succeed(Logger, { log: (msg) => Effect.log(msg) });
79
+ *
80
+ * await run(function* () {
81
+ * const runtime = yield* makeEffectRuntime(LoggerLive);
82
+ * yield* runtime.run(Effect.gen(function* () {
83
+ * const logger = yield* Logger;
84
+ * yield* logger.log("Hello!");
85
+ * }));
86
+ * });
87
+ * ```
88
+ *
89
+ * @example Composing multiple layers
90
+ * ```ts
91
+ * const AppLayer = Layer.mergeAll(DatabaseLive, LoggerLive, CacheLive);
92
+ * const runtime = yield* makeEffectRuntime(AppLayer);
93
+ * ```
94
+ */
95
+ export declare function makeEffectRuntime<R = never>(layer?: Layer.Layer<R, never, never>): Operation<EffectRuntime<R>>;
96
+ //# sourceMappingURL=effect-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effect-runtime.d.ts","sourceRoot":"","sources":["../effect-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,IAAI,EAAE,KAAK,EAAkB,MAAM,QAAQ,CAAC;AACvE,OAAO,EAAE,KAAK,SAAS,EAA0B,MAAM,WAAW,CAAC;AAEnE;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,KAAK;IACtC;;;;;;;;;;;;;;;OAeG;IACH,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAExD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;CAC3E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,KAAK,EACzC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,GACnC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAoC7B"}
@@ -0,0 +1,77 @@
1
+ import { Layer, ManagedRuntime } from "effect";
2
+ import { action, call, resource } from "effection";
3
+ /**
4
+ * Create an EffectRuntime resource that manages an Effect ManagedRuntime.
5
+ *
6
+ * The ManagedRuntime is automatically disposed when the Effection scope ends,
7
+ * ensuring proper cleanup of Effect resources.
8
+ *
9
+ * @param layer - Optional Effect Layer to provide services. Defaults to `Layer.empty`.
10
+ * Users can compose multiple layers using Effect's `Layer.merge()`,
11
+ * `Layer.mergeAll()`, or `Layer.provide()` before passing.
12
+ * @returns An Operation that yields the EffectRuntime
13
+ *
14
+ * @example Basic usage
15
+ * ```ts
16
+ * import { run } from "effection";
17
+ * import { Effect } from "effect";
18
+ * import { makeEffectRuntime } from "@effectionx/effect";
19
+ *
20
+ * await run(function* () {
21
+ * const runtime = yield* makeEffectRuntime();
22
+ * const result = yield* runtime.run(Effect.succeed(42));
23
+ * console.log(result); // 42
24
+ * });
25
+ * ```
26
+ *
27
+ * @example With services
28
+ * ```ts
29
+ * import { Layer, Context, Effect } from "effect";
30
+ *
31
+ * class Logger extends Context.Tag("Logger")<Logger, { log: (msg: string) => Effect.Effect<void> }>() {}
32
+ * const LoggerLive = Layer.succeed(Logger, { log: (msg) => Effect.log(msg) });
33
+ *
34
+ * await run(function* () {
35
+ * const runtime = yield* makeEffectRuntime(LoggerLive);
36
+ * yield* runtime.run(Effect.gen(function* () {
37
+ * const logger = yield* Logger;
38
+ * yield* logger.log("Hello!");
39
+ * }));
40
+ * });
41
+ * ```
42
+ *
43
+ * @example Composing multiple layers
44
+ * ```ts
45
+ * const AppLayer = Layer.mergeAll(DatabaseLive, LoggerLive, CacheLive);
46
+ * const runtime = yield* makeEffectRuntime(AppLayer);
47
+ * ```
48
+ */
49
+ export function makeEffectRuntime(layer) {
50
+ return resource(function* (provide) {
51
+ const managedRuntime = ManagedRuntime.make(layer ?? Layer.empty);
52
+ const run = (effect) => {
53
+ return action((resolve, reject) => {
54
+ const controller = new AbortController();
55
+ managedRuntime
56
+ .runPromise(effect, { signal: controller.signal })
57
+ .then(resolve, reject);
58
+ return () => controller.abort();
59
+ });
60
+ };
61
+ const runExit = (effect) => {
62
+ return action((resolve, reject) => {
63
+ const controller = new AbortController();
64
+ managedRuntime
65
+ .runPromiseExit(effect, { signal: controller.signal })
66
+ .then(resolve, reject);
67
+ return () => controller.abort();
68
+ });
69
+ };
70
+ try {
71
+ yield* provide({ run, runExit });
72
+ }
73
+ finally {
74
+ yield* call(() => managedRuntime.dispose());
75
+ }
76
+ });
77
+ }
@@ -0,0 +1,100 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import type { UnknownException } from "effect/Cause";
3
+ import { type Operation, type Scope } from "effection";
4
+ /**
5
+ * A runtime for executing Effection operations inside Effect programs.
6
+ */
7
+ export interface EffectionRuntime {
8
+ /**
9
+ * Run an Effection operation and return its result as an Effect.
10
+ *
11
+ * Errors thrown in the operation become `UnknownException` in Effect.
12
+ * The Effection scope is automatically cleaned up when the Effect completes
13
+ * or is interrupted.
14
+ *
15
+ * @param operation - The Effection operation (generator function) to run
16
+ * @returns An Effect that yields the operation's result
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const program = Effect.gen(function* () {
21
+ * const runtime = yield* EffectionRuntime;
22
+ * return yield* runtime.run(function* () {
23
+ * yield* sleep(100);
24
+ * return "hello";
25
+ * });
26
+ * });
27
+ * ```
28
+ */
29
+ run<T>(operation: () => Operation<T>): Effect.Effect<T, UnknownException>;
30
+ }
31
+ /**
32
+ * Effect Context Tag for accessing the EffectionRuntime.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * const program = Effect.gen(function* () {
37
+ * const runtime = yield* EffectionRuntime;
38
+ * // use runtime.run(...)
39
+ * });
40
+ * ```
41
+ */
42
+ export declare const EffectionRuntime: Context.Tag<EffectionRuntime, EffectionRuntime>;
43
+ /**
44
+ * Create an Effect Layer that provides an EffectionRuntime.
45
+ *
46
+ * The Effection scope is automatically closed when the Effect scope ends,
47
+ * ensuring proper cleanup of Effection resources.
48
+ *
49
+ * @param parent - Optional parent Effection scope. If provided, the runtime's
50
+ * scope will inherit all contexts from the parent scope.
51
+ * @returns An Effect Layer providing EffectionRuntime
52
+ *
53
+ * @example Basic usage
54
+ * ```ts
55
+ * import { Effect } from "effect";
56
+ * import { sleep } from "effection";
57
+ * import { makeEffectionRuntime, EffectionRuntime } from "@effectionx/effect";
58
+ *
59
+ * const program = Effect.gen(function* () {
60
+ * const runtime = yield* EffectionRuntime;
61
+ * const result = yield* runtime.run(function* () {
62
+ * yield* sleep(100);
63
+ * return "hello from effection";
64
+ * });
65
+ * return result;
66
+ * });
67
+ *
68
+ * await Effect.runPromise(
69
+ * program.pipe(
70
+ * Effect.provide(makeEffectionRuntime()),
71
+ * Effect.scoped
72
+ * )
73
+ * );
74
+ * ```
75
+ *
76
+ * @example With parent scope (to inherit Effection contexts)
77
+ * ```ts
78
+ * import { Effect } from "effect";
79
+ * import { useScope } from "effection";
80
+ * import { makeEffectionRuntime, EffectionRuntime } from "@effectionx/effect";
81
+ *
82
+ * function* myOperation() {
83
+ * const scope = yield* useScope();
84
+ * const result = yield* call(() =>
85
+ * Effect.runPromise(
86
+ * Effect.gen(function* () {
87
+ * const runtime = yield* EffectionRuntime;
88
+ * return yield* runtime.run(function* () {
89
+ * // Can access Effection contexts from parent scope
90
+ * return "hello";
91
+ * });
92
+ * }).pipe(Effect.provide(makeEffectionRuntime(scope)), Effect.scoped)
93
+ * )
94
+ * );
95
+ * return result;
96
+ * }
97
+ * ```
98
+ */
99
+ export declare function makeEffectionRuntime(parent?: Scope): Layer.Layer<EffectionRuntime>;
100
+ //# sourceMappingURL=effection-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effection-runtime.d.ts","sourceRoot":"","sources":["../effection-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,KAAK,EAAe,MAAM,WAAW,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;CAC3E;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,iDAC6B,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,CAAC,EAAE,KAAK,GACb,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAqB/B"}
@@ -0,0 +1,82 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import { createScope } from "effection";
3
+ /**
4
+ * Effect Context Tag for accessing the EffectionRuntime.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * const program = Effect.gen(function* () {
9
+ * const runtime = yield* EffectionRuntime;
10
+ * // use runtime.run(...)
11
+ * });
12
+ * ```
13
+ */
14
+ export const EffectionRuntime = Context.GenericTag("EffectionRuntime");
15
+ /**
16
+ * Create an Effect Layer that provides an EffectionRuntime.
17
+ *
18
+ * The Effection scope is automatically closed when the Effect scope ends,
19
+ * ensuring proper cleanup of Effection resources.
20
+ *
21
+ * @param parent - Optional parent Effection scope. If provided, the runtime's
22
+ * scope will inherit all contexts from the parent scope.
23
+ * @returns An Effect Layer providing EffectionRuntime
24
+ *
25
+ * @example Basic usage
26
+ * ```ts
27
+ * import { Effect } from "effect";
28
+ * import { sleep } from "effection";
29
+ * import { makeEffectionRuntime, EffectionRuntime } from "@effectionx/effect";
30
+ *
31
+ * const program = Effect.gen(function* () {
32
+ * const runtime = yield* EffectionRuntime;
33
+ * const result = yield* runtime.run(function* () {
34
+ * yield* sleep(100);
35
+ * return "hello from effection";
36
+ * });
37
+ * return result;
38
+ * });
39
+ *
40
+ * await Effect.runPromise(
41
+ * program.pipe(
42
+ * Effect.provide(makeEffectionRuntime()),
43
+ * Effect.scoped
44
+ * )
45
+ * );
46
+ * ```
47
+ *
48
+ * @example With parent scope (to inherit Effection contexts)
49
+ * ```ts
50
+ * import { Effect } from "effect";
51
+ * import { useScope } from "effection";
52
+ * import { makeEffectionRuntime, EffectionRuntime } from "@effectionx/effect";
53
+ *
54
+ * function* myOperation() {
55
+ * const scope = yield* useScope();
56
+ * const result = yield* call(() =>
57
+ * Effect.runPromise(
58
+ * Effect.gen(function* () {
59
+ * const runtime = yield* EffectionRuntime;
60
+ * return yield* runtime.run(function* () {
61
+ * // Can access Effection contexts from parent scope
62
+ * return "hello";
63
+ * });
64
+ * }).pipe(Effect.provide(makeEffectionRuntime(scope)), Effect.scoped)
65
+ * )
66
+ * );
67
+ * return result;
68
+ * }
69
+ * ```
70
+ */
71
+ export function makeEffectionRuntime(parent) {
72
+ return Layer.scoped(EffectionRuntime, Effect.gen(function* () {
73
+ const [scope, close] = createScope(parent);
74
+ const run = (operation) => {
75
+ return Effect.tryPromise(() => scope.run(operation));
76
+ };
77
+ yield* Effect.addFinalizer(() => Effect.gen(function* () {
78
+ yield* Effect.tryPromise(() => close()).pipe(Effect.exit);
79
+ }));
80
+ return { run };
81
+ }));
82
+ }
package/dist/mod.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export { makeEffectRuntime } from "./effect-runtime.ts";
2
+ export type { EffectRuntime } from "./effect-runtime.ts";
3
+ export { EffectionRuntime, makeEffectionRuntime } from "./effection-runtime.ts";
4
+ export type { EffectionRuntime as EffectionRuntimeType } from "./effection-runtime.ts";
5
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../mod.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAChF,YAAY,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/mod.js ADDED
@@ -0,0 +1,4 @@
1
+ // Effect -> Effection
2
+ export { makeEffectRuntime } from "./effect-runtime.js";
3
+ // Effection -> Effect
4
+ export { EffectionRuntime, makeEffectionRuntime } from "./effection-runtime.js";