mini-effect 0.0.5 → 0.0.7
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/README.md +100 -10
- package/dist/concurrency.d.mts +4 -4
- package/dist/concurrency.mjs +16 -5
- package/dist/fetch.d.mts +5 -5
- package/dist/mini-effect.d.mts +42 -27
- package/dist/mini-effect.mjs +45 -34
- package/dist/schema.d.mts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,7 +19,17 @@ npm install mini-effect
|
|
|
19
19
|
## Core
|
|
20
20
|
|
|
21
21
|
```typescript
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
fn,
|
|
24
|
+
succeed,
|
|
25
|
+
fail,
|
|
26
|
+
gen,
|
|
27
|
+
pipe,
|
|
28
|
+
run,
|
|
29
|
+
catchSome,
|
|
30
|
+
dependency,
|
|
31
|
+
retry,
|
|
32
|
+
} from "mini-effect";
|
|
23
33
|
```
|
|
24
34
|
|
|
25
35
|
### Create Effects
|
|
@@ -74,6 +84,24 @@ pipe(
|
|
|
74
84
|
);
|
|
75
85
|
```
|
|
76
86
|
|
|
87
|
+
### Retry
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// Retry up to 3 times before failing
|
|
91
|
+
const resilient = retry(
|
|
92
|
+
3,
|
|
93
|
+
fn(() => fetchUnreliableData()),
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
// Retry forever until success
|
|
97
|
+
const persistent = retry(
|
|
98
|
+
"forever",
|
|
99
|
+
fn(() => pollUntilReady()),
|
|
100
|
+
);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
When `times` is a number, the effect is retried up to that many times; if it still fails, the last error propagates. When `times` is `"forever"`, retries are unlimited and the error type narrows to `never`.
|
|
104
|
+
|
|
77
105
|
### Execution
|
|
78
106
|
|
|
79
107
|
```typescript
|
|
@@ -81,6 +109,60 @@ const result = await run(effect);
|
|
|
81
109
|
const result = await run(effect, abortController.signal);
|
|
82
110
|
```
|
|
83
111
|
|
|
112
|
+
## Dependencies
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { dependency, gen, run } from "mini-effect";
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`dependency` creates a typed tag that represents a value your effects need at runtime. Use `yield*` to read a dependency and `.provide()` to supply it.
|
|
119
|
+
|
|
120
|
+
### Define a Dependency
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
const UserName = dependency("UserName")<string>();
|
|
124
|
+
const Logger = dependency("Logger")<{ log: (msg: string) => void }>();
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Read Dependencies in Effects
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
const sayHello = gen(function* () {
|
|
131
|
+
const name = yield* UserName;
|
|
132
|
+
return `Hello, ${name}`;
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Provide Dependencies via Pipe
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const result = await run(sayHello.pipe(UserName.provide("Alice")));
|
|
140
|
+
// => "Hello, Alice"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Compose Across Effects
|
|
144
|
+
|
|
145
|
+
Dependencies propagate through `yield*` — provide them at any level:
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
const program = gen(function* () {
|
|
149
|
+
const message = yield* sayHello;
|
|
150
|
+
return message;
|
|
151
|
+
}).pipe(UserName.provide("GPT"));
|
|
152
|
+
|
|
153
|
+
await run(program);
|
|
154
|
+
// => "Hello, GPT"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Missing Dependencies
|
|
158
|
+
|
|
159
|
+
If a dependency is not provided, the effect fails with an `Error`:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
await run(sayHello);
|
|
163
|
+
// throws Error("Missing dependency: UserName")
|
|
164
|
+
```
|
|
165
|
+
|
|
84
166
|
## Concurrency
|
|
85
167
|
|
|
86
168
|
```typescript
|
|
@@ -155,15 +237,23 @@ Re-exports all of [Valibot](https://valibot.dev/).
|
|
|
155
237
|
|
|
156
238
|
### `mini-effect`
|
|
157
239
|
|
|
158
|
-
| Export
|
|
159
|
-
|
|
|
160
|
-
| `fn`
|
|
161
|
-
| `succeed`
|
|
162
|
-
| `fail`
|
|
163
|
-
| `gen`
|
|
164
|
-
| `pipe`
|
|
165
|
-
| `run`
|
|
166
|
-
| `catchSome`
|
|
240
|
+
| Export | Signature |
|
|
241
|
+
| ------------ | ---------------------------------------------------------------- |
|
|
242
|
+
| `fn` | `(thunk: (signal: AbortSignal) => T \| Promise<T>) => Effect<T>` |
|
|
243
|
+
| `succeed` | `(value: T) => Effect<T, never>` |
|
|
244
|
+
| `fail` | `(error: E) => Effect<never, E>` |
|
|
245
|
+
| `gen` | `(generator: (signal) => Generator<Effect>) => Effect` |
|
|
246
|
+
| `pipe` | `(effect, ...fns) => Effect` |
|
|
247
|
+
| `run` | `(effect, signal?) => Promise<T>` |
|
|
248
|
+
| `catchSome` | `(handler: (cause) => Effect \| undefined) => WrapEffect` |
|
|
249
|
+
| `dependency` | `(tag: string) => <T>() => Dependency<tag, T>` |
|
|
250
|
+
| `retry` | `(times: number \| "forever", effect) => Effect` |
|
|
251
|
+
|
|
252
|
+
#### `Dependency<D, T>`
|
|
253
|
+
|
|
254
|
+
| Member | Signature |
|
|
255
|
+
| --------- | ------------------------- |
|
|
256
|
+
| `provide` | `(instance: T) => Effect` |
|
|
167
257
|
|
|
168
258
|
### `mini-effect/concurrency`
|
|
169
259
|
|
package/dist/concurrency.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Effect, inferError, inferReturn } from "./mini-effect.mjs";
|
|
1
|
+
import { Effect, inferDependency, inferError, inferProvides, inferReturn } from "./mini-effect.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/concurrency.d.ts
|
|
4
|
-
declare const fork: <const E extends Effect
|
|
5
|
-
declare const all: <const E extends Effect<any, any>[]>(values: E) => Effect<{ [K in keyof E]: inferReturn<E[K]> }, inferError<E[number]>>;
|
|
4
|
+
declare const fork: <const E extends Effect>(effect: E) => Effect<() => void, never, never, never>;
|
|
5
|
+
declare const all: <const E extends Effect<any, any>[]>(values: E) => Effect<{ [K in keyof E]: inferReturn<E[K]> }, inferError<E[number]>, inferDependency<E[number]>, inferProvides<E[number]>>;
|
|
6
6
|
declare const allSettled: <const E extends Effect<any, any>[]>(values: E) => Effect<{ [K in keyof E]: PromiseSettledResult<inferReturn<E[K]>> }, inferError<E[number]>>;
|
|
7
|
-
declare const any: <const E extends Effect
|
|
7
|
+
declare const any: <const E extends Effect[]>(values: E) => Effect<inferReturn<E[number]>, inferError<E[number]>, inferDependency<E[number]>, inferProvides<E[number]>>;
|
|
8
8
|
declare const race: <const E extends Effect<any, any>[]>(values: E) => Effect<inferReturn<E[number]>, inferError<E[number]>>;
|
|
9
9
|
//#endregion
|
|
10
10
|
export { all, allSettled, any, fork, race };
|
package/dist/concurrency.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fn, run } from "./mini-effect.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/concurrency.ts
|
|
4
4
|
const localController = (signal) => {
|
|
@@ -6,16 +6,27 @@ const localController = (signal) => {
|
|
|
6
6
|
signal.addEventListener("abort", () => controller.abort(signal.reason));
|
|
7
7
|
return controller;
|
|
8
8
|
};
|
|
9
|
-
const fork = (effect) => fn((signal) => {
|
|
9
|
+
const fork = (effect) => fn((signal, ctx) => {
|
|
10
10
|
const controller = localController(signal);
|
|
11
|
-
run(effect, controller.signal).catch();
|
|
11
|
+
run(effect, controller.signal, ctx).catch();
|
|
12
12
|
return () => controller.abort();
|
|
13
13
|
});
|
|
14
|
-
const promiseMethod = (method, values) => fn(async (signal) => {
|
|
14
|
+
const promiseMethod = (method, values) => fn(async (signal, ctx) => {
|
|
15
15
|
let controller = localController(signal);
|
|
16
16
|
let localSignal = controller.signal;
|
|
17
|
+
let result;
|
|
18
|
+
let done;
|
|
19
|
+
let raceController = new AbortController();
|
|
17
20
|
try {
|
|
18
|
-
|
|
21
|
+
let promise = Promise[method](values.map((effect) => run(effect, localSignal, ctx)));
|
|
22
|
+
result = await Promise.race([promise, new Promise((resolve, reject) => {
|
|
23
|
+
done = resolve;
|
|
24
|
+
signal.addEventListener("abort", () => reject(signal.reason), { signal: raceController.signal });
|
|
25
|
+
})]);
|
|
26
|
+
raceController.abort();
|
|
27
|
+
done?.();
|
|
28
|
+
done = void 0;
|
|
29
|
+
return result;
|
|
19
30
|
} finally {
|
|
20
31
|
if (!controller.signal.aborted) controller.abort();
|
|
21
32
|
}
|
package/dist/fetch.d.mts
CHANGED
|
@@ -5,10 +5,10 @@ import { Failure, FailureConstructor } from "./tag.mjs";
|
|
|
5
5
|
declare const FailedToFetchError: FailureConstructor<"FailedToFetch">;
|
|
6
6
|
declare const FailedToReadError: FailureConstructor<"FailedToRead">;
|
|
7
7
|
declare const request: (input: string | URL, init?: RequestInit) => Effect<Response, InstanceType<typeof FailedToFetchError>>;
|
|
8
|
-
declare const blob: (response: Response) => Effect<Blob, Failure<"FailedToRead"
|
|
9
|
-
declare const bytes: (response: Response) => Effect<Uint8Array<ArrayBuffer>, Failure<"FailedToRead"
|
|
10
|
-
declare const formData: (response: Response) => Effect<FormData, Failure<"FailedToRead"
|
|
11
|
-
declare const json: (response: Response) => Effect<unknown, InstanceType<typeof FailedToReadError
|
|
12
|
-
declare const text: (response: Response) => Effect<string, Failure<"FailedToRead"
|
|
8
|
+
declare const blob: (response: Response) => Effect<Blob, Failure<"FailedToRead">, never, never>;
|
|
9
|
+
declare const bytes: (response: Response) => Effect<Uint8Array<ArrayBuffer>, Failure<"FailedToRead">, never, never>;
|
|
10
|
+
declare const formData: (response: Response) => Effect<FormData, Failure<"FailedToRead">, never, never>;
|
|
11
|
+
declare const json: (response: Response) => Effect<unknown, InstanceType<typeof FailedToReadError>, never, never>;
|
|
12
|
+
declare const text: (response: Response) => Effect<string, Failure<"FailedToRead">, never, never>;
|
|
13
13
|
//#endregion
|
|
14
14
|
export { blob, bytes, formData, json, request, text };
|
package/dist/mini-effect.d.mts
CHANGED
|
@@ -1,42 +1,57 @@
|
|
|
1
1
|
//#region src/mini-effect.d.ts
|
|
2
2
|
declare const SYMBOL: SymbolConstructor;
|
|
3
|
-
declare const
|
|
3
|
+
declare const DEPENDENCY_TYPE: unique symbol;
|
|
4
|
+
declare const DEPENDENCY: unique symbol;
|
|
5
|
+
declare const PROVIDES_TYPE: unique symbol;
|
|
6
|
+
declare const PROVIDER: unique symbol;
|
|
7
|
+
declare const HANDLES_ERROR: unique symbol;
|
|
4
8
|
declare const RUN: unique symbol;
|
|
5
9
|
declare const ERROR: unique symbol;
|
|
6
|
-
declare const run: <T, E$1>(effect: Effect<T, E$1>, signal?: AbortSignal) => Promise<T>;
|
|
7
|
-
declare const fn: <R$1, C = never>(thunk: Thunk<R$1>) => Effect<R$1, C>;
|
|
8
|
-
declare const fail: <C>(cause: C) => Effect<never, C>;
|
|
9
|
-
declare const succeed: <R$1>(result: R$1) => Effect<R$1, never>;
|
|
10
|
-
declare const catchSome: <T = any, C = any, CE = any>(thunk: (cause: unknown) => Effect<T, C> | undefined) => WrapEffect<T, C, CE>;
|
|
11
|
-
declare const
|
|
10
|
+
declare const run: <T, E$1>(effect: Effect<T, E$1>, signal?: AbortSignal, ctx?: Record<string, unknown>) => Promise<T>;
|
|
11
|
+
declare const fn: <R$1, C = never>(thunk: Thunk<R$1>) => Effect<R$1, C, never, never>;
|
|
12
|
+
declare const fail: <C>(cause: C) => Effect<never, C, never, never>;
|
|
13
|
+
declare const succeed: <R$1>(result: R$1) => Effect<R$1, never, never, never>;
|
|
14
|
+
declare const catchSome: <T = any, C = any, CE = any, D$1 = any, P$1 = any>(thunk: (cause: unknown) => Effect<T, C, D$1, P$1> | undefined) => WrapEffect<T, C, CE, D$1, P$1>;
|
|
15
|
+
declare const dependency: <D$1 extends string>(tag: D$1) => <T>() => Dependency<D$1, T>;
|
|
16
|
+
declare const gen: <T extends Effect, TReturn, TNext>(thunk: (signal: AbortSignal, ctx: Record<string, unknown>) => Generator<T, TReturn, TNext>, localContext?: boolean) => Effect<TReturn, inferError<T>, Exclude<inferDependency<T>, inferProvides<T>>, inferProvides<T>>;
|
|
12
17
|
declare const pipe: <F extends Effect, P$1 extends [Pipeable, ...Pipeable[]]>(first: F, ...pipeable: PipeReturn<[F, ...P$1]> extends never ? never : P$1) => PipeReturn<[F, ...P$1]>;
|
|
13
|
-
declare const retry: <R$1 extends number | "forever", T, C>(times: R$1, effect: Effect<T, C>) => Effect<T, R$1 extends "forever" ? never : C>;
|
|
14
|
-
declare class Effect<T = any, C = any> {
|
|
15
|
-
[RUN]?:
|
|
18
|
+
declare const retry: <R$1 extends number | "forever", T, C, D$1, P$1>(times: R$1, effect: Effect<T, C, D$1, P$1>) => Effect<T, R$1 extends "forever" ? never : C, D$1, P$1>;
|
|
19
|
+
declare class Effect<T = any, C = any, D$1 = any, P$1 = any> {
|
|
20
|
+
[RUN]?: Thunk<T>;
|
|
16
21
|
[ERROR]?: (cause: unknown) => Effect | undefined;
|
|
17
|
-
|
|
18
|
-
[
|
|
19
|
-
|
|
22
|
+
[DEPENDENCY_TYPE]: D$1;
|
|
23
|
+
[PROVIDES_TYPE]: P$1;
|
|
24
|
+
constructor(run?: Thunk<T>, catchSome?: (cause: unknown) => Effect | undefined);
|
|
25
|
+
[SYMBOL.iterator](): Generator<Effect<T, C, D$1, P$1>, T, any>;
|
|
26
|
+
readonly pipe: <E$1 extends [Pipeable, ...Pipeable[]]>(...pipeable: E$1) => PipeReturn<[Effect<T, C, D$1, P$1>, ...E$1]>;
|
|
20
27
|
}
|
|
21
|
-
declare class WrapEffect<T = any, C = any, CE = any> {
|
|
22
|
-
readonly [
|
|
23
|
-
readonly [ERROR]?: (cause: unknown) => Effect<any, any> | undefined;
|
|
24
|
-
readonly [REMOVE]: CE;
|
|
25
|
-
constructor(run?: (signal: AbortSignal) => PromiseLike<T> | T, catchSome?: (cause: unknown) => Effect | undefined);
|
|
26
|
-
[SYMBOL.iterator](): Generator<Effect<T, C>, T, any>;
|
|
28
|
+
declare class WrapEffect<T = any, C = any, CE = any, D$1 = any, P$1 = any> extends Effect<T, C, D$1, P$1> {
|
|
29
|
+
readonly [HANDLES_ERROR]: CE;
|
|
27
30
|
}
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
declare class Dependency<D$1 extends string = any, T = any> extends WrapEffect<T, never, Dependency<D$1, T>, Dependency<D$1, T>, never> {
|
|
32
|
+
readonly [DEPENDENCY]: true;
|
|
33
|
+
readonly __tag: D$1;
|
|
34
|
+
constructor(tag: D$1);
|
|
35
|
+
readonly provide: (instance: T) => Provide<D$1, T>;
|
|
36
|
+
}
|
|
37
|
+
declare class Provide<D$1 extends string = any, T = any> extends Effect<void, never, never, Dependency<D$1, T>> {
|
|
38
|
+
readonly [PROVIDER] = true;
|
|
39
|
+
constructor(tag: D$1, instance: T);
|
|
40
|
+
}
|
|
41
|
+
type Thunk<out R$1> = (signal: AbortSignal, ctx: Record<string, unknown>) => R$1 | PromiseLike<R$1>;
|
|
42
|
+
type PipeableThunk<out T = any, out C = any, in I = any, out D$1 = never, out P$1 = never> = (next: I) => Effect<T, C, D$1, P$1>;
|
|
30
43
|
type Pipeable = PipeableThunk | Effect | WrapEffect;
|
|
31
|
-
type inferInput<T> = T extends PipeableThunk<any, any, infer I> ? I : never;
|
|
32
|
-
type inferReturn<T> = T extends
|
|
44
|
+
type inferInput<T> = T extends PipeableThunk<any, any, infer I> ? I : T extends Effect ? any : never;
|
|
45
|
+
type inferReturn<T> = T extends PipeableThunk<infer R> ? R : T extends WrapEffect<infer R> ? R : T extends Effect<infer R> ? R : never;
|
|
33
46
|
type inferError<T> = T extends PipeableThunk<any, infer E> ? E : T extends WrapEffect<any, infer E> ? E : T extends Effect<any, infer E> ? E : never;
|
|
34
47
|
type inferExclude<T> = T extends WrapEffect<any, any, infer CE> ? CE : never;
|
|
35
|
-
type
|
|
36
|
-
type
|
|
37
|
-
type
|
|
48
|
+
type inferDependency<T> = T extends Dependency<infer A, infer B> ? Dependency<A, B> : T extends Effect<any, any, infer D> ? D : never;
|
|
49
|
+
type inferProvides<T> = T extends Provide<infer D, infer T> ? Dependency<D, T> : T extends Effect<any, any, any, infer D> ? D : never;
|
|
50
|
+
type Simplify<T> = T extends Effect<infer R, infer E, infer D, infer P> ? Effect<R, E, D, P> : never;
|
|
51
|
+
type PipeReturn<F extends Pipeable[]> = IsNever<CheckPipe<F>> extends true ? never : Simplify<Effect<inferReturn<CheckPipe<F>> | inferReturn<Extract<F[number], WrapEffect>>, Exclude<inferError<F[number]>, inferExclude<Extract<F[number], WrapEffect>>>, Exclude<inferDependency<F[number]>, inferProvides<F[number]>>, Exclude<inferProvides<F[number]>, inferDependency<F[number]>>>>;
|
|
52
|
+
type CheckPipe<F extends Pipeable[]> = F extends [Effect, Provide, ...infer R] ? R extends [Pipeable, ...Pipeable[]] ? CheckPipe<R> : F[0] : F extends [Effect, WrapEffect, ...infer R] ? R extends [Pipeable, ...Pipeable[]] ? CheckPipe<R> : F[0] : F extends [Pipeable, Pipeable, ...infer P] ? ExtendsStrict<inferReturn<F[0]>, inferInput<F[1]>> extends true ? P extends Pipeable[] ? CheckPipe<[F[1], ...P]> : never : never : F extends [WrapEffect] ? Effect<inferReturn<F[0]>> : F extends [Pipeable] ? F[0] : never;
|
|
38
53
|
type IsNever<T> = [T] extends [never] ? true : false;
|
|
39
54
|
type IsAny<T> = 0 extends 1 & NoInfer<T> ? true : false;
|
|
40
55
|
type ExtendsStrict<Left, Right> = IsAny<Left | Right> extends true ? true : IsNever<Left> extends true ? IsNever<Right> : [Left] extends [Right] ? true : false;
|
|
41
56
|
//#endregion
|
|
42
|
-
export { Effect, Pipeable, PipeableThunk, Thunk, WrapEffect,
|
|
57
|
+
export { Dependency, Effect, Pipeable, PipeableThunk, Thunk, WrapEffect, catchSome, dependency, fail, fn, gen, inferDependency, inferError, inferExclude, inferInput, inferProvides, inferReturn, pipe, retry, run, succeed };
|
package/dist/mini-effect.mjs
CHANGED
|
@@ -1,24 +1,33 @@
|
|
|
1
1
|
//#region src/mini-effect.ts
|
|
2
2
|
const SYMBOL = Symbol;
|
|
3
|
-
const
|
|
3
|
+
const DEPENDENCY_TYPE = /* @__PURE__ */ SYMBOL();
|
|
4
|
+
const DEPENDENCY = /* @__PURE__ */ SYMBOL();
|
|
5
|
+
const PROVIDES_TYPE = /* @__PURE__ */ SYMBOL();
|
|
6
|
+
const PROVIDER = /* @__PURE__ */ SYMBOL();
|
|
7
|
+
const HANDLES_ERROR = /* @__PURE__ */ SYMBOL();
|
|
4
8
|
const RUN = SYMBOL();
|
|
5
9
|
const ERROR = SYMBOL();
|
|
6
10
|
const DEFAULT_SIGNAL = new AbortController().signal;
|
|
7
11
|
const isFunction = (value) => typeof value === "function";
|
|
8
|
-
const quickYieldResult = (iterator, signal, ret) => {
|
|
12
|
+
const quickYieldResult = (iterator, signal, ctx, ret) => {
|
|
9
13
|
ret = iterator.next(ret);
|
|
10
|
-
return ret.done ? ret.value : run(ret.value, signal).then((r) => quickYieldResult(iterator, signal, r));
|
|
14
|
+
return ret.done ? ret.value : run(ret.value, signal, ctx).then((r) => quickYieldResult(iterator, signal, ctx, r));
|
|
11
15
|
};
|
|
12
|
-
const run = (effect, signal) => new Promise((resolve) => resolve(effect[RUN](signal ?? DEFAULT_SIGNAL)));
|
|
16
|
+
const run = (effect, signal, ctx) => new Promise((resolve) => resolve(effect[RUN](signal ?? DEFAULT_SIGNAL, ctx ?? {})));
|
|
13
17
|
const fn = (thunk) => new Effect(thunk);
|
|
14
18
|
const fail = (cause) => fn(() => {
|
|
15
19
|
throw cause;
|
|
16
20
|
});
|
|
17
21
|
const succeed = (result) => fn(() => result);
|
|
18
22
|
const catchSome = (thunk) => new WrapEffect(void 0, thunk);
|
|
19
|
-
const
|
|
23
|
+
const dependency = (tag) => () => new Dependency(tag);
|
|
24
|
+
const gen = (thunk, localContext) => fn((signal, ctx) => {
|
|
25
|
+
let ctxOverride = localContext ? { ...ctx } : ctx;
|
|
26
|
+
return quickYieldResult(thunk(signal, ctxOverride), signal, ctxOverride);
|
|
27
|
+
});
|
|
20
28
|
const wrapEffect = (pipe$1, onErr) => new WrapEffect(pipe$1[RUN], (cause) => pipe$1[ERROR]?.(cause) ?? onErr(cause));
|
|
21
29
|
const pipe = (first, ...pipeable) => {
|
|
30
|
+
let deps = [];
|
|
22
31
|
let run$1 = [];
|
|
23
32
|
let wrap = [];
|
|
24
33
|
let pipe$1;
|
|
@@ -31,19 +40,21 @@ const pipe = (first, ...pipeable) => {
|
|
|
31
40
|
}
|
|
32
41
|
};
|
|
33
42
|
let handler, wrappedFirst = wrapEffect(first, handlePipeError);
|
|
34
|
-
for (pipe$1 of pipeable)
|
|
43
|
+
for (pipe$1 of pipeable) if (pipe$1[PROVIDER]) deps.push(pipe$1);
|
|
44
|
+
else {
|
|
35
45
|
handler = pipe$1[ERROR];
|
|
36
46
|
if (isFunction(handler)) wrap.push(handler);
|
|
37
47
|
if (isFunction(pipe$1) || isFunction(pipe$1[RUN])) run$1.push(pipe$1);
|
|
38
48
|
}
|
|
39
|
-
return gen(function* () {
|
|
49
|
+
return gen(function* (_, ctx) {
|
|
50
|
+
for (pipe$1 of deps) yield* pipe$1;
|
|
40
51
|
next = yield* wrappedFirst;
|
|
41
52
|
for (pipe$1 of run$1) {
|
|
42
53
|
if (isFunction(pipe$1)) pipe$1 = pipe$1(next);
|
|
43
54
|
if (isFunction(pipe$1[RUN])) next = yield* wrapEffect(pipe$1, handlePipeError);
|
|
44
55
|
}
|
|
45
56
|
return next;
|
|
46
|
-
});
|
|
57
|
+
}, true);
|
|
47
58
|
};
|
|
48
59
|
const retry = (times, effect) => {
|
|
49
60
|
let step = 0;
|
|
@@ -52,16 +63,18 @@ const retry = (times, effect) => {
|
|
|
52
63
|
var Effect = class {
|
|
53
64
|
[RUN];
|
|
54
65
|
[ERROR];
|
|
66
|
+
[DEPENDENCY_TYPE];
|
|
67
|
+
[PROVIDES_TYPE];
|
|
55
68
|
constructor(run$1, catchSome$1) {
|
|
56
|
-
this[RUN] = catchSome$1 && run$1 ? (signal) => {
|
|
69
|
+
this[RUN] = catchSome$1 && run$1 ? (signal, ctx) => {
|
|
57
70
|
let res;
|
|
58
71
|
let handleError = (cause) => {
|
|
59
72
|
const recovery = catchSome$1(cause);
|
|
60
|
-
if (recovery) return recovery[RUN]?.(signal);
|
|
73
|
+
if (recovery) return recovery[RUN]?.(signal, ctx);
|
|
61
74
|
throw cause;
|
|
62
75
|
};
|
|
63
76
|
try {
|
|
64
|
-
res = run$1(signal);
|
|
77
|
+
res = run$1(signal, ctx);
|
|
65
78
|
return isFunction(res?.then) ? res.then(void 0, handleError) : res;
|
|
66
79
|
} catch (cause) {
|
|
67
80
|
return handleError(cause);
|
|
@@ -74,31 +87,29 @@ var Effect = class {
|
|
|
74
87
|
}
|
|
75
88
|
pipe = (...pipeable) => pipe(this, ...pipeable);
|
|
76
89
|
};
|
|
77
|
-
var WrapEffect = class {
|
|
78
|
-
[
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
res = run$1(signal);
|
|
91
|
-
return isFunction(res?.then) ? res.then(void 0, handleError) : res;
|
|
92
|
-
} catch (cause) {
|
|
93
|
-
return handleError(cause);
|
|
94
|
-
}
|
|
95
|
-
} : run$1;
|
|
96
|
-
this[ERROR] = catchSome$1;
|
|
90
|
+
var WrapEffect = class extends Effect {
|
|
91
|
+
[HANDLES_ERROR];
|
|
92
|
+
};
|
|
93
|
+
var Dependency = class extends WrapEffect {
|
|
94
|
+
[DEPENDENCY];
|
|
95
|
+
__tag;
|
|
96
|
+
constructor(tag) {
|
|
97
|
+
super((_, ctx) => {
|
|
98
|
+
if (tag in ctx) return ctx[tag];
|
|
99
|
+
throw new Error(`Missing dependency: ${tag}`);
|
|
100
|
+
});
|
|
101
|
+
this.__tag = tag;
|
|
97
102
|
}
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
provide = (instance) => new Provide(this.__tag, instance);
|
|
104
|
+
};
|
|
105
|
+
var Provide = class extends Effect {
|
|
106
|
+
[PROVIDER] = true;
|
|
107
|
+
constructor(tag, instance) {
|
|
108
|
+
super((_, ctx) => {
|
|
109
|
+
ctx[tag] = instance;
|
|
110
|
+
});
|
|
100
111
|
}
|
|
101
112
|
};
|
|
102
113
|
|
|
103
114
|
//#endregion
|
|
104
|
-
export { Effect, WrapEffect,
|
|
115
|
+
export { Dependency, Effect, WrapEffect, catchSome, dependency, fail, fn, gen, pipe, retry, run, succeed };
|
package/dist/schema.d.mts
CHANGED
|
@@ -6,6 +6,6 @@ export * from "valibot";
|
|
|
6
6
|
//#region src/schema.d.ts
|
|
7
7
|
type Schema = v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>> | v.BaseSchemaAsync<unknown, unknown, v.BaseIssue<unknown>>;
|
|
8
8
|
declare const FaildToValidateError: FailureConstructor<"FailedToValidate">;
|
|
9
|
-
declare const validate: <const S extends Schema>(schema: S) => (value: unknown) => Effect<v.InferOutput<S>, InstanceType<typeof FaildToValidateError
|
|
9
|
+
declare const validate: <const S extends Schema>(schema: S) => (value: unknown) => Effect<v.InferOutput<S>, InstanceType<typeof FaildToValidateError>, never, never>;
|
|
10
10
|
//#endregion
|
|
11
11
|
export { Schema, validate };
|