@nicolastoulemont/std 0.6.0 → 0.7.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/README.md +232 -27
- package/dist/adt/index.d.mts +2 -2
- package/dist/adt/index.mjs +1 -1
- package/dist/adt-DajUZvJe.mjs +2 -0
- package/dist/adt-DajUZvJe.mjs.map +1 -0
- package/dist/brand/index.d.mts +2 -2
- package/dist/brand/index.mjs +1 -1
- package/dist/brand-Bia3Vj6l.mjs +2 -0
- package/dist/brand-Bia3Vj6l.mjs.map +1 -0
- package/dist/context/index.d.mts +2 -0
- package/dist/context/index.mjs +1 -0
- package/dist/context-CCHj1nab.mjs +2 -0
- package/dist/context-CCHj1nab.mjs.map +1 -0
- package/dist/context-r8ESJiFn.d.mts +176 -0
- package/dist/context-r8ESJiFn.d.mts.map +1 -0
- package/dist/data/index.d.mts +2 -2
- package/dist/data/index.mjs +1 -1
- package/dist/data-CJxw6al9.mjs +2 -0
- package/dist/data-CJxw6al9.mjs.map +1 -0
- package/dist/data.tagged-error.types-CLlJJ3n5.d.mts +50 -0
- package/dist/data.tagged-error.types-CLlJJ3n5.d.mts.map +1 -0
- package/dist/{discriminator.types-9PxvrZki.d.mts → discriminator.types-CTURejXz.d.mts} +1 -1
- package/dist/discriminator.types-CTURejXz.d.mts.map +1 -0
- package/dist/dual-CZhzZslG.mjs +2 -0
- package/dist/dual-CZhzZslG.mjs.map +1 -0
- package/dist/either/index.d.mts +2 -2
- package/dist/either/index.mjs +1 -1
- package/dist/either-6BwadiFj.mjs +2 -0
- package/dist/either-6BwadiFj.mjs.map +1 -0
- package/dist/{equality-CD4_A1Op.mjs → equality-CoyUHWh9.mjs} +1 -1
- package/dist/{equality-CD4_A1Op.mjs.map → equality-CoyUHWh9.mjs.map} +1 -1
- package/dist/{flow-CYjiodlC.mjs → flow-D8_tllWl.mjs} +1 -1
- package/dist/flow-D8_tllWl.mjs.map +1 -0
- package/dist/functions/index.d.mts +2 -0
- package/dist/functions/index.mjs +1 -0
- package/dist/functions-BkevX2Dw.mjs +2 -0
- package/dist/functions-BkevX2Dw.mjs.map +1 -0
- package/dist/fx/index.d.mts +2 -3
- package/dist/fx/index.mjs +1 -1
- package/dist/fx-BzxLbf1Q.mjs +2 -0
- package/dist/fx-BzxLbf1Q.mjs.map +1 -0
- package/dist/fx.runtime-BcC6yMSy.mjs +2 -0
- package/dist/fx.runtime-BcC6yMSy.mjs.map +1 -0
- package/dist/{fx.types-CDVjDn_3.mjs → fx.types-Bg-Mmdm5.mjs} +1 -1
- package/dist/fx.types-Bg-Mmdm5.mjs.map +1 -0
- package/dist/{fx.types-B34asVRX.d.mts → fx.types-DeEWEltG.d.mts} +2 -2
- package/dist/{fx.types-B34asVRX.d.mts.map → fx.types-DeEWEltG.d.mts.map} +1 -1
- package/dist/index-7Lv982Om.d.mts +217 -0
- package/dist/index-7Lv982Om.d.mts.map +1 -0
- package/dist/index-B_iY5tq0.d.mts +241 -0
- package/dist/index-B_iY5tq0.d.mts.map +1 -0
- package/dist/index-B_wWGszy.d.mts +129 -0
- package/dist/index-B_wWGszy.d.mts.map +1 -0
- package/dist/index-BiiE8NS7.d.mts +108 -0
- package/dist/index-BiiE8NS7.d.mts.map +1 -0
- package/dist/index-By6dNRc4.d.mts +277 -0
- package/dist/index-By6dNRc4.d.mts.map +1 -0
- package/dist/index-CCo85AdC.d.mts +121 -0
- package/dist/index-CCo85AdC.d.mts.map +1 -0
- package/dist/index-CUZn-ohG.d.mts +490 -0
- package/dist/index-CUZn-ohG.d.mts.map +1 -0
- package/dist/index-CugDqdx6.d.mts +464 -0
- package/dist/index-CugDqdx6.d.mts.map +1 -0
- package/dist/{index-B2l8_CiD.d.mts → index-DEAWPlcI.d.mts} +155 -216
- package/dist/index-DEAWPlcI.d.mts.map +1 -0
- package/dist/{index-C4v_3f3-.d.mts → index-DKS1g1oC.d.mts} +95 -42
- package/dist/index-DKS1g1oC.d.mts.map +1 -0
- package/dist/{index-CklRfom5.d.mts → index-DSsDFLGw.d.mts} +263 -368
- package/dist/index-DSsDFLGw.d.mts.map +1 -0
- package/dist/{index-jeC5jyRh.d.mts → index-DXbYlSnB.d.mts} +64 -101
- package/dist/index-DXbYlSnB.d.mts.map +1 -0
- package/dist/{index-BzYtgdX0.d.mts → index-DaTvFhZ8.d.mts} +123 -16
- package/dist/index-DaTvFhZ8.d.mts.map +1 -0
- package/dist/{index-CjZ95Dsv.d.mts → index-Dm2dFysv.d.mts} +188 -202
- package/dist/index-Dm2dFysv.d.mts.map +1 -0
- package/dist/index.d.mts +23 -16
- package/dist/index.mjs +1 -1
- package/dist/layer/index.d.mts +2 -0
- package/dist/layer/index.mjs +1 -0
- package/dist/layer-BttmtDrs.mjs +2 -0
- package/dist/layer-BttmtDrs.mjs.map +1 -0
- package/dist/layer.types-DgpCIsk_.d.mts +100 -0
- package/dist/layer.types-DgpCIsk_.d.mts.map +1 -0
- package/dist/multithread/index.d.mts +2 -0
- package/dist/multithread/index.mjs +1 -0
- package/dist/multithread-xUUh4eLn.mjs +19 -0
- package/dist/multithread-xUUh4eLn.mjs.map +1 -0
- package/dist/option/index.d.mts +2 -3
- package/dist/option/index.mjs +1 -1
- package/dist/option-Qt1H-u7c.mjs +2 -0
- package/dist/option-Qt1H-u7c.mjs.map +1 -0
- package/dist/option.types-DRUm2QiI.mjs +2 -0
- package/dist/option.types-DRUm2QiI.mjs.map +1 -0
- package/dist/{option.types-ClJiBTdg.d.mts → option.types-DlAb6Sr0.d.mts} +4 -4
- package/dist/option.types-DlAb6Sr0.d.mts.map +1 -0
- package/dist/order/index.d.mts +2 -0
- package/dist/order/index.mjs +1 -0
- package/dist/order-D5c4QChk.mjs +2 -0
- package/dist/order-D5c4QChk.mjs.map +1 -0
- package/dist/pipeable-COGyGMUV.mjs +2 -0
- package/dist/pipeable-COGyGMUV.mjs.map +1 -0
- package/dist/{pipeable-B4YJA56p.d.mts → pipeable-rfqacPxZ.d.mts} +2 -9
- package/dist/{pipeable-B4YJA56p.d.mts.map → pipeable-rfqacPxZ.d.mts.map} +1 -1
- package/dist/predicate/index.d.mts +2 -2
- package/dist/predicate/index.mjs +1 -1
- package/dist/predicate-DUhhQqWY.mjs +2 -0
- package/dist/predicate-DUhhQqWY.mjs.map +1 -0
- package/dist/provide/index.d.mts +2 -0
- package/dist/provide/index.mjs +1 -0
- package/dist/provide-B_SqJpCd.mjs +2 -0
- package/dist/provide-B_SqJpCd.mjs.map +1 -0
- package/dist/queue/index.d.mts +2 -0
- package/dist/queue/index.mjs +1 -0
- package/dist/queue-CG5izEBS.mjs +2 -0
- package/dist/queue-CG5izEBS.mjs.map +1 -0
- package/dist/queue.types-CD2LOu37.d.mts +36 -0
- package/dist/queue.types-CD2LOu37.d.mts.map +1 -0
- package/dist/result/index.d.mts +2 -3
- package/dist/result/index.mjs +1 -1
- package/dist/result-BEzV0DYC.mjs +2 -0
- package/dist/result-BEzV0DYC.mjs.map +1 -0
- package/dist/{result.types-HHDzgSTV.d.mts → result.types-_xDAei3-.d.mts} +5 -97
- package/dist/result.types-_xDAei3-.d.mts.map +1 -0
- package/dist/schedule/index.d.mts +2 -0
- package/dist/schedule/index.mjs +1 -0
- package/dist/schedule-C6tjcJ1O.mjs +2 -0
- package/dist/schedule-C6tjcJ1O.mjs.map +1 -0
- package/dist/schedule-DlX2Dg69.d.mts +144 -0
- package/dist/schedule-DlX2Dg69.d.mts.map +1 -0
- package/dist/scope/index.d.mts +2 -0
- package/dist/scope/index.mjs +1 -0
- package/dist/scope-CZdp4wKX.d.mts +79 -0
- package/dist/scope-CZdp4wKX.d.mts.map +1 -0
- package/dist/scope-qwL1VUh2.mjs +2 -0
- package/dist/scope-qwL1VUh2.mjs.map +1 -0
- package/dist/service/index.d.mts +2 -0
- package/dist/service/index.mjs +1 -0
- package/dist/service-3PYQTUdH.mjs +2 -0
- package/dist/service-3PYQTUdH.mjs.map +1 -0
- package/dist/service-DrXU7KJG.d.mts +69 -0
- package/dist/service-DrXU7KJG.d.mts.map +1 -0
- package/dist/service-resolution-C19smeaO.mjs +2 -0
- package/dist/service-resolution-C19smeaO.mjs.map +1 -0
- package/package.json +50 -12
- package/dist/adt-CkRcY_GA.mjs +0 -2
- package/dist/adt-CkRcY_GA.mjs.map +0 -1
- package/dist/apply-fn.types-0g_9eXRy.d.mts +0 -8
- package/dist/apply-fn.types-0g_9eXRy.d.mts.map +0 -1
- package/dist/brand-Gy0kW6-n.mjs +0 -2
- package/dist/brand-Gy0kW6-n.mjs.map +0 -1
- package/dist/data-C0_3MGwm.mjs +0 -2
- package/dist/data-C0_3MGwm.mjs.map +0 -1
- package/dist/discriminator.types-9PxvrZki.d.mts.map +0 -1
- package/dist/either-CPzK-s8W.mjs +0 -2
- package/dist/either-CPzK-s8W.mjs.map +0 -1
- package/dist/err/index.d.mts +0 -2
- package/dist/err/index.mjs +0 -1
- package/dist/err-3KpQ4pj9.mjs +0 -2
- package/dist/err-3KpQ4pj9.mjs.map +0 -1
- package/dist/flow/index.d.mts +0 -2
- package/dist/flow/index.mjs +0 -1
- package/dist/flow-CYjiodlC.mjs.map +0 -1
- package/dist/fx-vqywVJhV.mjs +0 -2
- package/dist/fx-vqywVJhV.mjs.map +0 -1
- package/dist/fx.types-CDVjDn_3.mjs.map +0 -1
- package/dist/index-8Ne4GdOG.d.mts +0 -288
- package/dist/index-8Ne4GdOG.d.mts.map +0 -1
- package/dist/index-B2l8_CiD.d.mts.map +0 -1
- package/dist/index-BOrJQBPO.d.mts +0 -80
- package/dist/index-BOrJQBPO.d.mts.map +0 -1
- package/dist/index-BsXtpnw-.d.mts +0 -225
- package/dist/index-BsXtpnw-.d.mts.map +0 -1
- package/dist/index-BzYtgdX0.d.mts.map +0 -1
- package/dist/index-C4v_3f3-.d.mts.map +0 -1
- package/dist/index-CjZ95Dsv.d.mts.map +0 -1
- package/dist/index-CklRfom5.d.mts.map +0 -1
- package/dist/index-DZdmFtjA.d.mts +0 -79
- package/dist/index-DZdmFtjA.d.mts.map +0 -1
- package/dist/index-a4MEBZZ1.d.mts +0 -850
- package/dist/index-a4MEBZZ1.d.mts.map +0 -1
- package/dist/index-jeC5jyRh.d.mts.map +0 -1
- package/dist/option-DawZC1cE.mjs +0 -2
- package/dist/option-DawZC1cE.mjs.map +0 -1
- package/dist/option.types-ClJiBTdg.d.mts.map +0 -1
- package/dist/pipe/index.d.mts +0 -2
- package/dist/pipe/index.mjs +0 -1
- package/dist/pipe-BPpJyZf7.mjs +0 -2
- package/dist/pipe-BPpJyZf7.mjs.map +0 -1
- package/dist/pipeable-BA0mXhs4.mjs +0 -2
- package/dist/pipeable-BA0mXhs4.mjs.map +0 -1
- package/dist/predicate-Cy_oHA1Q.mjs +0 -2
- package/dist/predicate-Cy_oHA1Q.mjs.map +0 -1
- package/dist/result-CgGYLp0L.mjs +0 -2
- package/dist/result-CgGYLp0L.mjs.map +0 -1
- package/dist/result.types-HHDzgSTV.d.mts.map +0 -1
- /package/dist/{chunk-DAexk1S7.mjs → chunk-C934ptG5.mjs} +0 -0
- /package/dist/{option-Bb-taghv.mjs → option-CBCwzF0L.mjs} +0 -0
- /package/dist/{result-fiJhwVGz.mjs → result-B5WbPg8C.mjs} +0 -0
|
@@ -1,850 +0,0 @@
|
|
|
1
|
-
import { a as FxError, f as RunnableFx, i as Fx$1, m as SyncFx, n as AsyncFxGenerator, o as FxGenerator, s as FxRequirements, t as AsyncFx } from "./fx.types-B34asVRX.mjs";
|
|
2
|
-
import { a as ResultFromTry, b as Err, j as Ok, t as Result } from "./result.types-HHDzgSTV.mjs";
|
|
3
|
-
import { r as Option } from "./option.types-ClJiBTdg.mjs";
|
|
4
|
-
import { O as Either } from "./index-CklRfom5.mjs";
|
|
5
|
-
|
|
6
|
-
//#region src/shared/unify.types.d.ts
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Unify Option unions: Option<A> | Option<B> => Option<A | B>
|
|
10
|
-
*/
|
|
11
|
-
type UnifyOption<T> = [T] extends [Option<infer A>] ? Option<A> : never;
|
|
12
|
-
/**
|
|
13
|
-
* Unify Result unions: Result<A, E1> | Result<B, E2> => Result<A | B, E1 | E2>
|
|
14
|
-
*/
|
|
15
|
-
type UnifyResult<T> = [T] extends [Result<infer A, infer E>] ? Result<A, E> : never;
|
|
16
|
-
/**
|
|
17
|
-
* Unify Either unions: Either<L1, R1> | Either<L2, R2> => Either<L1 | L2, R1 | R2>
|
|
18
|
-
*/
|
|
19
|
-
type UnifyEither<T> = [T] extends [Either<infer L, infer R>] ? Either<L, R> : never;
|
|
20
|
-
/**
|
|
21
|
-
* Unify Fx unions: Fx<A1, E1, R1> | Fx<A2, E2, R2> => Fx<A1 | A2, E1 | E2, R1 | R2>
|
|
22
|
-
*/
|
|
23
|
-
type UnifyFx<T> = [T] extends [Fx$1<infer A, infer E, infer R>] ? Fx$1<A, E, R> : never;
|
|
24
|
-
/**
|
|
25
|
-
* Master Unify dispatcher - detects the container type and applies appropriate unification
|
|
26
|
-
*/
|
|
27
|
-
type Unify<T> = [T] extends [Option<unknown>] ? UnifyOption<T> : [T] extends [Result<unknown, unknown>] ? UnifyResult<T> : [T] extends [Either<unknown, unknown>] ? UnifyEither<T> : [T] extends [Fx$1<unknown, unknown, unknown>] ? UnifyFx<T> : T;
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region src/fx/exit.d.ts
|
|
30
|
-
/**
|
|
31
|
-
* Represents an unexpected thrown exception (defect) caught during Fx execution.
|
|
32
|
-
*/
|
|
33
|
-
type Defect = {
|
|
34
|
-
readonly _tag: "Defect";
|
|
35
|
-
readonly defect: unknown;
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* Exit represents the outcome of an Fx computation.
|
|
39
|
-
* A flat 3-variant discriminated union that cleanly separates:
|
|
40
|
-
* - `Ok<A>`: successful result with value of type A
|
|
41
|
-
* - `Err<E>`: typed failure with error of type E
|
|
42
|
-
* - `Defect`: unexpected thrown exception (defect)
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* ```ts
|
|
46
|
-
* const exit = Fx.run(computation)
|
|
47
|
-
* switch (exit._tag) {
|
|
48
|
-
* case "Ok": exit.value // A
|
|
49
|
-
* case "Err": exit.error // E (clean!)
|
|
50
|
-
* case "Defect": exit.defect // unknown
|
|
51
|
-
* }
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
type Exit<A$1, E$1> = Ok<A$1> | Err<E$1> | Defect;
|
|
55
|
-
/**
|
|
56
|
-
* Handler functions for Exit.match.
|
|
57
|
-
*/
|
|
58
|
-
type ExitMatch<A$1, E$1, R$1> = {
|
|
59
|
-
readonly Ok: (value: A$1) => R$1;
|
|
60
|
-
readonly Err: (error: E$1) => R$1;
|
|
61
|
-
readonly Defect: (defect: unknown) => R$1;
|
|
62
|
-
};
|
|
63
|
-
/**
|
|
64
|
-
* Exit namespace containing all Exit utilities.
|
|
65
|
-
*/
|
|
66
|
-
declare const Exit: {
|
|
67
|
-
readonly ok: <A$1>(value: A$1) => Ok<A$1>;
|
|
68
|
-
readonly err: <E$1>(error: E$1) => Err<E$1>;
|
|
69
|
-
readonly defect: (thrown: unknown) => Defect;
|
|
70
|
-
readonly isOk: <A$1, E$1>(exit: Exit<A$1, E$1>) => exit is Ok<A$1>;
|
|
71
|
-
readonly isErr: <A$1, E$1>(exit: Exit<A$1, E$1>) => exit is Err<E$1>;
|
|
72
|
-
readonly isDefect: <A$1, E$1>(exit: Exit<A$1, E$1>) => exit is Defect;
|
|
73
|
-
readonly match: {
|
|
74
|
-
<A$1, E$1, R$1>(exit: Exit<A$1, E$1>, handlers: ExitMatch<A$1, E$1, R$1>): R$1;
|
|
75
|
-
<A$1, E$1, R$1>(handlers: ExitMatch<A$1, E$1, R$1>): (exit: Exit<A$1, E$1>) => R$1;
|
|
76
|
-
};
|
|
77
|
-
readonly getOrThrow: <A$1, E$1>(exit: Exit<A$1, E$1>) => A$1;
|
|
78
|
-
};
|
|
79
|
-
//#endregion
|
|
80
|
-
//#region src/fx/fx.d.ts
|
|
81
|
-
/**
|
|
82
|
-
* Execute a sync Fx computation and return the Exit.
|
|
83
|
-
* Catches unexpected thrown exceptions and wraps them as Defect.
|
|
84
|
-
* Only available when R = never (all dependencies provided).
|
|
85
|
-
*
|
|
86
|
-
* @param fx - The sync computation to execute
|
|
87
|
-
* @returns Exit<A, E>
|
|
88
|
-
*/
|
|
89
|
-
declare function fxRun<A$1, E$1>(fx: SyncFx<A$1, E$1>): Exit<A$1, E$1>;
|
|
90
|
-
/**
|
|
91
|
-
* Execute an async Fx computation and return a Promise of the Exit.
|
|
92
|
-
* Catches unexpected thrown exceptions and wraps them as Defect.
|
|
93
|
-
* Only available when R = never (all dependencies provided).
|
|
94
|
-
*
|
|
95
|
-
* @param fx - The async computation to execute
|
|
96
|
-
* @returns Promise<Exit<A, E>>
|
|
97
|
-
*/
|
|
98
|
-
declare function fxRun<A$1, E$1>(fx: AsyncFx<A$1, E$1>): Promise<Exit<A$1, E$1>>;
|
|
99
|
-
/**
|
|
100
|
-
* Execute an Fx computation (union type).
|
|
101
|
-
* Returns Exit for sync, Promise<Exit> for async.
|
|
102
|
-
* Catches unexpected thrown exceptions and wraps them as Defect.
|
|
103
|
-
*/
|
|
104
|
-
declare function fxRun<A$1, E$1>(fx: RunnableFx<A$1, E$1>): Exit<A$1, E$1> | Promise<Exit<A$1, E$1>>;
|
|
105
|
-
/**
|
|
106
|
-
* Internal helper to run a sync Fx computation.
|
|
107
|
-
* Wraps execution in try-catch to capture unexpected thrown exceptions as Defect.
|
|
108
|
-
*/
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Create a composable computation from a sync generator function.
|
|
112
|
-
* Returns a SyncFx that can be stored, passed around, and executed later.
|
|
113
|
-
*
|
|
114
|
-
* @template Yielded - The type of values yielded by the generator (must implement Fx protocol)
|
|
115
|
-
* @template A - The success value type
|
|
116
|
-
* @param generatorFn - A function that returns a sync generator
|
|
117
|
-
* @returns SyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
* ```ts
|
|
121
|
-
* const getUser = (id: string) => Fx.gen(function* () {
|
|
122
|
-
* const db = yield* Database
|
|
123
|
-
* const logger = yield* Logger
|
|
124
|
-
*
|
|
125
|
-
* logger.info(`Fetching user ${id}`)
|
|
126
|
-
* return yield* db.query<User>(`SELECT * FROM users WHERE id = '${id}'`)
|
|
127
|
-
* })
|
|
128
|
-
* // Type: SyncFx<User[], DatabaseError, Database | Logger>
|
|
129
|
-
*
|
|
130
|
-
* // Execute later with dependencies provided
|
|
131
|
-
* const exit = pipe(getUser("123"), provide(AppLayer)).run()
|
|
132
|
-
* ```
|
|
133
|
-
*/
|
|
134
|
-
declare function fxGen<Yielded extends Fx$1<unknown, unknown, unknown>, A$1>(generatorFn: () => Generator<Yielded, A$1, unknown>): SyncFx<A$1, FxError<Yielded>, FxRequirements<Yielded>>;
|
|
135
|
-
/**
|
|
136
|
-
* Create a composable computation from an async generator function.
|
|
137
|
-
* Returns an AsyncFx that can be stored, passed around, and executed later.
|
|
138
|
-
*
|
|
139
|
-
* @template Yielded - The type of values yielded by the generator (must implement Fx protocol)
|
|
140
|
-
* @template A - The success value type
|
|
141
|
-
* @param generatorFn - A function that returns an async generator
|
|
142
|
-
* @returns AsyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>
|
|
143
|
-
*
|
|
144
|
-
* @example
|
|
145
|
-
* ```ts
|
|
146
|
-
* const fetchData = (url: string) => Fx.gen(async function* () {
|
|
147
|
-
* const logger = yield* Logger
|
|
148
|
-
*
|
|
149
|
-
* logger.info(`Fetching ${url}`)
|
|
150
|
-
* const response = await fetch(url)
|
|
151
|
-
* return yield* Result.try(async () => await response.json())
|
|
152
|
-
* })
|
|
153
|
-
* // Type: AsyncFx<unknown, Error, Logger>
|
|
154
|
-
* ```
|
|
155
|
-
*/
|
|
156
|
-
declare function fxGen<Yielded extends Fx$1<unknown, unknown, unknown>, A$1>(generatorFn: () => AsyncGenerator<Yielded, A$1, unknown>): AsyncFx<A$1, FxError<Yielded>, FxRequirements<Yielded>>;
|
|
157
|
-
/**
|
|
158
|
-
* Create a composable computation from a sync generator function that takes parameters.
|
|
159
|
-
* Returns a factory function that, when called with parameters, produces a SyncFx.
|
|
160
|
-
*
|
|
161
|
-
* @template P - The parameter types (must be non-empty)
|
|
162
|
-
* @template Yielded - The type of values yielded by the generator (must implement Fx protocol)
|
|
163
|
-
* @template A - The success value type
|
|
164
|
-
* @param generatorFn - A function that takes parameters and returns a sync generator
|
|
165
|
-
* @returns A factory function that produces SyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>
|
|
166
|
-
*
|
|
167
|
-
* @example
|
|
168
|
-
* ```ts
|
|
169
|
-
* const getUser = Fx.gen(function* ({userId}: {userId: string}) {
|
|
170
|
-
* const db = yield* Database
|
|
171
|
-
* return yield* db.query(`SELECT * FROM users WHERE id = '${userId}'`)
|
|
172
|
-
* })
|
|
173
|
-
* // Type: (params: {userId: string}) => SyncFx<...>
|
|
174
|
-
*
|
|
175
|
-
* const exit = Fx.run(pipe(getUser({userId: "123"}), provide(DbLayer)))
|
|
176
|
-
* ```
|
|
177
|
-
*/
|
|
178
|
-
declare function fxGen<P extends [unknown, ...unknown[]], Yielded extends Fx$1<unknown, unknown, unknown>, A$1>(generatorFn: (...params: P) => Generator<Yielded, A$1, unknown>): (...params: P) => SyncFx<A$1, FxError<Yielded>, FxRequirements<Yielded>>;
|
|
179
|
-
/**
|
|
180
|
-
* Create a composable computation from an async generator function that takes parameters.
|
|
181
|
-
* Returns a factory function that, when called with parameters, produces an AsyncFx.
|
|
182
|
-
*
|
|
183
|
-
* @template P - The parameter types (must be non-empty)
|
|
184
|
-
* @template Yielded - The type of values yielded by the generator (must implement Fx protocol)
|
|
185
|
-
* @template A - The success value type
|
|
186
|
-
* @param generatorFn - A function that takes parameters and returns an async generator
|
|
187
|
-
* @returns A factory function that produces AsyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>
|
|
188
|
-
*
|
|
189
|
-
* @example
|
|
190
|
-
* ```ts
|
|
191
|
-
* const fetchUser = Fx.gen(async function* ({url}: {url: string}) {
|
|
192
|
-
* const response = await fetch(url)
|
|
193
|
-
* return yield* Result.try(async () => await response.json())
|
|
194
|
-
* })
|
|
195
|
-
* // Type: (params: {url: string}) => AsyncFx<...>
|
|
196
|
-
* ```
|
|
197
|
-
*/
|
|
198
|
-
declare function fxGen<P extends [unknown, ...unknown[]], Yielded extends Fx$1<unknown, unknown, unknown>, A$1>(generatorFn: (...params: P) => AsyncGenerator<Yielded, A$1, unknown>): (...params: P) => AsyncFx<A$1, FxError<Yielded>, FxRequirements<Yielded>>;
|
|
199
|
-
/**
|
|
200
|
-
* Execute a sync computation immediately and return the Exit.
|
|
201
|
-
* Catches unexpected thrown exceptions and wraps them as Defect.
|
|
202
|
-
* For computations without service dependencies.
|
|
203
|
-
*
|
|
204
|
-
* @template A - The success value type
|
|
205
|
-
* @template E - The error type
|
|
206
|
-
* @param generatorFn - A function that returns a sync generator
|
|
207
|
-
* @returns Exit<A, E>
|
|
208
|
-
*
|
|
209
|
-
* @example
|
|
210
|
-
* ```ts
|
|
211
|
-
* const exit = Fx.fn(function* () {
|
|
212
|
-
* const a = yield* Result.ok(10)
|
|
213
|
-
* const b = yield* Result.ok(20)
|
|
214
|
-
* return a + b
|
|
215
|
-
* })
|
|
216
|
-
* // Type: Exit<number, never>
|
|
217
|
-
* // exit = { _tag: "Ok", value: 30 }
|
|
218
|
-
* ```
|
|
219
|
-
*/
|
|
220
|
-
declare function fxFn<A$1, E$1>(generatorFn: () => FxGenerator<A$1, E$1, never>): Exit<A$1, E$1>;
|
|
221
|
-
/**
|
|
222
|
-
* Execute an async computation immediately and return a Promise of the Exit.
|
|
223
|
-
* Catches unexpected thrown exceptions and wraps them as Defect.
|
|
224
|
-
* For computations without service dependencies.
|
|
225
|
-
*
|
|
226
|
-
* @template A - The success value type
|
|
227
|
-
* @template E - The error type
|
|
228
|
-
* @param generatorFn - A function that returns an async generator
|
|
229
|
-
* @returns Promise<Exit<A, E>>
|
|
230
|
-
*
|
|
231
|
-
* @example
|
|
232
|
-
* ```ts
|
|
233
|
-
* const exit = await Fx.fn(async function* () {
|
|
234
|
-
* const response = await fetch("/api/users")
|
|
235
|
-
* const data = yield* Result.try(async () => await response.json())
|
|
236
|
-
* return data
|
|
237
|
-
* })
|
|
238
|
-
* // Type: Promise<Exit<unknown, Error>>
|
|
239
|
-
* ```
|
|
240
|
-
*/
|
|
241
|
-
declare function fxFn<A$1, E$1>(generatorFn: () => AsyncFxGenerator<A$1, E$1, never>): Promise<Exit<A$1, E$1>>;
|
|
242
|
-
/**
|
|
243
|
-
* Execute a sync computation with service dependencies immediately.
|
|
244
|
-
* Catches unexpected thrown exceptions and wraps them as Defect.
|
|
245
|
-
* The second argument is required when the computation has service requirements (R ≠ never).
|
|
246
|
-
*
|
|
247
|
-
* @template A - The success value type
|
|
248
|
-
* @template E - The error type from the computation
|
|
249
|
-
* @template E2 - The error type from the provider (layer)
|
|
250
|
-
* @template R - The required services type
|
|
251
|
-
* @param generatorFn - A function that returns a sync generator with service requirements
|
|
252
|
-
* @param provider - A function that provides the services (e.g., provide(AppLayer))
|
|
253
|
-
* @returns Exit<A, E | E2>
|
|
254
|
-
*
|
|
255
|
-
* @example
|
|
256
|
-
* ```ts
|
|
257
|
-
* const exit = Fx.fn(function* () {
|
|
258
|
-
* const config = yield* Config
|
|
259
|
-
* const logger = yield* Logger
|
|
260
|
-
* logger.info(`DB URL: ${config.dbUrl}`)
|
|
261
|
-
* return config.dbUrl
|
|
262
|
-
* }, provide(AppLayer))
|
|
263
|
-
* // Type: Exit<string, never>
|
|
264
|
-
* ```
|
|
265
|
-
*/
|
|
266
|
-
declare function fxFn<A$1, E$1, E2, R$1>(generatorFn: () => FxGenerator<A$1, E$1, R$1>, provider: (fx: RunnableFx<A$1, E$1, R$1>) => RunnableFx<A$1, E$1 | E2>): Exit<A$1, E$1 | E2>;
|
|
267
|
-
/**
|
|
268
|
-
* Execute an async computation with service dependencies immediately.
|
|
269
|
-
* Catches unexpected thrown exceptions and wraps them as Defect.
|
|
270
|
-
* The second argument is required when the computation has service requirements (R ≠ never).
|
|
271
|
-
*
|
|
272
|
-
* @template A - The success value type
|
|
273
|
-
* @template E - The error type from the computation
|
|
274
|
-
* @template E2 - The error type from the provider (layer)
|
|
275
|
-
* @template R - The required services type
|
|
276
|
-
* @param generatorFn - A function that returns an async generator with service requirements
|
|
277
|
-
* @param provider - A function that provides the services (e.g., provide(AppLayer))
|
|
278
|
-
* @returns Promise<Exit<A, E | E2>>
|
|
279
|
-
*
|
|
280
|
-
* @example
|
|
281
|
-
* ```ts
|
|
282
|
-
* const exit = await Fx.fn(async function* () {
|
|
283
|
-
* const config = yield* Config
|
|
284
|
-
* await doAsyncWork()
|
|
285
|
-
* return config.dbUrl
|
|
286
|
-
* }, provide(AppLayer))
|
|
287
|
-
* // Type: Promise<Exit<string, never>>
|
|
288
|
-
* ```
|
|
289
|
-
*/
|
|
290
|
-
declare function fxFn<A$1, E$1, E2, R$1>(generatorFn: () => AsyncFxGenerator<A$1, E$1, R$1>, provider: (fx: RunnableFx<A$1, E$1, R$1>) => RunnableFx<A$1, E$1 | E2>): Promise<Exit<A$1, E$1 | E2>>;
|
|
291
|
-
/**
|
|
292
|
-
* Handler functions for matching on a tagged union by `_tag` discriminator.
|
|
293
|
-
* Each handler receives the narrowed variant corresponding to its tag key.
|
|
294
|
-
*/
|
|
295
|
-
type TaggedMatch<T extends {
|
|
296
|
-
readonly _tag: string;
|
|
297
|
-
}, R$1> = { readonly [K in T["_tag"]]: (variant: Extract<T, {
|
|
298
|
-
readonly _tag: K;
|
|
299
|
-
}>) => R$1 };
|
|
300
|
-
/**
|
|
301
|
-
* Generic pattern matcher for any `_tag`-based discriminated union.
|
|
302
|
-
*
|
|
303
|
-
* Works with Exit, tagged errors, or any type with a `readonly _tag` discriminator.
|
|
304
|
-
* Each handler receives the full narrowed variant object for its tag.
|
|
305
|
-
*
|
|
306
|
-
* Supports both data-first and data-last (pipe) calling styles.
|
|
307
|
-
*
|
|
308
|
-
* @example
|
|
309
|
-
* ```ts
|
|
310
|
-
* // Match on Exit
|
|
311
|
-
* Fx.match(exit, {
|
|
312
|
-
* Ok: (ok) => ok.value,
|
|
313
|
-
* Err: (err) =>
|
|
314
|
-
* Fx.match(err.error, {
|
|
315
|
-
* DatabaseError: (e) => e.message,
|
|
316
|
-
* NotFoundError: (e) => e.resourceId,
|
|
317
|
-
* }),
|
|
318
|
-
* Defect: (d) => String(d.defect),
|
|
319
|
-
* })
|
|
320
|
-
*
|
|
321
|
-
* // Data-last with pipe
|
|
322
|
-
* pipe(exit, Fx.match({
|
|
323
|
-
* Ok: (ok) => ok.value,
|
|
324
|
-
* Err: (err) => "error",
|
|
325
|
-
* Defect: (d) => "defect",
|
|
326
|
-
* }))
|
|
327
|
-
* ```
|
|
328
|
-
*/
|
|
329
|
-
declare const fxMatch: {
|
|
330
|
-
<T extends {
|
|
331
|
-
readonly _tag: string;
|
|
332
|
-
}, R$1>(value: T, handlers: TaggedMatch<T, R$1>): R$1;
|
|
333
|
-
<T extends {
|
|
334
|
-
readonly _tag: string;
|
|
335
|
-
}, R$1>(handlers: TaggedMatch<T, R$1>): (value: T) => R$1;
|
|
336
|
-
};
|
|
337
|
-
declare const gen: typeof fxGen;
|
|
338
|
-
declare const fn: typeof fxFn;
|
|
339
|
-
declare const run: typeof fxRun;
|
|
340
|
-
declare const ok: <T>(value: T) => Result<T, never>;
|
|
341
|
-
declare const err: <E$1>(error: E$1) => Result<never, E$1>;
|
|
342
|
-
/**
|
|
343
|
-
* Fx namespace containing utilities for creating and running effectful computations.
|
|
344
|
-
*
|
|
345
|
-
* Fx provides a minimal API inspired by Effect.ts:
|
|
346
|
-
* - `Fx.gen()` - Create composable computations with service dependencies
|
|
347
|
-
* - `Fx.fn()` - Execute computations immediately
|
|
348
|
-
* - `Fx.run()` - Execute a computation (when all dependencies are provided)
|
|
349
|
-
* - `Fx.ok()` - Create successful results (alias for Result.ok)
|
|
350
|
-
* - `Fx.err()` - Create error results (alias for Result.err)
|
|
351
|
-
* - `Fx.try()` - Wrap throwing operations (alias for Result.try)
|
|
352
|
-
* - `Fx.option()` - Convert nullish values to Option (alias for Option.fromNullable)
|
|
353
|
-
*
|
|
354
|
-
* @example
|
|
355
|
-
* ```ts
|
|
356
|
-
* import { Fx, Service, Layer, provide, pipe, Exit } from "@nicolastoulemont/std"
|
|
357
|
-
*
|
|
358
|
-
* // Define services
|
|
359
|
-
* class Config extends Service<Config>()("Config") {
|
|
360
|
-
* readonly dbUrl!: string
|
|
361
|
-
* }
|
|
362
|
-
*
|
|
363
|
-
* class Logger extends Service<Logger>()("Logger") {
|
|
364
|
-
* readonly info!: (msg: string) => void
|
|
365
|
-
* }
|
|
366
|
-
*
|
|
367
|
-
* // Create layers
|
|
368
|
-
* const ConfigLive = Layer.ok(Config, { dbUrl: "postgres://..." })
|
|
369
|
-
* const LoggerLive = Layer.fx(Logger)(
|
|
370
|
-
* Fx.gen(function* () {
|
|
371
|
-
* const config = yield* Config
|
|
372
|
-
* return { info: (msg) => console.log(`[${config.dbUrl}] ${msg}`) }
|
|
373
|
-
* })
|
|
374
|
-
* )
|
|
375
|
-
*
|
|
376
|
-
* // Create workflow
|
|
377
|
-
* const myWorkflow = Fx.gen(function* () {
|
|
378
|
-
* const logger = yield* Logger
|
|
379
|
-
* logger.info("Hello from Fx!")
|
|
380
|
-
* return "done"
|
|
381
|
-
* })
|
|
382
|
-
*
|
|
383
|
-
* // Compose and run
|
|
384
|
-
* const AppLayer = pipe(ConfigLive, Layer.provide(LoggerLive))
|
|
385
|
-
* const exit = Fx.run(pipe(myWorkflow, provide(AppLayer)))
|
|
386
|
-
* // exit._tag === "Ok" | "Err" | "Defect"
|
|
387
|
-
* ```
|
|
388
|
-
*/
|
|
389
|
-
declare const Fx: {
|
|
390
|
-
readonly gen: typeof fxGen;
|
|
391
|
-
readonly fn: typeof fxFn;
|
|
392
|
-
readonly run: typeof fxRun;
|
|
393
|
-
readonly ok: <T>(value: T) => Result<T, never>;
|
|
394
|
-
readonly err: <E$1>(error: E$1) => Result<never, E$1>;
|
|
395
|
-
readonly match: {
|
|
396
|
-
<T extends {
|
|
397
|
-
readonly _tag: string;
|
|
398
|
-
}, R$1>(value: T, handlers: TaggedMatch<T, R$1>): R$1;
|
|
399
|
-
<T extends {
|
|
400
|
-
readonly _tag: string;
|
|
401
|
-
}, R$1>(handlers: TaggedMatch<T, R$1>): (value: T) => R$1;
|
|
402
|
-
};
|
|
403
|
-
readonly try: ResultFromTry;
|
|
404
|
-
readonly option: <T>(value: T) => Option<NonNullable<T>>;
|
|
405
|
-
};
|
|
406
|
-
//#endregion
|
|
407
|
-
//#region src/fx/service.d.ts
|
|
408
|
-
/**
|
|
409
|
-
* The interface returned by Service()().
|
|
410
|
-
* Acts as both a type tag and a runtime lookup key.
|
|
411
|
-
* Implements Fx protocol with E = never (no errors) and R = Self (requires itself).
|
|
412
|
-
* When yielded, yields itself (as Fx) for proper type inference.
|
|
413
|
-
*/
|
|
414
|
-
type ServiceClass<Self, Key extends string = string> = Fx$1<Self, never, Self> & {
|
|
415
|
-
readonly _tag: "Service";
|
|
416
|
-
readonly key: Key;
|
|
417
|
-
readonly _Self: Self;
|
|
418
|
-
/**
|
|
419
|
-
* Yielding the service class in a gen computation
|
|
420
|
-
* returns the service instance from context.
|
|
421
|
-
* Yields the ServiceClass itself (which implements Fx) for type inference.
|
|
422
|
-
*/
|
|
423
|
-
[Symbol.iterator](): Generator<ServiceClass<Self, Key>, Self, unknown>;
|
|
424
|
-
};
|
|
425
|
-
/**
|
|
426
|
-
* Extract the service type from a ServiceClass.
|
|
427
|
-
*/
|
|
428
|
-
type ServiceOf<T> = T extends ServiceClass<infer S> ? S : never;
|
|
429
|
-
/**
|
|
430
|
-
* Extract the key from a ServiceClass.
|
|
431
|
-
*/
|
|
432
|
-
type ServiceKey<T> = T extends ServiceClass<unknown, infer K> ? K : never;
|
|
433
|
-
/**
|
|
434
|
-
* Define a service with a unique key.
|
|
435
|
-
* The returned class acts as both a type and a runtime tag for lookup.
|
|
436
|
-
*
|
|
437
|
-
* Usage follows a double-invocation pattern:
|
|
438
|
-
* - First call provides the Self type parameter
|
|
439
|
-
* - Second call provides the unique key
|
|
440
|
-
*
|
|
441
|
-
* @example
|
|
442
|
-
* ```ts
|
|
443
|
-
* class Config extends Service<Config>()("Config") {
|
|
444
|
-
* readonly dbUrl!: string
|
|
445
|
-
* readonly logLevel!: "debug" | "info" | "error"
|
|
446
|
-
* }
|
|
447
|
-
*
|
|
448
|
-
* class Logger extends Service<Logger>()("Logger") {
|
|
449
|
-
* readonly info!: (msg: string) => void
|
|
450
|
-
* readonly error!: (msg: string) => void
|
|
451
|
-
* }
|
|
452
|
-
*
|
|
453
|
-
* // Use in Fx.gen:
|
|
454
|
-
* const workflow = Fx.gen(function* () {
|
|
455
|
-
* const config = yield* Config
|
|
456
|
-
* const logger = yield* Logger
|
|
457
|
-
* logger.info(`DB URL: ${config.dbUrl}`)
|
|
458
|
-
* })
|
|
459
|
-
* ```
|
|
460
|
-
*/
|
|
461
|
-
declare function Service<Self>(): <Key extends string>(key: Key) => ServiceClass<Self, Key> & (new () => Self);
|
|
462
|
-
/**
|
|
463
|
-
* Create a service tag without class syntax.
|
|
464
|
-
* Useful for simple services that don't need class inheritance.
|
|
465
|
-
*
|
|
466
|
-
* @example
|
|
467
|
-
* ```ts
|
|
468
|
-
* interface ConfigService {
|
|
469
|
-
* readonly dbUrl: string
|
|
470
|
-
* readonly logLevel: "debug" | "info" | "error"
|
|
471
|
-
* }
|
|
472
|
-
*
|
|
473
|
-
* const Config = serviceTag<ConfigService>("Config")
|
|
474
|
-
*
|
|
475
|
-
* // Use in Fx.gen:
|
|
476
|
-
* const workflow = Fx.gen(function* () {
|
|
477
|
-
* const config = yield* Config
|
|
478
|
-
* console.log(config.dbUrl)
|
|
479
|
-
* })
|
|
480
|
-
* ```
|
|
481
|
-
*/
|
|
482
|
-
declare function serviceTag<S>(key: string): ServiceClass<S>;
|
|
483
|
-
/**
|
|
484
|
-
* Check if a value is a ServiceClass.
|
|
485
|
-
*/
|
|
486
|
-
declare const isServiceClass: (value: unknown) => value is ServiceClass<unknown>;
|
|
487
|
-
//#endregion
|
|
488
|
-
//#region src/fx/context.d.ts
|
|
489
|
-
/**
|
|
490
|
-
* Context<Services> is an immutable map storing service implementations.
|
|
491
|
-
* The Services type parameter tracks which services are available.
|
|
492
|
-
*/
|
|
493
|
-
type Context<Services = never> = {
|
|
494
|
-
readonly _tag: "Context";
|
|
495
|
-
readonly _services: ReadonlyMap<string, unknown>;
|
|
496
|
-
readonly _Services: Services;
|
|
497
|
-
};
|
|
498
|
-
/**
|
|
499
|
-
* Get a service from a context.
|
|
500
|
-
* Throws if the service is not found.
|
|
501
|
-
*
|
|
502
|
-
* @param service - The service class (tag)
|
|
503
|
-
* @returns The service implementation
|
|
504
|
-
* @throws Error if service not found
|
|
505
|
-
*
|
|
506
|
-
* @example
|
|
507
|
-
* ```ts
|
|
508
|
-
* const config = Context.get(ctx, Config)
|
|
509
|
-
* ```
|
|
510
|
-
*/
|
|
511
|
-
declare function get<S>(ctx: Context<S>, service: ServiceClass<S>): S;
|
|
512
|
-
declare function get<S>(service: ServiceClass<S>): (ctx: Context<S>) => S;
|
|
513
|
-
/**
|
|
514
|
-
* Context namespace containing utilities for managing service contexts.
|
|
515
|
-
*
|
|
516
|
-
* A Context is an immutable map of services that can be provided to Fx computations.
|
|
517
|
-
* Services are identified by their unique keys.
|
|
518
|
-
*
|
|
519
|
-
* @example
|
|
520
|
-
* ```ts
|
|
521
|
-
* import { Context, Service } from "@nicolastoulemont/std"
|
|
522
|
-
*
|
|
523
|
-
* class Config extends Service<Config>()("Config") {
|
|
524
|
-
* readonly dbUrl!: string
|
|
525
|
-
* }
|
|
526
|
-
*
|
|
527
|
-
* class Logger extends Service<Logger>()("Logger") {
|
|
528
|
-
* readonly info!: (msg: string) => void
|
|
529
|
-
* }
|
|
530
|
-
*
|
|
531
|
-
* // Create a context with services
|
|
532
|
-
* const ctx = pipe(
|
|
533
|
-
* Context.empty(),
|
|
534
|
-
* Context.add(Config, { dbUrl: "postgres://..." }),
|
|
535
|
-
* Context.add(Logger, { info: console.log }),
|
|
536
|
-
* )
|
|
537
|
-
*
|
|
538
|
-
* // Or use make and merge
|
|
539
|
-
* const configCtx = Context.make(Config, { dbUrl: "postgres://..." })
|
|
540
|
-
* const loggerCtx = Context.make(Logger, { info: console.log })
|
|
541
|
-
* const fullCtx = Context.merge(configCtx, loggerCtx)
|
|
542
|
-
* ```
|
|
543
|
-
*/
|
|
544
|
-
declare const Context: {
|
|
545
|
-
readonly empty: () => Context;
|
|
546
|
-
readonly make: <S>(service: ServiceClass<S>, impl: S) => Context<S>;
|
|
547
|
-
readonly add: <S>(service: ServiceClass<S>, impl: S) => <Existing>(ctx: Context<Existing>) => Context<Existing | S>;
|
|
548
|
-
readonly merge: <A$1, B>(a: Context<A$1>, b: Context<B>) => Context<A$1 | B>;
|
|
549
|
-
readonly get: typeof get;
|
|
550
|
-
readonly unsafeGet: (ctx: Context<unknown>, key: string) => unknown;
|
|
551
|
-
readonly has: <S>(ctx: Context<unknown>, service: ServiceClass<S>) => boolean;
|
|
552
|
-
readonly keys: (ctx: Context<unknown>) => string[];
|
|
553
|
-
readonly size: (ctx: Context<unknown>) => number;
|
|
554
|
-
readonly isContext: (value: unknown) => value is Context<unknown>;
|
|
555
|
-
};
|
|
556
|
-
//#endregion
|
|
557
|
-
//#region src/fx/scope.d.ts
|
|
558
|
-
/**
|
|
559
|
-
* Scope manages resource lifecycles with finalizers.
|
|
560
|
-
* Finalizers run in LIFO (Last In, First Out) order when the scope closes.
|
|
561
|
-
*
|
|
562
|
-
* @example
|
|
563
|
-
* ```ts
|
|
564
|
-
* const DatabaseLive = Layer.scoped(Database)(
|
|
565
|
-
* Fx.gen(function* () {
|
|
566
|
-
* const scope = yield* Scope
|
|
567
|
-
*
|
|
568
|
-
* const connection = createConnection()
|
|
569
|
-
*
|
|
570
|
-
* // Register cleanup - runs when scope closes
|
|
571
|
-
* yield* scope.addFinalizer(() =>
|
|
572
|
-
* Fx.gen(function* () {
|
|
573
|
-
* connection.close()
|
|
574
|
-
* })
|
|
575
|
-
* )
|
|
576
|
-
*
|
|
577
|
-
* return { query: (sql) => connection.query(sql) }
|
|
578
|
-
* })
|
|
579
|
-
* )
|
|
580
|
-
* ```
|
|
581
|
-
*/
|
|
582
|
-
type ScopeService = {
|
|
583
|
-
/**
|
|
584
|
-
* Add a finalizer to be run when the scope closes.
|
|
585
|
-
* Finalizers are run in LIFO order.
|
|
586
|
-
*
|
|
587
|
-
* @param finalizer - A function that returns an Fx to run on cleanup
|
|
588
|
-
* @returns An Fx that completes when the finalizer is registered
|
|
589
|
-
*/
|
|
590
|
-
addFinalizer(finalizer: () => SyncFx<void> | AsyncFx<void>): SyncFx<void>;
|
|
591
|
-
/**
|
|
592
|
-
* Close the scope, running all finalizers in LIFO order.
|
|
593
|
-
*
|
|
594
|
-
* @param exit - The exit status of the computation
|
|
595
|
-
* @returns An Fx that completes when all finalizers have run
|
|
596
|
-
*/
|
|
597
|
-
close(exit: Result<unknown, unknown>): SyncFx<void> | AsyncFx<void>;
|
|
598
|
-
/**
|
|
599
|
-
* Fork a child scope.
|
|
600
|
-
* The child scope will be closed when the parent scope closes.
|
|
601
|
-
*
|
|
602
|
-
* @returns A new child scope
|
|
603
|
-
*/
|
|
604
|
-
fork(): ScopeService;
|
|
605
|
-
};
|
|
606
|
-
declare const ScopeTag_base: Fx$1<ScopeService, never, ScopeService> & {
|
|
607
|
-
readonly _tag: "Service";
|
|
608
|
-
readonly key: "@std/Scope";
|
|
609
|
-
readonly _Self: ScopeService;
|
|
610
|
-
[Symbol.iterator](): Generator<ServiceClass<ScopeService, "@std/Scope">, ScopeService, unknown>;
|
|
611
|
-
} & (new () => ScopeService);
|
|
612
|
-
declare class ScopeTag extends ScopeTag_base {}
|
|
613
|
-
/**
|
|
614
|
-
* Create a new Scope instance.
|
|
615
|
-
* This is the concrete implementation of the ScopeService interface.
|
|
616
|
-
*/
|
|
617
|
-
declare function createScope(): ScopeService;
|
|
618
|
-
/**
|
|
619
|
-
* Type utility to exclude Scope from requirements.
|
|
620
|
-
* Used by Layer.scoped to auto-provide Scope.
|
|
621
|
-
*/
|
|
622
|
-
type ExcludeScope<R$1> = Exclude<R$1, ScopeService>;
|
|
623
|
-
//#endregion
|
|
624
|
-
//#region src/fx/memo-map.d.ts
|
|
625
|
-
/**
|
|
626
|
-
* MemoMap caches built layers so each layer is only built once.
|
|
627
|
-
* Multiple dependents share the same service instance.
|
|
628
|
-
*
|
|
629
|
-
* This implements the "service singleton" pattern where a service
|
|
630
|
-
* is instantiated once and shared across all consumers.
|
|
631
|
-
*
|
|
632
|
-
* @example
|
|
633
|
-
* ```ts
|
|
634
|
-
* // Database is built once, shared by DocumentService and TeamService
|
|
635
|
-
* const AppLayer = Layer.merge(
|
|
636
|
-
* ConfigLive,
|
|
637
|
-
* LoggerLive,
|
|
638
|
-
* DatabaseLive, // Built once
|
|
639
|
-
* DocumentServiceLive, // Uses shared Database
|
|
640
|
-
* TeamServiceLive, // Uses same Database instance
|
|
641
|
-
* )
|
|
642
|
-
* ```
|
|
643
|
-
*/
|
|
644
|
-
declare class MemoMap {
|
|
645
|
-
private cache;
|
|
646
|
-
/**
|
|
647
|
-
* Get a cached context or build the layer if not cached.
|
|
648
|
-
*
|
|
649
|
-
* @param layer - The layer to get or build
|
|
650
|
-
* @param scope - The scope for resource management
|
|
651
|
-
* @param deps - Context containing the layer's dependencies
|
|
652
|
-
* @returns A RunnableFx producing the layer's context
|
|
653
|
-
*/
|
|
654
|
-
getOrBuild<ROut, E$1, RIn>(layer: Layer$1<ROut, E$1, RIn>, scope: ScopeService, deps: Context<RIn>): RunnableFx<Context<ROut>, E$1>;
|
|
655
|
-
/**
|
|
656
|
-
* Clear the cache.
|
|
657
|
-
* Useful for testing.
|
|
658
|
-
*/
|
|
659
|
-
clear(): void;
|
|
660
|
-
/**
|
|
661
|
-
* Get the number of cached layers.
|
|
662
|
-
*/
|
|
663
|
-
get size(): number;
|
|
664
|
-
}
|
|
665
|
-
/**
|
|
666
|
-
* Create a new MemoMap instance.
|
|
667
|
-
*/
|
|
668
|
-
declare const createMemoMap: () => MemoMap;
|
|
669
|
-
//#endregion
|
|
670
|
-
//#region src/fx/layer.types.d.ts
|
|
671
|
-
/**
|
|
672
|
-
* Layer<ROut, E, RIn, Sync> describes how to build services:
|
|
673
|
-
* - ROut: Services this layer provides
|
|
674
|
-
* - E: Errors that can occur during construction
|
|
675
|
-
* - RIn: Services this layer requires to build
|
|
676
|
-
* - Sync: Whether the layer builds synchronously (true = sync, false = async)
|
|
677
|
-
*/
|
|
678
|
-
type Layer$1<ROut, E$1 = never, RIn = never, Sync extends boolean = boolean> = {
|
|
679
|
-
readonly _tag: "Layer";
|
|
680
|
-
/** Phantom type for output services */
|
|
681
|
-
readonly _ROut: ROut;
|
|
682
|
-
/** Phantom type for errors */
|
|
683
|
-
readonly _E: E$1;
|
|
684
|
-
/** Phantom type for input requirements */
|
|
685
|
-
readonly _RIn: RIn;
|
|
686
|
-
/** Phantom type for sync tracking */
|
|
687
|
-
readonly _Sync: Sync;
|
|
688
|
-
/**
|
|
689
|
-
* Build the layer given its dependencies.
|
|
690
|
-
* Returns a RunnableFx that produces a Context with the provided services.
|
|
691
|
-
*
|
|
692
|
-
* @param memoMap - Cache for layer memoization
|
|
693
|
-
* @param scope - Scope for resource management
|
|
694
|
-
* @returns A RunnableFx that produces the context
|
|
695
|
-
*/
|
|
696
|
-
build(memoMap: MemoMap, scope: ScopeService): Sync extends true ? SyncFx<Context<ROut>, E$1, RIn> : RunnableFx<Context<ROut>, E$1, RIn>;
|
|
697
|
-
};
|
|
698
|
-
/**
|
|
699
|
-
* Extract the output services type from a Layer.
|
|
700
|
-
*/
|
|
701
|
-
type LayerROut<T> = T extends Layer$1<infer ROut, unknown, unknown> ? ROut : never;
|
|
702
|
-
/**
|
|
703
|
-
* Extract the error type from a Layer.
|
|
704
|
-
*/
|
|
705
|
-
type LayerError<T> = T extends Layer$1<unknown, infer E, unknown> ? E : never;
|
|
706
|
-
/**
|
|
707
|
-
* Extract the input requirements type from a Layer.
|
|
708
|
-
*/
|
|
709
|
-
type LayerRIn<T> = T extends Layer$1<unknown, unknown, infer RIn> ? RIn : never;
|
|
710
|
-
/**
|
|
711
|
-
* Merge all ROut types from an array of layers into a union.
|
|
712
|
-
*/
|
|
713
|
-
type MergeROut<L$1 extends readonly Layer$1<unknown, unknown, unknown>[]> = L$1[number] extends Layer$1<infer ROut, unknown, unknown> ? ROut : never;
|
|
714
|
-
/**
|
|
715
|
-
* Merge all error types from an array of layers into a union.
|
|
716
|
-
*/
|
|
717
|
-
type MergeError<L$1 extends readonly Layer$1<unknown, unknown, unknown>[]> = L$1[number] extends Layer$1<unknown, infer E, unknown> ? E : never;
|
|
718
|
-
/**
|
|
719
|
-
* Get all requirements from an array of layers that are NOT provided by any layer in the array.
|
|
720
|
-
* This computes the "unprovided" or "external" dependencies.
|
|
721
|
-
*/
|
|
722
|
-
type UnprovidedDeps<L$1 extends readonly Layer$1<unknown, unknown, unknown>[]> = Exclude<MergeRIn<L$1>, MergeROut<L$1>>;
|
|
723
|
-
/**
|
|
724
|
-
* Merge all RIn types from an array of layers into a union.
|
|
725
|
-
*/
|
|
726
|
-
type MergeRIn<L$1 extends readonly Layer$1<unknown, unknown, unknown>[]> = L$1[number] extends Layer$1<unknown, unknown, infer RIn> ? RIn : never;
|
|
727
|
-
/**
|
|
728
|
-
* Check if all layers in an array are sync.
|
|
729
|
-
* Returns true only if all layers have Sync=true.
|
|
730
|
-
*/
|
|
731
|
-
type AllSync<L$1 extends readonly Layer$1<unknown, unknown, unknown>[]> = L$1 extends readonly [] ? true : L$1 extends readonly [Layer$1<unknown, unknown, unknown, infer S>, ...infer Rest] ? S extends true ? Rest extends readonly Layer$1<unknown, unknown, unknown>[] ? AllSync<Rest> : false : false : false;
|
|
732
|
-
//#endregion
|
|
733
|
-
//#region src/fx/layer.d.ts
|
|
734
|
-
/**
|
|
735
|
-
* Create a layer from an Fx computation (can have dependencies).
|
|
736
|
-
* The Sync type parameter is inferred from the input fx:
|
|
737
|
-
* - SyncFx input → Layer with Sync=true
|
|
738
|
-
* - AsyncFx input → Layer with Sync=false
|
|
739
|
-
*/
|
|
740
|
-
declare function layerFx<S>(service: ServiceClass<S>): {
|
|
741
|
-
<E$1, R$1>(fx: SyncFx<S, E$1, R$1>): Layer$1<S, E$1, R$1, true>;
|
|
742
|
-
<E$1, R$1>(fx: AsyncFx<S, E$1, R$1>): Layer$1<S, E$1, R$1, false>;
|
|
743
|
-
<E$1, R$1>(fx: RunnableFx<S, E$1, R$1>): Layer$1<S, E$1, R$1>;
|
|
744
|
-
};
|
|
745
|
-
/**
|
|
746
|
-
* Create a scoped layer (with resource cleanup).
|
|
747
|
-
* The Sync type parameter is inferred from the input fx.
|
|
748
|
-
*/
|
|
749
|
-
declare function layerScoped<S>(service: ServiceClass<S>): {
|
|
750
|
-
<E$1, R$1>(fx: SyncFx<S, E$1, R$1 | ScopeService>): Layer$1<S, E$1, ExcludeScope<R$1>, true>;
|
|
751
|
-
<E$1, R$1>(fx: AsyncFx<S, E$1, R$1 | ScopeService>): Layer$1<S, E$1, ExcludeScope<R$1>, false>;
|
|
752
|
-
<E$1, R$1>(fx: RunnableFx<S, E$1, R$1 | ScopeService>): Layer$1<S, E$1, ExcludeScope<R$1>>;
|
|
753
|
-
};
|
|
754
|
-
/**
|
|
755
|
-
* Provide dependencies to a layer and merge outputs.
|
|
756
|
-
* Sync is preserved only if both the deps layer and the consuming layer are sync.
|
|
757
|
-
*/
|
|
758
|
-
declare function layerProvide<DepsROut, DepsE, DepsRIn, DepsSync extends boolean>(deps: Layer$1<DepsROut, DepsE, DepsRIn, DepsSync>): {
|
|
759
|
-
<ROut, E$1, RIn extends DepsROut, LayerSync extends boolean>(layer: Layer$1<ROut, E$1, RIn, LayerSync>): Layer$1<ROut | DepsROut, E$1 | DepsE, DepsRIn, LayerSync extends true ? DepsSync : false>;
|
|
760
|
-
};
|
|
761
|
-
/**
|
|
762
|
-
* Merge multiple layers with automatic dependency resolution.
|
|
763
|
-
* The merged layer is sync only if ALL input layers are sync.
|
|
764
|
-
*/
|
|
765
|
-
declare function layerMerge<L$1 extends Layer$1<unknown, unknown, unknown>[]>(...layers: L$1): Layer$1<MergeROut<L$1>, MergeError<L$1>, UnprovidedDeps<L$1>, AllSync<L$1>>;
|
|
766
|
-
declare const Layer: {
|
|
767
|
-
readonly ok: <S>(service: ServiceClass<S>, impl: S) => Layer$1<S, never, never, true>;
|
|
768
|
-
readonly err: <E$1>(error: E$1) => Layer$1<never, E$1, never, true>;
|
|
769
|
-
readonly fx: typeof layerFx;
|
|
770
|
-
readonly scoped: typeof layerScoped;
|
|
771
|
-
readonly provide: typeof layerProvide;
|
|
772
|
-
readonly merge: typeof layerMerge;
|
|
773
|
-
};
|
|
774
|
-
//#endregion
|
|
775
|
-
//#region src/fx/provide.d.ts
|
|
776
|
-
/**
|
|
777
|
-
* Extract the value type from an Fx.
|
|
778
|
-
*/
|
|
779
|
-
type FxValueType<F> = F extends RunnableFx<infer A, unknown, unknown> ? A : never;
|
|
780
|
-
/**
|
|
781
|
-
* Extract the error type from an Fx.
|
|
782
|
-
*/
|
|
783
|
-
type FxErrorType<F> = F extends RunnableFx<unknown, infer E, unknown> ? E : never;
|
|
784
|
-
/**
|
|
785
|
-
* Type for the result of provide based on layer sync and fx type.
|
|
786
|
-
* Uses infer to extract A and E from the actual Fx type.
|
|
787
|
-
* - Sync layer + SyncFx → SyncFx
|
|
788
|
-
* - Sync layer + AsyncFx → AsyncFx
|
|
789
|
-
* - Async layer + any fx → AsyncFx
|
|
790
|
-
* - Unknown sync layer + any fx → RunnableFx (fallback)
|
|
791
|
-
*/
|
|
792
|
-
type ProvideResult<E2, LayerSync extends boolean, Fx$2 extends RunnableFx<unknown, unknown, unknown>> = LayerSync extends true ? Fx$2["_tag"] extends "SyncFx" ? SyncFx<FxValueType<Fx$2>, FxErrorType<Fx$2> | E2> : AsyncFx<FxValueType<Fx$2>, FxErrorType<Fx$2> | E2> : LayerSync extends false ? AsyncFx<FxValueType<Fx$2>, FxErrorType<Fx$2> | E2> : RunnableFx<FxValueType<Fx$2>, FxErrorType<Fx$2> | E2>;
|
|
793
|
-
/**
|
|
794
|
-
* Provide a layer to an Fx computation, resolving all service requirements.
|
|
795
|
-
* Creates a new scope for resource management.
|
|
796
|
-
*
|
|
797
|
-
* Type preservation:
|
|
798
|
-
* - Sync layer + SyncFx → SyncFx
|
|
799
|
-
* - Sync layer + AsyncFx → AsyncFx
|
|
800
|
-
* - Async layer + any fx → AsyncFx
|
|
801
|
-
* - Unknown sync layer + any fx → RunnableFx (fallback)
|
|
802
|
-
*
|
|
803
|
-
* @param layer - The layer providing services (must have no external requirements)
|
|
804
|
-
* @returns A function that takes an Fx and returns an Fx with dependencies resolved
|
|
805
|
-
*
|
|
806
|
-
* @example
|
|
807
|
-
* ```ts
|
|
808
|
-
* const result = Fx.run(pipe(
|
|
809
|
-
* updateDocumentWorkflow(userId, docId, data),
|
|
810
|
-
* provide(AppLayer)
|
|
811
|
-
* ))
|
|
812
|
-
* ```
|
|
813
|
-
*/
|
|
814
|
-
declare function provide<ROut, E2, LayerSync extends boolean>(layer: Layer$1<ROut, E2, never, LayerSync>): <Fx$2 extends RunnableFx<unknown, unknown, ROut>>(fx: Fx$2) => ProvideResult<E2, LayerSync, Fx$2>;
|
|
815
|
-
/**
|
|
816
|
-
* Provide a context directly to an Fx computation.
|
|
817
|
-
*
|
|
818
|
-
* @param ctx - The context containing services
|
|
819
|
-
* @returns A function that takes an Fx and returns an Fx with dependencies resolved
|
|
820
|
-
*
|
|
821
|
-
* @example
|
|
822
|
-
* ```ts
|
|
823
|
-
* const ctx = Context.make(Config, configImpl)
|
|
824
|
-
* const result = Fx.run(pipe(
|
|
825
|
-
* myWorkflow,
|
|
826
|
-
* provideContext(ctx)
|
|
827
|
-
* ))
|
|
828
|
-
* ```
|
|
829
|
-
*/
|
|
830
|
-
declare const provideContext: <R$1>(ctx: Context<R$1>) => <A$1, E$1>(fx: RunnableFx<A$1, E$1, R$1>) => RunnableFx<A$1, E$1>;
|
|
831
|
-
/**
|
|
832
|
-
* Provide a single service to an Fx computation.
|
|
833
|
-
*
|
|
834
|
-
* @param service - The service class (tag)
|
|
835
|
-
* @param impl - The service implementation
|
|
836
|
-
* @returns A function that takes an Fx and returns an Fx with the service provided
|
|
837
|
-
*
|
|
838
|
-
* @example
|
|
839
|
-
* ```ts
|
|
840
|
-
* const result = Fx.run(pipe(
|
|
841
|
-
* myWorkflow,
|
|
842
|
-
* provideService(Config, configImpl),
|
|
843
|
-
* provideService(Logger, loggerImpl),
|
|
844
|
-
* ))
|
|
845
|
-
* ```
|
|
846
|
-
*/
|
|
847
|
-
declare const provideService: <S>(service: ServiceClass<S>, impl: S) => <A$1, E$1, R$1>(fx: RunnableFx<A$1, E$1, R$1 | S>) => RunnableFx<A$1, E$1, Exclude<R$1, S>>;
|
|
848
|
-
//#endregion
|
|
849
|
-
export { gen as A, isServiceClass as C, err as D, TaggedMatch as E, Unify as F, UnifyEither as I, UnifyFx as L, run as M, Defect as N, fn as O, Exit as P, UnifyOption as R, ServiceOf as S, Fx as T, createScope as _, Layer$1 as a, ServiceClass as b, LayerROut as c, UnprovidedDeps as d, MemoMap as f, ScopeTag as g, ScopeService as h, Layer as i, ok as j, fxMatch as k, MergeError as l, ExcludeScope as m, provideContext as n, LayerError as o, createMemoMap as p, provideService as r, LayerRIn as s, provide as t, MergeROut as u, Context as v, serviceTag as w, ServiceKey as x, Service as y, UnifyResult as z };
|
|
850
|
-
//# sourceMappingURL=index-a4MEBZZ1.d.mts.map
|