@nicolastoulemont/std 0.5.1 → 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 +546 -0
- 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/chunk-C934ptG5.mjs +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-DkThfvNE.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-CoyUHWh9.mjs +2 -0
- package/dist/equality-CoyUHWh9.mjs.map +1 -0
- package/dist/flow-D8_tllWl.mjs +2 -0
- 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-CXTwEa1G.mjs → fx.types-Bg-Mmdm5.mjs} +1 -1
- package/dist/fx.types-Bg-Mmdm5.mjs.map +1 -0
- package/dist/{fx.types-DO-8yG4c.d.mts → fx.types-DeEWEltG.d.mts} +3 -8
- package/dist/{fx.types-DO-8yG4c.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-DEAWPlcI.d.mts +405 -0
- package/dist/index-DEAWPlcI.d.mts.map +1 -0
- package/dist/index-DKS1g1oC.d.mts +449 -0
- package/dist/index-DKS1g1oC.d.mts.map +1 -0
- package/dist/index-DSsDFLGw.d.mts +777 -0
- package/dist/index-DSsDFLGw.d.mts.map +1 -0
- package/dist/{index-DjjJIDaA.d.mts → index-DXbYlSnB.d.mts} +66 -103
- package/dist/index-DXbYlSnB.d.mts.map +1 -0
- package/dist/{index-DtAPrec7.d.mts → index-DaTvFhZ8.d.mts} +167 -52
- package/dist/index-DaTvFhZ8.d.mts.map +1 -0
- package/dist/index-Dm2dFysv.d.mts +415 -0
- 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-Cluybn30.d.mts → option.types-DlAb6Sr0.d.mts} +6 -11
- 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-KHu4D8ol.d.mts → pipeable-rfqacPxZ.d.mts} +2 -9
- package/dist/{pipeable-KHu4D8ol.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-B5WbPg8C.mjs +1 -0
- package/dist/result-BEzV0DYC.mjs +2 -0
- package/dist/result-BEzV0DYC.mjs.map +1 -0
- package/dist/{result.types-fIbuBwVQ.d.mts → result.types-_xDAei3-.d.mts} +31 -109
- 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 +52 -13
- package/dist/adt-DZmVJG4P.mjs +0 -2
- package/dist/adt-DZmVJG4P.mjs.map +0 -1
- package/dist/apply-fn.types-CMgY6WQe.d.mts +0 -8
- package/dist/apply-fn.types-CMgY6WQe.d.mts.map +0 -1
- package/dist/brand-BUqMmkzC.mjs +0 -2
- package/dist/brand-BUqMmkzC.mjs.map +0 -1
- package/dist/data-DzqKBCQg.mjs +0 -2
- package/dist/data-DzqKBCQg.mjs.map +0 -1
- package/dist/discriminator.types-DkThfvNE.d.mts.map +0 -1
- package/dist/either-BDY9T5oz.mjs +0 -2
- package/dist/either-BDY9T5oz.mjs.map +0 -1
- package/dist/equality-D2EJvZm4.mjs +0 -2
- package/dist/equality-D2EJvZm4.mjs.map +0 -1
- package/dist/err/index.d.mts +0 -2
- package/dist/err/index.mjs +0 -1
- package/dist/err-CYs4b1RV.mjs +0 -2
- package/dist/err-CYs4b1RV.mjs.map +0 -1
- package/dist/flow/index.d.mts +0 -2
- package/dist/flow/index.mjs +0 -1
- package/dist/flow-CxKQ5yac.mjs +0 -2
- package/dist/flow-CxKQ5yac.mjs.map +0 -1
- package/dist/fx-C4UuWCqP.mjs +0 -2
- package/dist/fx-C4UuWCqP.mjs.map +0 -1
- package/dist/fx.types-CXTwEa1G.mjs.map +0 -1
- package/dist/index-78LWwTds.d.mts +0 -288
- package/dist/index-78LWwTds.d.mts.map +0 -1
- package/dist/index-BQ5wVDSP.d.mts +0 -441
- package/dist/index-BQ5wVDSP.d.mts.map +0 -1
- package/dist/index-BahMvQpA.d.mts +0 -80
- package/dist/index-BahMvQpA.d.mts.map +0 -1
- package/dist/index-Bs5TTFlK.d.mts +0 -882
- package/dist/index-Bs5TTFlK.d.mts.map +0 -1
- package/dist/index-BuLJRX1e.d.mts +0 -476
- package/dist/index-BuLJRX1e.d.mts.map +0 -1
- package/dist/index-CDio8mJY.d.mts +0 -225
- package/dist/index-CDio8mJY.d.mts.map +0 -1
- package/dist/index-DLlx9jiG.d.mts +0 -389
- package/dist/index-DLlx9jiG.d.mts.map +0 -1
- package/dist/index-DjjJIDaA.d.mts.map +0 -1
- package/dist/index-DtAPrec7.d.mts.map +0 -1
- package/dist/index-IdejL485.d.mts +0 -79
- package/dist/index-IdejL485.d.mts.map +0 -1
- package/dist/index-UYodvXes.d.mts +0 -846
- package/dist/index-UYodvXes.d.mts.map +0 -1
- package/dist/option-Qiv7Ls7L.mjs +0 -2
- package/dist/option-Qiv7Ls7L.mjs.map +0 -1
- package/dist/option.types-By5UOfC2.mjs +0 -2
- package/dist/option.types-By5UOfC2.mjs.map +0 -1
- package/dist/option.types-Cluybn30.d.mts.map +0 -1
- package/dist/pipe/index.d.mts +0 -2
- package/dist/pipe/index.mjs +0 -1
- package/dist/pipe-BROILDeC.mjs +0 -2
- package/dist/pipe-BROILDeC.mjs.map +0 -1
- package/dist/pipeable-rQvolRqh.mjs +0 -2
- package/dist/pipeable-rQvolRqh.mjs.map +0 -1
- package/dist/predicate-DvXnfmeJ.mjs +0 -2
- package/dist/predicate-DvXnfmeJ.mjs.map +0 -1
- package/dist/result-B68pxC7l.mjs +0 -2
- package/dist/result-B68pxC7l.mjs.map +0 -1
- package/dist/result.types-fIbuBwVQ.d.mts.map +0 -1
- /package/dist/{result-uRORQlAQ.mjs → option-CBCwzF0L.mjs} +0 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { a as OptionFilter, c as OptionMatch, d as OptionUnwrapOr, f as OptionUnwrapOrElse, i as OptionAll, l as OptionOrElse, n as NoSuchElementError$1, o as OptionFlatMap, r as Option$1, s as OptionMap, t as FromTryReturn, u as OptionTap } from "./option.types-DlAb6Sr0.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/option/option.d.ts
|
|
4
|
+
declare namespace option_d_exports {
|
|
5
|
+
export { NoSuchElementError, Option, all, filter, flatMap, fromNullable, fromTry, isNone, isSome, map, match, none, orElse, some, tap, unwrapOr, unwrapOrElse };
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Re-exported error type used when yielding `Option.none()` in `Fx.gen`.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
13
|
+
*
|
|
14
|
+
* const error = new Option.NoSuchElementError()
|
|
15
|
+
* // => error.name === "NoSuchElementError"
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @category Re-exports
|
|
19
|
+
*/
|
|
20
|
+
declare const NoSuchElementError: typeof NoSuchElementError$1;
|
|
21
|
+
/**
|
|
22
|
+
* Re-exported `NoSuchElementError` instance type.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* import type { Option } from "@nicolastoulemont/std"
|
|
27
|
+
*
|
|
28
|
+
* type Example = Option.NoSuchElementError
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @category Re-exports
|
|
32
|
+
*/
|
|
33
|
+
type NoSuchElementError = InstanceType<typeof NoSuchElementError$1>;
|
|
34
|
+
/**
|
|
35
|
+
* Re-exported `Option` type.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* import type { Option } from "@nicolastoulemont/std"
|
|
40
|
+
*
|
|
41
|
+
* type Example = Option.Option<unknown>
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @category Re-exports
|
|
45
|
+
*/
|
|
46
|
+
type Option<T> = Option$1<T>;
|
|
47
|
+
/**
|
|
48
|
+
* Create an Option with a value.
|
|
49
|
+
*
|
|
50
|
+
* @param value - The value to wrap
|
|
51
|
+
* @returns An Option with `_tag: "Some"`
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
56
|
+
*
|
|
57
|
+
* const value = Option.some(42)
|
|
58
|
+
* // => { _tag: "Some", value: 42 }
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @category Constructors
|
|
62
|
+
*/
|
|
63
|
+
declare const some: <T>(value: T) => Option$1<T>;
|
|
64
|
+
/**
|
|
65
|
+
* Create an Option with no value.
|
|
66
|
+
*
|
|
67
|
+
* @returns An Option with `_tag: "None"`
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
72
|
+
*
|
|
73
|
+
* const value = Option.none<number>()
|
|
74
|
+
* // => { _tag: "None" }
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @category Constructors
|
|
78
|
+
*/
|
|
79
|
+
declare const none: <T = never>() => Option$1<T>;
|
|
80
|
+
/**
|
|
81
|
+
* Check if an Option has a value.
|
|
82
|
+
*
|
|
83
|
+
* @param option - The Option to check
|
|
84
|
+
* @returns true if the Option is some
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
89
|
+
*
|
|
90
|
+
* const value = Option.isSome(Option.some(1))
|
|
91
|
+
* // => true
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
94
|
+
* @category Guards
|
|
95
|
+
*/
|
|
96
|
+
declare const isSome: <T>(option: Option$1<T>) => option is Extract<Option$1<T>, {
|
|
97
|
+
_tag: "Some";
|
|
98
|
+
}>;
|
|
99
|
+
/**
|
|
100
|
+
* isNone utility.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
105
|
+
*
|
|
106
|
+
* const value = Option.isNone(Option.none())
|
|
107
|
+
* // => true
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* @category Guards
|
|
111
|
+
*/
|
|
112
|
+
declare const isNone: <T>(option: Option$1<T>) => option is Extract<Option$1<T>, {
|
|
113
|
+
_tag: "None";
|
|
114
|
+
}>;
|
|
115
|
+
/**
|
|
116
|
+
* Transform the value of an Option.
|
|
117
|
+
* If the Option is none, it passes through unchanged.
|
|
118
|
+
*
|
|
119
|
+
* Supports both data-first and data-last calling styles:
|
|
120
|
+
* - Data-first: `map(option, fn)`
|
|
121
|
+
* - Data-last: `pipe(option, map(fn))`
|
|
122
|
+
*
|
|
123
|
+
* Supports both sync and async functions:
|
|
124
|
+
* - Sync fn: returns Option<U>
|
|
125
|
+
* - Async fn: returns Promise<Option<U>>
|
|
126
|
+
*
|
|
127
|
+
* @param fn - Function to transform the value
|
|
128
|
+
* @returns A function that takes an Option and returns a new Option
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
133
|
+
*
|
|
134
|
+
* const input = Option.some(2)
|
|
135
|
+
* const dataFirst = Option.map(input, (n) => n + 1)
|
|
136
|
+
* // => { _tag: "Some", value: 3 }
|
|
137
|
+
*
|
|
138
|
+
* const dataLast = Option.map((n: number) => n + 1)(input)
|
|
139
|
+
* // => { _tag: "Some", value: 3 }
|
|
140
|
+
* ```
|
|
141
|
+
*
|
|
142
|
+
* @category Mapping
|
|
143
|
+
*/
|
|
144
|
+
declare const map: OptionMap;
|
|
145
|
+
/**
|
|
146
|
+
* Chain operations that return Options.
|
|
147
|
+
* If the Option is none, it passes through unchanged.
|
|
148
|
+
*
|
|
149
|
+
* Supports both data-first and data-last calling styles:
|
|
150
|
+
* - Data-first: `flatMap(option, fn)`
|
|
151
|
+
* - Data-last: `pipe(option, flatMap(fn))`
|
|
152
|
+
*
|
|
153
|
+
* Supports both sync and async functions:
|
|
154
|
+
* - Sync fn: returns Option<U>
|
|
155
|
+
* - Async fn: returns Promise<Option<U>>
|
|
156
|
+
*
|
|
157
|
+
* @param fn - Function that takes a value and returns an Option (or Promise<Option>)
|
|
158
|
+
* @returns A function that takes an Option and returns a new Option
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
163
|
+
*
|
|
164
|
+
* const input = Option.some(2)
|
|
165
|
+
* const dataFirst = Option.flatMap(input, (n) => Option.some(n + 1))
|
|
166
|
+
* // => { _tag: "Some", value: 3 }
|
|
167
|
+
*
|
|
168
|
+
* const dataLast = Option.flatMap((n: number) => Option.some(n + 1))(input)
|
|
169
|
+
* // => { _tag: "Some", value: 3 }
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* @category Sequencing
|
|
173
|
+
*/
|
|
174
|
+
declare const flatMap: OptionFlatMap;
|
|
175
|
+
/**
|
|
176
|
+
* Perform a side effect on the value without modifying the Option.
|
|
177
|
+
* Useful for debugging, logging, or other side effects in a pipeline.
|
|
178
|
+
* If the Option is none, the function is not called.
|
|
179
|
+
*
|
|
180
|
+
* Supports both data-first and data-last calling styles:
|
|
181
|
+
* - Data-first: `tap(option, fn)`
|
|
182
|
+
* - Data-last: `pipe(option, tap(fn))`
|
|
183
|
+
*
|
|
184
|
+
* Supports both sync and async functions:
|
|
185
|
+
* - Sync fn: returns Option<T>
|
|
186
|
+
* - Async fn: returns Promise<Option<T>>
|
|
187
|
+
*
|
|
188
|
+
* @param fn - Function to call with the value (return value is ignored)
|
|
189
|
+
* @returns A function that takes an Option and returns the same Option
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```ts
|
|
193
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
194
|
+
*
|
|
195
|
+
* let seen = 0
|
|
196
|
+
* const input = Option.some(2)
|
|
197
|
+
* const dataFirst = Option.tap(input, (n) => {
|
|
198
|
+
* seen = n
|
|
199
|
+
* })
|
|
200
|
+
* // => { _tag: "Some", value: 2 }
|
|
201
|
+
*
|
|
202
|
+
* const dataLast = Option.tap((n: number) => {
|
|
203
|
+
* seen = n
|
|
204
|
+
* })(input)
|
|
205
|
+
* // => { _tag: "Some", value: 2 }
|
|
206
|
+
* ```
|
|
207
|
+
*
|
|
208
|
+
* @category Sequencing
|
|
209
|
+
*/
|
|
210
|
+
declare const tap: OptionTap;
|
|
211
|
+
/**
|
|
212
|
+
* Recover from none by providing an alternative Option.
|
|
213
|
+
* If the Option is some, it passes through unchanged.
|
|
214
|
+
*
|
|
215
|
+
* Supports both data-first and data-last calling styles:
|
|
216
|
+
* - Data-first: `orElse(option, fn)`
|
|
217
|
+
* - Data-last: `pipe(option, orElse(fn))`
|
|
218
|
+
*
|
|
219
|
+
* Supports both sync and async functions:
|
|
220
|
+
* - Sync fn: returns Option<T | U>
|
|
221
|
+
* - Async fn: returns Promise<Option<T | U>>
|
|
222
|
+
*
|
|
223
|
+
* @param fn - Function that returns an alternative Option
|
|
224
|
+
* @returns A function that takes an Option and returns a new Option
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```ts
|
|
228
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
229
|
+
*
|
|
230
|
+
* const input = Option.none<number>()
|
|
231
|
+
* const dataFirst = Option.orElse(input, () => Option.some(0))
|
|
232
|
+
* // => { _tag: "Some", value: 0 }
|
|
233
|
+
*
|
|
234
|
+
* const dataLast = Option.orElse(() => Option.some(0))(input)
|
|
235
|
+
* // => { _tag: "Some", value: 0 }
|
|
236
|
+
* ```
|
|
237
|
+
*
|
|
238
|
+
* @category Combining
|
|
239
|
+
*/
|
|
240
|
+
declare const orElse: OptionOrElse;
|
|
241
|
+
/**
|
|
242
|
+
* Filter an Option based on a predicate.
|
|
243
|
+
* If the predicate returns false, converts to none.
|
|
244
|
+
* If the Option is already none, it passes through unchanged.
|
|
245
|
+
*
|
|
246
|
+
* Supports both data-first and data-last calling styles:
|
|
247
|
+
* - Data-first: `filter(option, predicate)`
|
|
248
|
+
* - Data-last: `pipe(option, filter(predicate))`
|
|
249
|
+
*
|
|
250
|
+
* @param predicate - Function that returns true to keep the value
|
|
251
|
+
* @returns A function that takes an Option and returns a new Option
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
256
|
+
*
|
|
257
|
+
* const input = Option.some(3)
|
|
258
|
+
* const dataFirst = Option.filter(input, (n) => n > 0)
|
|
259
|
+
* // => { _tag: "Some", value: 3 }
|
|
260
|
+
*
|
|
261
|
+
* const dataLast = Option.filter((n: number) => n > 0)(input)
|
|
262
|
+
* // => { _tag: "Some", value: 3 }
|
|
263
|
+
* ```
|
|
264
|
+
*
|
|
265
|
+
* @category Filtering
|
|
266
|
+
*/
|
|
267
|
+
declare const filter: OptionFilter;
|
|
268
|
+
/**
|
|
269
|
+
* Combine multiple Options into a single Option.
|
|
270
|
+
* Supports both array and object inputs.
|
|
271
|
+
*
|
|
272
|
+
* - If all Options are some, returns some with all values
|
|
273
|
+
* - If any Option is none, returns none (short-circuits)
|
|
274
|
+
*
|
|
275
|
+
* For arrays of 1-6 elements, tuple types are inferred automatically.
|
|
276
|
+
* For longer arrays, use `as const` to preserve tuple structure.
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* ```ts
|
|
280
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
281
|
+
*
|
|
282
|
+
* const combined = Option.all([Option.some(1), Option.some(2)] as const)
|
|
283
|
+
* // => { _tag: "Some", value: [1, 2] }
|
|
284
|
+
* ```
|
|
285
|
+
*
|
|
286
|
+
* @category Combining
|
|
287
|
+
*/
|
|
288
|
+
declare const all: OptionAll;
|
|
289
|
+
/**
|
|
290
|
+
* Get the value or a default value.
|
|
291
|
+
*
|
|
292
|
+
* Supports both data-first and data-last calling styles:
|
|
293
|
+
* - Data-first: `unwrapOr(option, defaultValue)`
|
|
294
|
+
* - Data-last: `pipe(option, unwrapOr(defaultValue))`
|
|
295
|
+
*
|
|
296
|
+
* Uses NoInfer to prevent type inference from the default value.
|
|
297
|
+
*
|
|
298
|
+
* @param defaultValue - Value to return if the Option is none
|
|
299
|
+
* @returns A function that takes an Option and returns the value or default
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* ```ts
|
|
303
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
304
|
+
*
|
|
305
|
+
* const input = Option.none<number>()
|
|
306
|
+
* const dataFirst = Option.unwrapOr(input, 0)
|
|
307
|
+
* // => 0
|
|
308
|
+
*
|
|
309
|
+
* const dataLast = Option.unwrapOr(0)(input)
|
|
310
|
+
* // => 0
|
|
311
|
+
* ```
|
|
312
|
+
*
|
|
313
|
+
* @category Getters
|
|
314
|
+
*/
|
|
315
|
+
declare const unwrapOr: OptionUnwrapOr;
|
|
316
|
+
/**
|
|
317
|
+
* Get the value or compute a value.
|
|
318
|
+
*
|
|
319
|
+
* Supports both data-first and data-last calling styles:
|
|
320
|
+
* - Data-first: `unwrapOrElse(option, fn)`
|
|
321
|
+
* - Data-last: `pipe(option, unwrapOrElse(fn))`
|
|
322
|
+
*
|
|
323
|
+
* @param fn - Function to compute a value
|
|
324
|
+
* @returns A function that takes an Option and returns the value or computed value
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```ts
|
|
328
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
329
|
+
*
|
|
330
|
+
* const input = Option.none<number>()
|
|
331
|
+
* const dataFirst = Option.unwrapOrElse(input, () => 0)
|
|
332
|
+
* // => 0
|
|
333
|
+
*
|
|
334
|
+
* const dataLast = Option.unwrapOrElse(() => 0)(input)
|
|
335
|
+
* // => 0
|
|
336
|
+
* ```
|
|
337
|
+
*
|
|
338
|
+
* @category Getters
|
|
339
|
+
*/
|
|
340
|
+
declare const unwrapOrElse: OptionUnwrapOrElse;
|
|
341
|
+
/**
|
|
342
|
+
* Pattern match on an Option, handling both some and none cases.
|
|
343
|
+
*
|
|
344
|
+
* Supports both data-first and data-last calling styles:
|
|
345
|
+
* - Data-first: `match(option, { Some: ..., None: ... })`
|
|
346
|
+
* - Data-last: `pipe(option, match({ Some: ..., None: ... }))`
|
|
347
|
+
*
|
|
348
|
+
* @param handlers - Object with `Some` and `None` handlers
|
|
349
|
+
* @returns A function that takes an Option and returns the handler result
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* ```ts
|
|
353
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
354
|
+
*
|
|
355
|
+
* const input = Option.some(2)
|
|
356
|
+
* const dataFirst = Option.match(input, {
|
|
357
|
+
* Some: (value) => `some:${value}` ,
|
|
358
|
+
* None: () => "none" ,
|
|
359
|
+
* })
|
|
360
|
+
* // => "some:2"
|
|
361
|
+
*
|
|
362
|
+
* const dataLast = Option.match({
|
|
363
|
+
* Some: (value: number) => `some:${value}` ,
|
|
364
|
+
* None: () => "none" ,
|
|
365
|
+
* })(input)
|
|
366
|
+
* // => "some:2"
|
|
367
|
+
* ```
|
|
368
|
+
*
|
|
369
|
+
* @category Pattern Matching
|
|
370
|
+
*/
|
|
371
|
+
declare const match: OptionMatch;
|
|
372
|
+
/**
|
|
373
|
+
* fromNullable utility.
|
|
374
|
+
*
|
|
375
|
+
* @example
|
|
376
|
+
* ```ts
|
|
377
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
378
|
+
*
|
|
379
|
+
* const value = Option.fromNullable("Ada")
|
|
380
|
+
* // => { _tag: "Some", value: "Ada" }
|
|
381
|
+
* ```
|
|
382
|
+
*
|
|
383
|
+
* @category Conversions
|
|
384
|
+
*/
|
|
385
|
+
declare const fromNullable: <T>(value: T) => Option$1<NonNullable<T>>;
|
|
386
|
+
/**
|
|
387
|
+
* Wrap a function that might throw into an Option.
|
|
388
|
+
* Supports both sync and async functions with automatic type inference.
|
|
389
|
+
*
|
|
390
|
+
* - Sync fn: returns Option<T>
|
|
391
|
+
* - Async fn: returns Promise<Option<T>>
|
|
392
|
+
*
|
|
393
|
+
* **Note on `any` return types:** If your function returns `any` (e.g., `JSON.parse`),
|
|
394
|
+
* you should add an explicit return type annotation. This is because TypeScript's
|
|
395
|
+
* conditional types cannot determine if `any` is a Promise or not, resulting in a
|
|
396
|
+
* union type `Promise<Option<unknown>> | Option<any>` that won't work
|
|
397
|
+
* with Option utilities like `isSome` or `isNone`.
|
|
398
|
+
*
|
|
399
|
+
* @param fn - Function that might throw (sync or async)
|
|
400
|
+
* @returns An Option with the return value or none
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* ```ts
|
|
404
|
+
* import { Option } from "@nicolastoulemont/std"
|
|
405
|
+
*
|
|
406
|
+
* const parsed = Option.fromTry(() => Number.parseInt("42", 10))
|
|
407
|
+
* // => { _tag: "Some", value: 42 }
|
|
408
|
+
* ```
|
|
409
|
+
*
|
|
410
|
+
* @category Conversions
|
|
411
|
+
*/
|
|
412
|
+
declare const fromTry: <T>(fn: () => T) => FromTryReturn<T>;
|
|
413
|
+
//#endregion
|
|
414
|
+
export { option_d_exports as t };
|
|
415
|
+
//# sourceMappingURL=index-Dm2dFysv.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-Dm2dFysv.d.mts","names":[],"sources":["../src/option/option.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;cA4Da,2BAAkB;;;;;;;;AAA/B;AAcA;AAcA;AAwBA;;AAA8C,KAtClC,kBAAA,GAAqB,YAsCa,CAAA,OAtCO,oBAsCP,CAAA;;;AA8B9C;AAkCA;;;;;;;AAgBA;;AAAkC,KAxGtB,MAwGsB,CAAA,CAAA,CAAA,GAxGV,QAwGU,CAxGC,CAwGD,CAAA;;;;;AAqClC;AAwCA;AAwCA;AAwCA;AA8BA;AA8BA;AAkDA;AA6BA;AAmCA;AA2CA;;;AAAsD,cAtczC,IAscyC,EAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAtcvB,CAscuB,EAAA,GAtcnB,QAscmB,CAtcR,CAscQ,CAAA;;;AA6BtD;;;;;;;;;;;;;cArca,uBAAsB,SAAW;;;;;;;;;;;;;;;;;cAkCjC,oBAAqB,SAAW,iBAAe,QAAQ,SAAW;;;;;;;;;;;;;;;;cAgBlE,oBAAqB,SAAW,iBAAe,QAAQ,SAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAqClE,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAwCL,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAwCT,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAwCL,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;cA8BR,QAAQ;;;;;;;;;;;;;;;;;;;;;cA8BR,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;cAkDL,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;cA6BV,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAmCd,OAAO;;;;;;;;;;;;;;cA2CP,yBAA0B,MAAI,SAAW,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;cA6BrD,uBAAwB,MAAI,cAAc"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { t as
|
|
11
|
-
import {
|
|
12
|
-
import { t as
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { t as
|
|
16
|
-
|
|
1
|
+
import { t as adt_d_exports } from "./index-DKS1g1oC.mjs";
|
|
2
|
+
import { t as brand_d_exports } from "./index-DXbYlSnB.mjs";
|
|
3
|
+
import { n as service_d_exports } from "./service-DrXU7KJG.mjs";
|
|
4
|
+
import { n as context_d_exports } from "./context-r8ESJiFn.mjs";
|
|
5
|
+
import "./context/index.mjs";
|
|
6
|
+
import { t as data_d_exports } from "./index-DaTvFhZ8.mjs";
|
|
7
|
+
import { t as either_d_exports } from "./index-DSsDFLGw.mjs";
|
|
8
|
+
import { n as flow, t as pipe } from "./index-B_wWGszy.mjs";
|
|
9
|
+
import { r as schedule_d_exports } from "./schedule-DlX2Dg69.mjs";
|
|
10
|
+
import { t as fx_d_exports } from "./index-CugDqdx6.mjs";
|
|
11
|
+
import { r as scope_d_exports } from "./scope-CZdp4wKX.mjs";
|
|
12
|
+
import { t as layer_d_exports } from "./index-7Lv982Om.mjs";
|
|
13
|
+
import { t as multithread_d_exports } from "./index-By6dNRc4.mjs";
|
|
14
|
+
import { t as option_d_exports } from "./index-Dm2dFysv.mjs";
|
|
15
|
+
import { t as order_d_exports } from "./index-CUZn-ohG.mjs";
|
|
16
|
+
import { t as predicate_d_exports } from "./index-B_iY5tq0.mjs";
|
|
17
|
+
import { t as provide_d_exports } from "./index-BiiE8NS7.mjs";
|
|
18
|
+
import { t as queue_d_exports } from "./index-CCo85AdC.mjs";
|
|
19
|
+
import { t as result_d_exports } from "./index-DEAWPlcI.mjs";
|
|
20
|
+
import "./schedule/index.mjs";
|
|
21
|
+
import "./scope/index.mjs";
|
|
22
|
+
import "./service/index.mjs";
|
|
23
|
+
export { adt_d_exports as Adt, brand_d_exports as Brand, context_d_exports as Context, data_d_exports as Data, either_d_exports as Either, fx_d_exports as Fx, layer_d_exports as Layer, multithread_d_exports as Multithread, option_d_exports as Option, order_d_exports as Order, predicate_d_exports as Predicate, provide_d_exports as Provide, queue_d_exports as Queue, result_d_exports as Result, schedule_d_exports as Schedule, scope_d_exports as Scope, service_d_exports as Service, flow, pipe };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./
|
|
1
|
+
import{t as e}from"./adt-DajUZvJe.mjs";import{t}from"./flow-D8_tllWl.mjs";import{i as n}from"./result-BEzV0DYC.mjs";import{t as r}from"./brand-Bia3Vj6l.mjs";import{t as i}from"./context-CCHj1nab.mjs";import"./context/index.mjs";import{n as a}from"./data-CJxw6al9.mjs";import{r as o}from"./option-Qt1H-u7c.mjs";import{t as s}from"./either-6BwadiFj.mjs";import{t as c}from"./functions-BkevX2Dw.mjs";import{a as l}from"./queue-CG5izEBS.mjs";import{t as u}from"./fx-BzxLbf1Q.mjs";import{t as d}from"./layer-BttmtDrs.mjs";import{t as f}from"./multithread-xUUh4eLn.mjs";import{t as p}from"./order-D5c4QChk.mjs";import{t as m}from"./predicate-DUhhQqWY.mjs";import{n as h}from"./scope-qwL1VUh2.mjs";import{t as g}from"./provide-B_SqJpCd.mjs";import"./queue/index.mjs";import{t as _}from"./schedule-C6tjcJ1O.mjs";import"./scope/index.mjs";import{t as v}from"./service-3PYQTUdH.mjs";export{e as Adt,r as Brand,i as Context,a as Data,s as Either,u as Fx,d as Layer,f as Multithread,o as Option,p as Order,m as Predicate,g as Provide,l as Queue,n as Result,_ as Schedule,h as Scope,v as Service,t as flow,c as pipe};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"../layer-BttmtDrs.mjs";export{e as Layer};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{t as e}from"./chunk-C934ptG5.mjs";import{t}from"./fx.types-Bg-Mmdm5.mjs";import{i as n,n as r,r as i}from"./context-CCHj1nab.mjs";import{n as a,t as o}from"./service-resolution-C19smeaO.mjs";var s=e({err:()=>h,fx:()=>g,merge:()=>y,ok:()=>m,provide:()=>v,scoped:()=>_});const c=(e,n)=>({_tag:`Layer`,_ROut:void 0,_E:void 0,_RIn:void 0,_Sync:void 0,build:()=>({_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){return i(e,n)}})}),l=e=>({_tag:`Layer`,_ROut:void 0,_E:void 0,_RIn:void 0,_Sync:void 0,build:()=>({_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>e,_R:()=>void 0},*[Symbol.iterator](){throw yield e,Error(`Unreachable`)}})});function u(e){return n=>({_tag:`Layer`,_ROut:void 0,_E:void 0,_RIn:void 0,_Sync:void 0,build:()=>n._tag===`AsyncFx`?{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},async*[Symbol.asyncIterator](){let t=n[Symbol.asyncIterator](),r=await t.next();for(;r.done!==!0;){let e=yield r.value;r=await t.next(e)}return i(e,r.value)}}:{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){let t=n[Symbol.iterator](),r=t.next();for(;r.done!==!0;){let e=yield r.value;r=t.next(e)}return i(e,r.value)}}})}function d(e){return n=>({_tag:`Layer`,_ROut:void 0,_E:void 0,_RIn:void 0,_Sync:void 0,build:(r,a)=>n._tag===`AsyncFx`?{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},async*[Symbol.asyncIterator](){let t=n[Symbol.asyncIterator](),r=await t.next();for(;r.done!==!0;){let e=r.value;if(o(e)?.key===`@std/Scope`)r=await t.next(a);else{let n=yield e;r=await t.next(n)}}return i(e,r.value)}}:{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){let t=n[Symbol.iterator](),r=t.next();for(;r.done!==!0;){let e=r.value;if(o(e)?.key===`@std/Scope`)r=t.next(a);else{let n=yield e;r=t.next(n)}}return i(e,r.value)}}})}function f(e){return r=>({_tag:`Layer`,_ROut:void 0,_E:void 0,_RIn:void 0,_Sync:void 0,build:(i,o)=>{let s=e.build(i,o);return s._tag===`AsyncFx`?{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},async*[Symbol.asyncIterator](){let e=s[Symbol.asyncIterator](),t=await e.next();for(;t.done!==!0;){let n=yield t.value;t=await e.next(n)}let c=t.value,l=r.build(i,o);if(l._tag===`AsyncFx`){let e=l[Symbol.asyncIterator](),t=await e.next();for(;t.done!==!0;){let n=t.value,r=a(c,n);if(r!==void 0){t=await e.next(r);continue}let i=yield n;t=await e.next(i)}return n(c,t.value)}let u=l[Symbol.iterator](),d=u.next();for(;d.done!==!0;){let e=d.value,t=a(c,e);if(t!==void 0){d=u.next(t);continue}let n=yield e;d=u.next(n)}return n(c,d.value)}}:{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){let e=s[Symbol.iterator](),t=e.next();for(;t.done!==!0;){let n=yield t.value;t=e.next(n)}let c=t.value,l=r.build(i,o);if(l._tag===`SyncFx`){let e=l[Symbol.iterator](),t=e.next();for(;t.done!==!0;){let n=t.value,r=a(c,n);if(r!==void 0){t=e.next(r);continue}let i=yield n;t=e.next(i)}return n(c,t.value)}throw Error(`Cannot use async layer in sync context`)}}}})}function p(...e){return{_tag:`Layer`,_ROut:void 0,_E:void 0,_RIn:void 0,_Sync:void 0,build:(i,o)=>e.some(e=>e.build(i,o)._tag===`AsyncFx`)?{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},async*[Symbol.asyncIterator](){let t=r();for(let r of e){let e=r.build(i,o);if(e._tag===`AsyncFx`){let r=e[Symbol.asyncIterator](),i=await r.next();for(;i.done!==!0;){let e=i.value,n=a(t,e);if(n!==void 0){i=await r.next(n);continue}let o=yield e;i=await r.next(o)}t=n(t,i.value)}else{let r=e[Symbol.iterator](),i=r.next();for(;i.done!==!0;){let e=i.value,n=a(t,e);if(n!==void 0){i=r.next(n);continue}let o=yield e;i=r.next(o)}t=n(t,i.value)}}return t}}:{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){let t=r();for(let r of e){let e=r.build(i,o);if(e._tag!==`SyncFx`)throw Error(`Expected sync layer in sync context`);let s=e[Symbol.iterator](),c=s.next();for(;c.done!==!0;){let e=c.value,n=a(t,e);if(n!==void 0){c=s.next(n);continue}let r=yield e;c=s.next(r)}t=n(t,c.value)}return t}}}}const m=c,h=l,g=u,_=d,v=f,y=p;export{s as t};
|
|
2
|
+
//# sourceMappingURL=layer-BttmtDrs.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer-BttmtDrs.mjs","names":["Context.make","fx","layerGen","layerResult","Context.merge","Context.empty"],"sources":["../src/layer/layer.ts"],"sourcesContent":["/**\n * Layer construction and composition for service dependency graphs.\n *\n * **Mental model**\n * - A `Layer` builds one or more services, potentially requiring other services.\n * - Compose layers and provide dependencies before running `Fx`.\n *\n * **Common tasks**\n * - Build from values with `Layer.ok`.\n * - Build from effects with `Layer.fx` or `Layer.scoped`.\n * - Compose with `Layer.provide` and `Layer.merge`.\n *\n * **Gotchas**\n * - Async layers force async execution paths.\n * - Scoped layers require scope finalization.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Layer } from \"@nicolastoulemont/std\"\n *\n * import { Service } from \"@nicolastoulemont/std\"\n * \n * const Port = Service.tag<number>(\"Port\")\n * const portLayer = Layer.ok(Port, 3000)\n * // => layer that provides Port\n * ```\n *\n * @module\n */\nimport * as Context from \"../context/context\"\nimport type { Context as ContextType } from \"../context/context\"\nimport { FxTypeId } from \"../fx/fx.types\"\nimport type { RunnableFx, SyncFx, AsyncFx, FxYield } from \"../fx/fx.types\"\nimport type { ScopeService, ExcludeScope } from \"../scope/scope\"\nimport type { ServiceClass } from \"../service/service\"\nimport { asServiceRequest, resolveService } from \"../service/service-resolution\"\nimport type { Layer as LayerType, MergeROut, MergeError, UnprovidedDeps, AllSync } from \"./layer.types\"\n\n/* oxlint-disable no-unsafe-type-assertion -- Layer composition carries erased generic channels and phantom type slots that require assertion-based reconstruction. */\n\n/**\n * Create a layer from a synchronous value (no dependencies).\n */\nconst layerOk = <S>(service: ServiceClass<S>, impl: S): LayerType<S, never, never, true> => ({\n _tag: \"Layer\",\n _ROut: undefined as unknown as S,\n _E: undefined as never,\n _RIn: undefined as never,\n _Sync: undefined as unknown as true,\n build: (): SyncFx<ContextType<S>> => ({\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as ContextType<S>,\n _E: () => undefined as never,\n _R: () => undefined as never,\n },\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<never, ContextType<S>, unknown> {\n return Context.make(service, impl)\n },\n }),\n})\n\n/**\n * Create a layer that always fails with an error.\n */\nconst layerErr = <E>(error: E): LayerType<never, E, never, true> => ({\n _tag: \"Layer\",\n _ROut: undefined as never,\n _E: undefined as unknown as E,\n _RIn: undefined as never,\n _Sync: undefined as unknown as true,\n build: (): SyncFx<ContextType, E> => ({\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as never,\n _E: () => error,\n _R: () => undefined as never,\n },\n *[Symbol.iterator](): Generator<E, never, unknown> {\n yield error\n throw new Error(\"Unreachable\")\n },\n }),\n})\n\n/**\n * Create a layer from an Fx computation (can have dependencies).\n * The Sync type parameter is inferred from the input fx:\n * - SyncFx input → Layer with Sync=true\n * - AsyncFx input → Layer with Sync=false\n *\n * @example\n * ```ts\n * import { Layer } from \"@nicolastoulemont/std\"\n *\n * import { Fx, Service } from \"@nicolastoulemont/std\"\n * \n * const Port = Service.tag<number>(\"Port\")\n * const portLayer = Layer.fx(Port)(Fx.gen(function* () {\n * return 3000\n * }))\n * // => effect-backed layer\n * ```\n *\n * @category Constructors\n */\nfunction layerFx<S>(service: ServiceClass<S>): {\n <E, R>(fx: SyncFx<S, E, R>): LayerType<S, E, R, true>\n <E, R>(fx: AsyncFx<S, E, R>): LayerType<S, E, R, false>\n <E, R>(fx: RunnableFx<S, E, R>): LayerType<S, E, R>\n}\nfunction layerFx<S>(service: ServiceClass<S>) {\n return <E, R>(fx: RunnableFx<S, E, R>): LayerType<S, E, R> => ({\n _tag: \"Layer\",\n _ROut: undefined as unknown as S,\n _E: undefined as unknown as E,\n _RIn: undefined as unknown as R,\n _Sync: undefined as unknown as boolean,\n build: (): RunnableFx<ContextType<S>, E, R> => {\n if (fx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as ContextType<S>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as unknown as R,\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<FxYield<E, R>, ContextType<S>, unknown> {\n const gen = fx[Symbol.asyncIterator]()\n let result = await gen.next()\n while (result.done !== true) {\n const value = yield result.value\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(value)\n }\n return Context.make(service, result.value)\n },\n } as AsyncFx<ContextType<S>, E, R>\n }\n\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as ContextType<S>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as unknown as R,\n },\n *[Symbol.iterator](): Generator<FxYield<E, R>, ContextType<S>, unknown> {\n const gen = fx[Symbol.iterator]()\n let result = gen.next()\n while (result.done !== true) {\n const value = yield result.value\n result = gen.next(value)\n }\n return Context.make(service, result.value)\n },\n } as SyncFx<ContextType<S>, E, R>\n },\n })\n}\n\n/**\n * Create a scoped layer (with resource cleanup).\n * The Sync type parameter is inferred from the input fx.\n *\n * @example\n * ```ts\n * import { Layer } from \"@nicolastoulemont/std\"\n *\n * import { Fx, Service } from \"@nicolastoulemont/std\"\n * \n * const Resource = Service.tag<{ close: () => void }>(\"Resource\")\n * const resourceLayer = Layer.scoped(Resource)(Fx.gen(function* () {\n * return { close: () => undefined }\n * }) as never)\n * // => scoped layer with finalization support\n * ```\n *\n * @category Constructors\n */\nfunction layerScoped<S>(service: ServiceClass<S>): {\n <E, R>(fx: SyncFx<S, E, R | ScopeService>): LayerType<S, E, ExcludeScope<R>, true>\n <E, R>(fx: AsyncFx<S, E, R | ScopeService>): LayerType<S, E, ExcludeScope<R>, false>\n <E, R>(fx: RunnableFx<S, E, R | ScopeService>): LayerType<S, E, ExcludeScope<R>>\n}\nfunction layerScoped<S>(service: ServiceClass<S>) {\n return <E, R>(fx: RunnableFx<S, E, R | ScopeService>): LayerType<S, E, ExcludeScope<R>> => ({\n _tag: \"Layer\",\n _ROut: undefined as unknown as S,\n _E: undefined as unknown as E,\n _RIn: undefined as unknown as ExcludeScope<R>,\n _Sync: undefined as unknown as boolean,\n build: (_memoMap, scope): RunnableFx<ContextType<S>, E, ExcludeScope<R>> => {\n if (fx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as ContextType<S>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as unknown as ExcludeScope<R>,\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<FxYield<E, ExcludeScope<R>>, ContextType<S>, unknown> {\n const gen = fx[Symbol.asyncIterator]()\n let result = await gen.next()\n while (result.done !== true) {\n const yielded = result.value\n const serviceRequest = asServiceRequest(yielded)\n if (serviceRequest?.key === \"@std/Scope\") {\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(scope)\n } else {\n const value = yield yielded as FxYield<E, ExcludeScope<R>>\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(value)\n }\n }\n return Context.make(service, result.value)\n },\n } as AsyncFx<ContextType<S>, E, ExcludeScope<R>>\n }\n\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as ContextType<S>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as unknown as ExcludeScope<R>,\n },\n *[Symbol.iterator](): Generator<FxYield<E, ExcludeScope<R>>, ContextType<S>, unknown> {\n const gen = fx[Symbol.iterator]()\n let result = gen.next()\n while (result.done !== true) {\n const yielded = result.value\n const serviceRequest = asServiceRequest(yielded)\n if (serviceRequest?.key === \"@std/Scope\") {\n result = gen.next(scope)\n } else {\n const value = yield yielded as FxYield<E, ExcludeScope<R>>\n result = gen.next(value)\n }\n }\n return Context.make(service, result.value)\n },\n } as SyncFx<ContextType<S>, E, ExcludeScope<R>>\n },\n })\n}\n\n// ============================================================================\n// Layer Composition\n// ============================================================================\n\n/**\n * Provide dependencies to a layer and merge outputs.\n * Sync is preserved only if both the deps layer and the consuming layer are sync.\n *\n * @example\n * ```ts\n * import { Layer } from \"@nicolastoulemont/std\"\n *\n * import { Service } from \"@nicolastoulemont/std\"\n * \n * const Logger = Service.tag<{ log: (message: string) => void }>(\"Logger\")\n * const App = Service.tag<{ start: () => void }>(\"App\")\n * const loggerLayer = Layer.ok(Logger, { log: () => undefined })\n * const appLayer = Layer.ok(App, { start: () => undefined })\n * const provided = Layer.provide(loggerLayer)(appLayer)\n * // => composed layer\n * ```\n *\n * @category Sequencing\n */\nfunction layerProvide<DepsROut, DepsE, DepsRIn, DepsSync extends boolean>(\n deps: LayerType<DepsROut, DepsE, DepsRIn, DepsSync>,\n): {\n <ROut, E, RIn extends DepsROut, LayerSync extends boolean>(\n layer: LayerType<ROut, E, RIn, LayerSync>,\n ): LayerType<ROut | DepsROut, E | DepsE, DepsRIn, LayerSync extends true ? DepsSync : false>\n}\nfunction layerProvide<DepsROut, DepsE, DepsRIn>(deps: LayerType<DepsROut, DepsE, DepsRIn>) {\n return <ROut, E, RIn extends DepsROut>(\n layer: LayerType<ROut, E, RIn>,\n ): LayerType<ROut | DepsROut, E | DepsE, DepsRIn> => ({\n _tag: \"Layer\",\n _ROut: undefined as unknown as ROut | DepsROut,\n _E: undefined as unknown as E | DepsE,\n _RIn: undefined as unknown as DepsRIn,\n _Sync: undefined as unknown as boolean,\n build: (memoMap, scope): RunnableFx<ContextType<ROut | DepsROut>, E | DepsE, DepsRIn> => {\n const depsBuildFx = deps.build(memoMap, scope)\n\n if (depsBuildFx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as ContextType<ROut | DepsROut>,\n _E: () => undefined as unknown as E | DepsE,\n _R: () => undefined as unknown as DepsRIn,\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<\n FxYield<E | DepsE, DepsRIn>,\n ContextType<ROut | DepsROut>,\n unknown\n > {\n const depsGen = depsBuildFx[Symbol.asyncIterator]()\n let depsResult = await depsGen.next()\n while (depsResult.done !== true) {\n const value = yield depsResult.value\n // oxlint-disable-next-line no-await-in-loop\n depsResult = await depsGen.next(value)\n }\n const depsCtx = depsResult.value\n\n const layerBuildFx = layer.build(memoMap, scope)\n if (layerBuildFx._tag === \"AsyncFx\") {\n const layerGen = layerBuildFx[Symbol.asyncIterator]()\n let layerResult = await layerGen.next()\n while (layerResult.done !== true) {\n const yielded = layerResult.value\n const service = resolveService(depsCtx, yielded)\n if (service !== undefined) {\n // oxlint-disable-next-line no-await-in-loop\n layerResult = await layerGen.next(service)\n continue\n }\n const value = yield yielded as FxYield<E, DepsRIn>\n // oxlint-disable-next-line no-await-in-loop\n layerResult = await layerGen.next(value)\n }\n return Context.merge(depsCtx, layerResult.value)\n }\n\n const layerGen = layerBuildFx[Symbol.iterator]()\n let layerResult = layerGen.next()\n while (layerResult.done !== true) {\n const yielded = layerResult.value\n const service = resolveService(depsCtx, yielded)\n if (service !== undefined) {\n layerResult = layerGen.next(service)\n continue\n }\n const value = yield yielded as FxYield<E, DepsRIn>\n layerResult = layerGen.next(value)\n }\n return Context.merge(depsCtx, layerResult.value)\n },\n } as AsyncFx<ContextType<ROut | DepsROut>, E | DepsE, DepsRIn>\n }\n\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as ContextType<ROut | DepsROut>,\n _E: () => undefined as unknown as E | DepsE,\n _R: () => undefined as unknown as DepsRIn,\n },\n *[Symbol.iterator](): Generator<FxYield<E | DepsE, DepsRIn>, ContextType<ROut | DepsROut>, unknown> {\n const depsGen = depsBuildFx[Symbol.iterator]()\n let depsResult = depsGen.next()\n while (depsResult.done !== true) {\n const value = yield depsResult.value\n depsResult = depsGen.next(value)\n }\n const depsCtx = depsResult.value\n\n const layerBuildFx = layer.build(memoMap, scope)\n if (layerBuildFx._tag === \"SyncFx\") {\n const syncGen = layerBuildFx[Symbol.iterator]()\n let layerResult = syncGen.next()\n while (layerResult.done !== true) {\n const yielded = layerResult.value\n const service = resolveService(depsCtx, yielded)\n if (service !== undefined) {\n layerResult = syncGen.next(service)\n continue\n }\n const value = yield yielded as FxYield<E, DepsRIn>\n layerResult = syncGen.next(value)\n }\n return Context.merge(depsCtx, layerResult.value)\n }\n throw new Error(\"Cannot use async layer in sync context\")\n },\n } as SyncFx<ContextType<ROut | DepsROut>, E | DepsE, DepsRIn>\n },\n })\n}\n\n/**\n * Merge multiple layers with automatic dependency resolution.\n * The merged layer is sync only if ALL input layers are sync.\n *\n * @example\n * ```ts\n * import { Layer } from \"@nicolastoulemont/std\"\n *\n * import { Service } from \"@nicolastoulemont/std\"\n * \n * const Logger = Service.tag<{ log: (message: string) => void }>(\"Logger\")\n * const Clock = Service.tag<{ now: () => number }>(\"Clock\")\n * const merged = Layer.merge(\n * Layer.ok(Logger, { log: () => undefined }),\n * Layer.ok(Clock, { now: () => Date.now() }),\n * )\n * // => layer that provides Logger | Clock\n * ```\n *\n * @category Combining\n */\nfunction layerMerge<L extends LayerType<unknown, unknown, unknown>[]>(\n ...layers: L\n): LayerType<MergeROut<L>, MergeError<L>, UnprovidedDeps<L>, AllSync<L>>\nfunction layerMerge<L extends LayerType<unknown, unknown, unknown>[]>(\n ...layers: L\n): LayerType<MergeROut<L>, MergeError<L>, UnprovidedDeps<L>> {\n return {\n _tag: \"Layer\",\n _ROut: undefined as unknown as MergeROut<L>,\n _E: undefined as unknown as MergeError<L>,\n _RIn: undefined as unknown as UnprovidedDeps<L>,\n _Sync: undefined as unknown as boolean,\n build: (memoMap, scope): RunnableFx<ContextType<MergeROut<L>>, MergeError<L>, UnprovidedDeps<L>> => {\n const hasAsync = layers.some((l) => l.build(memoMap, scope)._tag === \"AsyncFx\")\n\n if (hasAsync) {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as ContextType<MergeROut<L>>,\n _E: () => undefined as unknown as MergeError<L>,\n _R: () => undefined as unknown as UnprovidedDeps<L>,\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<\n FxYield<MergeError<L>, UnprovidedDeps<L>>,\n ContextType<MergeROut<L>>,\n unknown\n > {\n let ctx = Context.empty() as ContextType<unknown>\n for (const layer of layers) {\n const buildFx = layer.build(memoMap, scope)\n if (buildFx._tag === \"AsyncFx\") {\n const gen = buildFx[Symbol.asyncIterator]()\n // oxlint-disable-next-line no-await-in-loop\n let result = await gen.next()\n while (result.done !== true) {\n const yielded = result.value\n const service = resolveService(ctx, yielded)\n if (service !== undefined) {\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(service)\n continue\n }\n const value = yield yielded as FxYield<MergeError<L>, UnprovidedDeps<L>>\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(value)\n }\n ctx = Context.merge(ctx, result.value)\n } else {\n const gen = buildFx[Symbol.iterator]()\n let result = gen.next()\n while (result.done !== true) {\n const yielded = result.value\n const service = resolveService(ctx, yielded)\n if (service !== undefined) {\n result = gen.next(service)\n continue\n }\n const value = yield yielded as FxYield<MergeError<L>, UnprovidedDeps<L>>\n result = gen.next(value)\n }\n ctx = Context.merge(ctx, result.value)\n }\n }\n return ctx as ContextType<MergeROut<L>>\n },\n } as AsyncFx<ContextType<MergeROut<L>>, MergeError<L>, UnprovidedDeps<L>>\n }\n\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as ContextType<MergeROut<L>>,\n _E: () => undefined as unknown as MergeError<L>,\n _R: () => undefined as unknown as UnprovidedDeps<L>,\n },\n *[Symbol.iterator](): Generator<FxYield<MergeError<L>, UnprovidedDeps<L>>, ContextType<MergeROut<L>>, unknown> {\n let ctx = Context.empty() as ContextType<unknown>\n for (const layer of layers) {\n const buildFx = layer.build(memoMap, scope)\n if (buildFx._tag !== \"SyncFx\") {\n throw new Error(\"Expected sync layer in sync context\")\n }\n const gen = buildFx[Symbol.iterator]()\n let result = gen.next()\n while (result.done !== true) {\n const yielded = result.value\n const service = resolveService(ctx, yielded)\n if (service !== undefined) {\n result = gen.next(service)\n continue\n }\n const value = yield yielded as FxYield<MergeError<L>, UnprovidedDeps<L>>\n result = gen.next(value)\n }\n ctx = Context.merge(ctx, result.value)\n }\n return ctx as ContextType<MergeROut<L>>\n },\n } as SyncFx<ContextType<MergeROut<L>>, MergeError<L>, UnprovidedDeps<L>>\n },\n }\n}\n\n/**\n * Create a successful no-dependency layer from a plain service value.\n *\n * @example\n * ```ts\n * import { Layer } from \"@nicolastoulemont/std\"\n *\n * import { Service } from \"@nicolastoulemont/std\"\n * \n * const Port = Service.tag<number>(\"Port\")\n * const portLayer = Layer.ok(Port, 3000)\n * // => layer that provides Port\n * ```\n *\n * @category Constructors\n */\nexport const ok = layerOk\n\n/**\n * Create a layer that always fails with an error.\n *\n * @example\n * ```ts\n * import { Layer } from \"@nicolastoulemont/std\"\n *\n * const failingLayer = Layer.err(\"missing-config\")\n * // => layer that always fails with Err(\"missing-config\")\n * ```\n *\n * @category Constructors\n */\nexport const err = layerErr\n\n/**\n * Create a layer from an effectful service builder.\n *\n * @example\n * ```ts\n * import { Layer } from \"@nicolastoulemont/std\"\n *\n * import { Fx, Service } from \"@nicolastoulemont/std\"\n * \n * const Port = Service.tag<number>(\"Port\")\n * const portLayer = Layer.fx(Port)(Fx.gen(function* () {\n * return 3000\n * }))\n * // => effect-backed layer\n * ```\n *\n * @category Constructors\n */\nexport const fx = layerFx\n\n/**\n * Create a scoped layer that registers resource finalizers.\n *\n * @example\n * ```ts\n * import { Layer } from \"@nicolastoulemont/std\"\n *\n * import { Fx, Service } from \"@nicolastoulemont/std\"\n * \n * const Resource = Service.tag<{ close: () => void }>(\"Resource\")\n * const resourceLayer = Layer.scoped(Resource)(Fx.gen(function* () {\n * return { close: () => undefined }\n * }) as never)\n * // => scoped layer with finalization support\n * ```\n *\n * @category Constructors\n */\nexport const scoped = layerScoped\n\n/**\n * Provide one layer to another, satisfying dependencies.\n *\n * @example\n * ```ts\n * import { Layer } from \"@nicolastoulemont/std\"\n *\n * import { Service } from \"@nicolastoulemont/std\"\n * \n * const Logger = Service.tag<{ log: (message: string) => void }>(\"Logger\")\n * const App = Service.tag<{ start: () => void }>(\"App\")\n * const loggerLayer = Layer.ok(Logger, { log: () => undefined })\n * const appLayer = Layer.ok(App, { start: () => undefined })\n * const provided = Layer.provide(loggerLayer)(appLayer)\n * // => composed layer\n * ```\n *\n * @category Sequencing\n */\nexport const provide = layerProvide\n\n/**\n * Merge multiple layers into a single composite layer.\n *\n * @example\n * ```ts\n * import { Layer } from \"@nicolastoulemont/std\"\n *\n * import { Service } from \"@nicolastoulemont/std\"\n * \n * const Logger = Service.tag<{ log: (message: string) => void }>(\"Logger\")\n * const Clock = Service.tag<{ now: () => number }>(\"Clock\")\n * const merged = Layer.merge(\n * Layer.ok(Logger, { log: () => undefined }),\n * Layer.ok(Clock, { now: () => Date.now() }),\n * )\n * // => layer that provides Logger | Clock\n * ```\n *\n * @category Combining\n */\nexport const merge = layerMerge\n\n/* oxlint-enable no-unsafe-type-assertion */\n"],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { f as RunnableFx, m as SyncFx } from "./fx.types-DeEWEltG.mjs";
|
|
2
|
+
import { t as Context } from "./context-r8ESJiFn.mjs";
|
|
3
|
+
import { n as ScopeService } from "./scope-CZdp4wKX.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/provide/memo-map.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* MemoMap caches built layers so each layer is only built once.
|
|
9
|
+
* Multiple dependents share the same service instance.
|
|
10
|
+
*
|
|
11
|
+
* This implements the "service singleton" pattern where a service
|
|
12
|
+
* is instantiated once and shared across all consumers.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* // Database is built once, shared by DocumentService and TeamService
|
|
17
|
+
* const AppLayer = Layer.merge(
|
|
18
|
+
* ConfigLive,
|
|
19
|
+
* LoggerLive,
|
|
20
|
+
* DatabaseLive, // Built once
|
|
21
|
+
* DocumentServiceLive, // Uses shared Database
|
|
22
|
+
* TeamServiceLive, // Uses same Database instance
|
|
23
|
+
* )
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
declare class MemoMap {
|
|
27
|
+
private cache;
|
|
28
|
+
/**
|
|
29
|
+
* Get a cached context or build the layer if not cached.
|
|
30
|
+
*
|
|
31
|
+
* @param layer - The layer to get or build
|
|
32
|
+
* @param scope - The scope for resource management
|
|
33
|
+
* @param deps - Context containing the layer's dependencies
|
|
34
|
+
* @returns A RunnableFx producing the layer's context
|
|
35
|
+
*/
|
|
36
|
+
getOrBuild<ROut, E, RIn>(layer: Layer<ROut, E, RIn>, scope: ScopeService, deps: Context<RIn>): RunnableFx<Context<ROut>, E>;
|
|
37
|
+
/**
|
|
38
|
+
* Clear the cache.
|
|
39
|
+
* Useful for testing.
|
|
40
|
+
*/
|
|
41
|
+
clear(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Get the number of cached layers.
|
|
44
|
+
*/
|
|
45
|
+
get size(): number;
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/layer/layer.types.d.ts
|
|
49
|
+
/**
|
|
50
|
+
* Layer<ROut, E, RIn, Sync> describes how to build services:
|
|
51
|
+
* - ROut: Services this layer provides
|
|
52
|
+
* - E: Errors that can occur during construction
|
|
53
|
+
* - RIn: Services this layer requires to build
|
|
54
|
+
* - Sync: Whether the layer builds synchronously (true = sync, false = async)
|
|
55
|
+
*/
|
|
56
|
+
type Layer<ROut, E = never, RIn = never, Sync extends boolean = boolean> = {
|
|
57
|
+
readonly _tag: "Layer";
|
|
58
|
+
/** Phantom type for output services */
|
|
59
|
+
readonly _ROut: ROut;
|
|
60
|
+
/** Phantom type for errors */
|
|
61
|
+
readonly _E: E;
|
|
62
|
+
/** Phantom type for input requirements */
|
|
63
|
+
readonly _RIn: RIn;
|
|
64
|
+
/** Phantom type for sync tracking */
|
|
65
|
+
readonly _Sync: Sync;
|
|
66
|
+
/**
|
|
67
|
+
* Build the layer given its dependencies.
|
|
68
|
+
* Returns a RunnableFx that produces a Context with the provided services.
|
|
69
|
+
*
|
|
70
|
+
* @param memoMap - Cache for layer memoization
|
|
71
|
+
* @param scope - Scope for resource management
|
|
72
|
+
* @returns A RunnableFx that produces the context
|
|
73
|
+
*/
|
|
74
|
+
build(memoMap: MemoMap, scope: ScopeService): Sync extends true ? SyncFx<Context<ROut>, E, RIn> : RunnableFx<Context<ROut>, E, RIn>;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Merge all ROut types from an array of layers into a union.
|
|
78
|
+
*/
|
|
79
|
+
type MergeROut<L extends readonly Layer<unknown, unknown, unknown>[]> = L[number] extends Layer<infer ROut, unknown, unknown> ? ROut : never;
|
|
80
|
+
/**
|
|
81
|
+
* Merge all error types from an array of layers into a union.
|
|
82
|
+
*/
|
|
83
|
+
type MergeError<L extends readonly Layer<unknown, unknown, unknown>[]> = L[number] extends Layer<unknown, infer E, unknown> ? E : never;
|
|
84
|
+
/**
|
|
85
|
+
* Get all requirements from an array of layers that are NOT provided by any layer in the array.
|
|
86
|
+
* This computes the "unprovided" or "external" dependencies.
|
|
87
|
+
*/
|
|
88
|
+
type UnprovidedDeps<L extends readonly Layer<unknown, unknown, unknown>[]> = Exclude<MergeRIn<L>, MergeROut<L>>;
|
|
89
|
+
/**
|
|
90
|
+
* Merge all RIn types from an array of layers into a union.
|
|
91
|
+
*/
|
|
92
|
+
type MergeRIn<L extends readonly Layer<unknown, unknown, unknown>[]> = L[number] extends Layer<unknown, unknown, infer RIn> ? RIn : never;
|
|
93
|
+
/**
|
|
94
|
+
* Check if all layers in an array are sync.
|
|
95
|
+
* Returns true only if all layers have Sync=true.
|
|
96
|
+
*/
|
|
97
|
+
type AllSync<L extends readonly Layer<unknown, unknown, unknown>[]> = L extends readonly [] ? true : L extends readonly [Layer<unknown, unknown, unknown, infer S>, ...infer Rest] ? S extends true ? Rest extends readonly Layer<unknown, unknown, unknown>[] ? AllSync<Rest> : false : false : false;
|
|
98
|
+
//#endregion
|
|
99
|
+
export { UnprovidedDeps as a, MergeROut as i, Layer as n, MergeError as r, AllSync as t };
|
|
100
|
+
//# sourceMappingURL=layer.types-DgpCIsk_.d.mts.map
|