@nicolastoulemont/std 0.7.2 → 0.8.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.
Files changed (209) hide show
  1. package/README.md +570 -168
  2. package/dist/adt/index.d.mts +1 -1
  3. package/dist/adt/index.mjs +1 -1
  4. package/dist/adt-CzdkjlUM.mjs +2 -0
  5. package/dist/adt-CzdkjlUM.mjs.map +1 -0
  6. package/dist/brand/index.d.mts +1 -1
  7. package/dist/brand/index.mjs +1 -1
  8. package/dist/brand-DZgGDrAe.mjs +2 -0
  9. package/dist/brand-DZgGDrAe.mjs.map +1 -0
  10. package/dist/brand.types-B3NDX1vo.d.mts +62 -0
  11. package/dist/brand.types-B3NDX1vo.d.mts.map +1 -0
  12. package/dist/context/index.d.mts +1 -1
  13. package/dist/context/index.mjs +1 -1
  14. package/dist/{context-CCHj1nab.mjs → context-0xDbwtpx.mjs} +2 -2
  15. package/dist/context-0xDbwtpx.mjs.map +1 -0
  16. package/dist/{context-r8ESJiFn.d.mts → context-B2dWloPl.d.mts} +2 -18
  17. package/dist/context-B2dWloPl.d.mts.map +1 -0
  18. package/dist/data/index.d.mts +1 -1
  19. package/dist/data/index.mjs +1 -1
  20. package/dist/{data-BLXO4XwS.mjs → data-BHYPdqWZ.mjs} +2 -2
  21. package/dist/{data-BLXO4XwS.mjs.map → data-BHYPdqWZ.mjs.map} +1 -1
  22. package/dist/{discriminator.types-CTURejXz.d.mts → discriminator.types-C-ygT2S1.d.mts} +1 -1
  23. package/dist/discriminator.types-C-ygT2S1.d.mts.map +1 -0
  24. package/dist/{dual-CZhzZslG.mjs → dual-fN6OUwN_.mjs} +1 -1
  25. package/dist/{dual-CZhzZslG.mjs.map → dual-fN6OUwN_.mjs.map} +1 -1
  26. package/dist/duration/index.d.mts +2 -0
  27. package/dist/duration/index.mjs +1 -0
  28. package/dist/duration-CYoDHcOR.mjs +2 -0
  29. package/dist/duration-CYoDHcOR.mjs.map +1 -0
  30. package/dist/either/index.d.mts +1 -1
  31. package/dist/either/index.mjs +1 -1
  32. package/dist/{either-BMLPfvMl.mjs → either-G7uOu4Ar.mjs} +2 -2
  33. package/dist/either-G7uOu4Ar.mjs.map +1 -0
  34. package/dist/{equality-CoyUHWh9.mjs → equality-BX6BUidG.mjs} +1 -1
  35. package/dist/{equality-CoyUHWh9.mjs.map → equality-BX6BUidG.mjs.map} +1 -1
  36. package/dist/{flow-D8_tllWl.mjs → flow-CNyLsPGb.mjs} +1 -1
  37. package/dist/flow-CNyLsPGb.mjs.map +1 -0
  38. package/dist/functions/index.d.mts +1 -1
  39. package/dist/functions/index.mjs +1 -1
  40. package/dist/functions-ByAk682_.mjs +2 -0
  41. package/dist/functions-ByAk682_.mjs.map +1 -0
  42. package/dist/fx/index.d.mts +1 -1
  43. package/dist/fx/index.mjs +1 -1
  44. package/dist/fx-DUXDxwsU.mjs +2 -0
  45. package/dist/fx-DUXDxwsU.mjs.map +1 -0
  46. package/dist/{fx.runtime-DclEDyjY.mjs → fx.runtime-jQxh77s3.mjs} +2 -2
  47. package/dist/{fx.runtime-DclEDyjY.mjs.map → fx.runtime-jQxh77s3.mjs.map} +1 -1
  48. package/dist/{fx.types-DeEWEltG.d.mts → fx.types-BdN1EWxr.d.mts} +1 -1
  49. package/dist/{fx.types-DeEWEltG.d.mts.map → fx.types-BdN1EWxr.d.mts.map} +1 -1
  50. package/dist/{fx.types-Bg-Mmdm5.mjs → fx.types-DyQVgTS8.mjs} +1 -1
  51. package/dist/{fx.types-Bg-Mmdm5.mjs.map → fx.types-DyQVgTS8.mjs.map} +1 -1
  52. package/dist/{index-DXbYlSnB.d.mts → index-BA0EsFxS.d.mts} +5 -74
  53. package/dist/index-BA0EsFxS.d.mts.map +1 -0
  54. package/dist/{index-UzMbg1dh.d.mts → index-BqJ1GWAF.d.mts} +20 -56
  55. package/dist/index-BqJ1GWAF.d.mts.map +1 -0
  56. package/dist/index-BsPOcZk9.d.mts +96 -0
  57. package/dist/index-BsPOcZk9.d.mts.map +1 -0
  58. package/dist/{index-DEAWPlcI.d.mts → index-CIvNgjsx.d.mts} +24 -56
  59. package/dist/index-CIvNgjsx.d.mts.map +1 -0
  60. package/dist/{index-B_iY5tq0.d.mts → index-CNTYbcY9.d.mts} +1 -21
  61. package/dist/index-CNTYbcY9.d.mts.map +1 -0
  62. package/dist/index-Ctg7XUOs.d.mts +36 -0
  63. package/dist/index-Ctg7XUOs.d.mts.map +1 -0
  64. package/dist/{index-Cq2IFito.d.mts → index-Ctqe1fD1.d.mts} +3 -17
  65. package/dist/index-Ctqe1fD1.d.mts.map +1 -0
  66. package/dist/{index-B_wWGszy.d.mts → index-D7mFNjot.d.mts} +1 -5
  67. package/dist/index-D7mFNjot.d.mts.map +1 -0
  68. package/dist/{index-CUZn-ohG.d.mts → index-D8rDE60Y.d.mts} +23 -54
  69. package/dist/index-D8rDE60Y.d.mts.map +1 -0
  70. package/dist/{index-By6dNRc4.d.mts → index-DR7hzXU4.d.mts} +3 -23
  71. package/dist/{index-By6dNRc4.d.mts.map → index-DR7hzXU4.d.mts.map} +1 -1
  72. package/dist/{index-DKS1g1oC.d.mts → index-DfQGXBQI.d.mts} +54 -45
  73. package/dist/index-DfQGXBQI.d.mts.map +1 -0
  74. package/dist/{index-BNQ9xSAz.d.mts → index-MsJqfQu0.d.mts} +64 -70
  75. package/dist/index-MsJqfQu0.d.mts.map +1 -0
  76. package/dist/{index-CGiLfREk.d.mts → index-UINIHFuh.d.mts} +39 -15
  77. package/dist/index-UINIHFuh.d.mts.map +1 -0
  78. package/dist/{index-BiiE8NS7.d.mts → index-crtzMG48.d.mts} +14 -23
  79. package/dist/index-crtzMG48.d.mts.map +1 -0
  80. package/dist/{index-B1-tBzc0.d.mts → index-dCRymj_g.d.mts} +23 -71
  81. package/dist/{index-B1-tBzc0.d.mts.map → index-dCRymj_g.d.mts.map} +1 -1
  82. package/dist/index-uE3S3Krx.d.mts +245 -0
  83. package/dist/index-uE3S3Krx.d.mts.map +1 -0
  84. package/dist/index.d.mts +21 -19
  85. package/dist/index.mjs +1 -1
  86. package/dist/layer/index.d.mts +1 -1
  87. package/dist/layer/index.mjs +1 -1
  88. package/dist/{layer-BttmtDrs.mjs → layer-CKtH7TRL.mjs} +2 -2
  89. package/dist/layer-CKtH7TRL.mjs.map +1 -0
  90. package/dist/{layer.types-DgpCIsk_.d.mts → layer.types-BB0MrvLg.d.mts} +4 -4
  91. package/dist/{layer.types-DgpCIsk_.d.mts.map → layer.types-BB0MrvLg.d.mts.map} +1 -1
  92. package/dist/multithread/index.d.mts +1 -1
  93. package/dist/multithread/index.mjs +1 -1
  94. package/dist/{multithread-xUUh4eLn.mjs → multithread-Cyc8Bz45.mjs} +2 -2
  95. package/dist/multithread-Cyc8Bz45.mjs.map +1 -0
  96. package/dist/option/index.d.mts +1 -1
  97. package/dist/option/index.mjs +1 -1
  98. package/dist/{option-Tfbo4wty.mjs → option-C2iCxAuJ.mjs} +2 -2
  99. package/dist/option-C2iCxAuJ.mjs.map +1 -0
  100. package/dist/{option.types-D1mm0zUb.mjs → option.types-CbY_swma.mjs} +1 -1
  101. package/dist/{option.types-D1mm0zUb.mjs.map → option.types-CbY_swma.mjs.map} +1 -1
  102. package/dist/{option.types-qPevEZQd.d.mts → option.types-D9hrKcfa.d.mts} +3 -3
  103. package/dist/{option.types-qPevEZQd.d.mts.map → option.types-D9hrKcfa.d.mts.map} +1 -1
  104. package/dist/order/index.d.mts +1 -1
  105. package/dist/order/index.mjs +1 -1
  106. package/dist/order-BXOBEKvB.mjs +2 -0
  107. package/dist/order-BXOBEKvB.mjs.map +1 -0
  108. package/dist/{pipeable-rfqacPxZ.d.mts → pipeable-BIrevC0D.d.mts} +1 -1
  109. package/dist/{pipeable-rfqacPxZ.d.mts.map → pipeable-BIrevC0D.d.mts.map} +1 -1
  110. package/dist/pipeable-Dp1_23zH.mjs +2 -0
  111. package/dist/{pipeable-COGyGMUV.mjs.map → pipeable-Dp1_23zH.mjs.map} +1 -1
  112. package/dist/predicate/index.d.mts +1 -1
  113. package/dist/predicate/index.mjs +1 -1
  114. package/dist/{predicate-DUhhQqWY.mjs → predicate-D_1SsIi4.mjs} +2 -2
  115. package/dist/predicate-D_1SsIi4.mjs.map +1 -0
  116. package/dist/provide/index.d.mts +1 -1
  117. package/dist/provide/index.mjs +1 -1
  118. package/dist/{provide-BmSM3Ruy.mjs → provide--yZE8x-n.mjs} +2 -2
  119. package/dist/provide--yZE8x-n.mjs.map +1 -0
  120. package/dist/queue/index.d.mts +1 -1
  121. package/dist/queue/index.mjs +1 -1
  122. package/dist/{queue-Sg6KJerl.mjs → queue-apiEOlRD.mjs} +2 -2
  123. package/dist/queue-apiEOlRD.mjs.map +1 -0
  124. package/dist/{queue.types-CD2LOu37.d.mts → queue.types-B-l5XYbU.d.mts} +1 -1
  125. package/dist/{queue.types-CD2LOu37.d.mts.map → queue.types-B-l5XYbU.d.mts.map} +1 -1
  126. package/dist/result/index.d.mts +1 -1
  127. package/dist/result/index.mjs +1 -1
  128. package/dist/{result-BEzV0DYC.mjs → result-D3VY0qBG.mjs} +2 -2
  129. package/dist/result-D3VY0qBG.mjs.map +1 -0
  130. package/dist/{result.types-_xDAei3-.d.mts → result.types-BKzChyWY.d.mts} +3 -3
  131. package/dist/{result.types-_xDAei3-.d.mts.map → result.types-BKzChyWY.d.mts.map} +1 -1
  132. package/dist/schedule/index.d.mts +1 -1
  133. package/dist/schedule/index.mjs +1 -1
  134. package/dist/schedule-B9K_2Z21.d.mts +183 -0
  135. package/dist/schedule-B9K_2Z21.d.mts.map +1 -0
  136. package/dist/schedule-C6iN3oMt.mjs +2 -0
  137. package/dist/schedule-C6iN3oMt.mjs.map +1 -0
  138. package/dist/schema/index.d.mts +2 -0
  139. package/dist/schema/index.mjs +1 -0
  140. package/dist/schema-D87TVF_b.mjs +2 -0
  141. package/dist/schema-D87TVF_b.mjs.map +1 -0
  142. package/dist/schema.shared-CI4eydjX.mjs +2 -0
  143. package/dist/schema.shared-CI4eydjX.mjs.map +1 -0
  144. package/dist/schema.types-CFzzx4bw.d.mts +45 -0
  145. package/dist/schema.types-CFzzx4bw.d.mts.map +1 -0
  146. package/dist/scope/index.d.mts +1 -1
  147. package/dist/scope/index.mjs +1 -1
  148. package/dist/{scope-CZdp4wKX.d.mts → scope-CuM3CzwG.d.mts} +3 -9
  149. package/dist/scope-CuM3CzwG.d.mts.map +1 -0
  150. package/dist/{scope-D_kzd1nT.mjs → scope-gVt4PESc.mjs} +2 -2
  151. package/dist/scope-gVt4PESc.mjs.map +1 -0
  152. package/dist/service/index.d.mts +1 -1
  153. package/dist/service/index.mjs +1 -1
  154. package/dist/{service-3PYQTUdH.mjs → service-CWAIEH46.mjs} +2 -2
  155. package/dist/service-CWAIEH46.mjs.map +1 -0
  156. package/dist/{service-DrXU7KJG.d.mts → service-D8mr0wwg.d.mts} +2 -8
  157. package/dist/service-D8mr0wwg.d.mts.map +1 -0
  158. package/dist/{service-resolution-C19smeaO.mjs → service-resolution-BefYr4nR.mjs} +1 -1
  159. package/dist/{service-resolution-C19smeaO.mjs.map → service-resolution-BefYr4nR.mjs.map} +1 -1
  160. package/package.json +9 -1
  161. package/dist/adt-DajUZvJe.mjs +0 -2
  162. package/dist/adt-DajUZvJe.mjs.map +0 -1
  163. package/dist/brand-Bia3Vj6l.mjs +0 -2
  164. package/dist/brand-Bia3Vj6l.mjs.map +0 -1
  165. package/dist/context-CCHj1nab.mjs.map +0 -1
  166. package/dist/context-r8ESJiFn.d.mts.map +0 -1
  167. package/dist/data.tagged-error.types-CGiKD-ES.d.mts +0 -29
  168. package/dist/data.tagged-error.types-CGiKD-ES.d.mts.map +0 -1
  169. package/dist/discriminator.types-CTURejXz.d.mts.map +0 -1
  170. package/dist/either-BMLPfvMl.mjs.map +0 -1
  171. package/dist/flow-D8_tllWl.mjs.map +0 -1
  172. package/dist/functions-BkevX2Dw.mjs +0 -2
  173. package/dist/functions-BkevX2Dw.mjs.map +0 -1
  174. package/dist/fx-K-a9Smhn.mjs +0 -2
  175. package/dist/fx-K-a9Smhn.mjs.map +0 -1
  176. package/dist/index-7Lv982Om.d.mts +0 -217
  177. package/dist/index-7Lv982Om.d.mts.map +0 -1
  178. package/dist/index-BNQ9xSAz.d.mts.map +0 -1
  179. package/dist/index-B_iY5tq0.d.mts.map +0 -1
  180. package/dist/index-B_wWGszy.d.mts.map +0 -1
  181. package/dist/index-BiiE8NS7.d.mts.map +0 -1
  182. package/dist/index-CGiLfREk.d.mts.map +0 -1
  183. package/dist/index-CUZn-ohG.d.mts.map +0 -1
  184. package/dist/index-Cq2IFito.d.mts.map +0 -1
  185. package/dist/index-DEAWPlcI.d.mts.map +0 -1
  186. package/dist/index-DKS1g1oC.d.mts.map +0 -1
  187. package/dist/index-DXbYlSnB.d.mts.map +0 -1
  188. package/dist/index-UzMbg1dh.d.mts.map +0 -1
  189. package/dist/layer-BttmtDrs.mjs.map +0 -1
  190. package/dist/multithread-xUUh4eLn.mjs.map +0 -1
  191. package/dist/option-Tfbo4wty.mjs.map +0 -1
  192. package/dist/order-D5c4QChk.mjs +0 -2
  193. package/dist/order-D5c4QChk.mjs.map +0 -1
  194. package/dist/pipeable-COGyGMUV.mjs +0 -2
  195. package/dist/predicate-DUhhQqWY.mjs.map +0 -1
  196. package/dist/provide-BmSM3Ruy.mjs.map +0 -1
  197. package/dist/queue-Sg6KJerl.mjs.map +0 -1
  198. package/dist/result-BEzV0DYC.mjs.map +0 -1
  199. package/dist/schedule-C6tjcJ1O.mjs +0 -2
  200. package/dist/schedule-C6tjcJ1O.mjs.map +0 -1
  201. package/dist/schedule-DlX2Dg69.d.mts +0 -144
  202. package/dist/schedule-DlX2Dg69.d.mts.map +0 -1
  203. package/dist/scope-CZdp4wKX.d.mts.map +0 -1
  204. package/dist/scope-D_kzd1nT.mjs.map +0 -1
  205. package/dist/service-3PYQTUdH.mjs.map +0 -1
  206. package/dist/service-DrXU7KJG.d.mts.map +0 -1
  207. /package/dist/{chunk-C934ptG5.mjs → chunk-oQKkju2G.mjs} +0 -0
  208. /package/dist/{option-CBCwzF0L.mjs → option-CXXiA1w-.mjs} +0 -0
  209. /package/dist/{result-B5WbPg8C.mjs → result-xFLfwriM.mjs} +0 -0
@@ -0,0 +1,183 @@
1
+ import { n as TaggedErrorFactory } from "./index-UINIHFuh.mjs";
2
+ import { n as InputError, t as Input } from "./index-BsPOcZk9.mjs";
3
+
4
+ //#region src/schedule/schedule.d.ts
5
+ declare namespace schedule_d_exports {
6
+ export { AsyncRetrySchedule, RetrySchedule, ScheduleInvalidDelayError, ScheduleInvalidFactorError, ScheduleInvalidRetryCountError, SyncRetrySchedule, exponential, fixed, recurs };
7
+ }
8
+ /**
9
+ * Retry schedule used by Fx.retry.
10
+ *
11
+ * A schedule defines:
12
+ * - how many retries are allowed after the first attempt
13
+ * - how long to wait before each retry attempt
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { Schedule } from "@nicolastoulemont/std"
18
+ *
19
+ * type Example = typeof Schedule
20
+ * ```
21
+ */
22
+ type RetrySchedule = SyncRetrySchedule | AsyncRetrySchedule;
23
+ /**
24
+ * Schedule that never introduces async delays.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { Schedule } from "@nicolastoulemont/std"
29
+ *
30
+ * type Example = typeof Schedule
31
+ * ```
32
+ */
33
+ type SyncRetrySchedule = {
34
+ readonly _tag: "RetrySchedule";
35
+ readonly _sync: true;
36
+ readonly maxRetries: number;
37
+ readonly delayForAttempt: (retryAttempt: number) => number;
38
+ };
39
+ /**
40
+ * Schedule that may delay retries, requiring async execution.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import { Schedule } from "@nicolastoulemont/std"
45
+ *
46
+ * type Example = typeof Schedule
47
+ * ```
48
+ */
49
+ type AsyncRetrySchedule = {
50
+ readonly _tag: "RetrySchedule";
51
+ readonly _sync: false;
52
+ readonly maxRetries: number;
53
+ readonly delayForAttempt: (retryAttempt: number) => number;
54
+ };
55
+ declare const ScheduleInvalidRetryCountError_base: TaggedErrorFactory<"ScheduleInvalidRetryCountError">;
56
+ /**
57
+ * Tagged error for invalid retry counts.
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * import { Schedule } from "@nicolastoulemont/std"
62
+ *
63
+ * const error = new Schedule.ScheduleInvalidRetryCountError({
64
+ * input: -1,
65
+ * message: "Schedule retry count must be an integer >= 0, received: -1",
66
+ * })
67
+ * // => error._tag === "ScheduleInvalidRetryCountError"
68
+ * ```
69
+ */
70
+ declare class ScheduleInvalidRetryCountError extends ScheduleInvalidRetryCountError_base<{
71
+ input: number;
72
+ message: string;
73
+ }> {}
74
+ declare const ScheduleInvalidDelayError_base: TaggedErrorFactory<"ScheduleInvalidDelayError">;
75
+ /**
76
+ * Tagged error for invalid schedule delay inputs.
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * import { Schedule } from "@nicolastoulemont/std"
81
+ *
82
+ * const error = new Schedule.ScheduleInvalidDelayError({
83
+ * field: "delay",
84
+ * input: "oops",
85
+ * message: "Invalid duration string: oops",
86
+ * })
87
+ * // => error._tag === "ScheduleInvalidDelayError"
88
+ * ```
89
+ */
90
+ declare class ScheduleInvalidDelayError extends ScheduleInvalidDelayError_base<{
91
+ field: "delay" | "baseDelay" | "maxDelay";
92
+ input: Input;
93
+ message: string;
94
+ cause?: InputError;
95
+ }> {}
96
+ declare const ScheduleInvalidFactorError_base: TaggedErrorFactory<"ScheduleInvalidFactorError">;
97
+ /**
98
+ * Tagged error for invalid exponential factors.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * import { Schedule } from "@nicolastoulemont/std"
103
+ *
104
+ * const error = new Schedule.ScheduleInvalidFactorError({
105
+ * input: 0,
106
+ * message: "Schedule factor must be a finite number > 0, received: 0",
107
+ * })
108
+ * // => error._tag === "ScheduleInvalidFactorError"
109
+ * ```
110
+ */
111
+ declare class ScheduleInvalidFactorError extends ScheduleInvalidFactorError_base<{
112
+ input: number;
113
+ message: string;
114
+ }> {}
115
+ type FixedScheduleOptions = {
116
+ readonly times: number;
117
+ /**
118
+ * The delay for the fixed schedule.
119
+ * in milliseconds.
120
+ */
121
+ readonly delay: Input;
122
+ };
123
+ type ExponentialScheduleOptions = {
124
+ readonly times: number;
125
+ /**
126
+ * The base delay for the exponential schedule.
127
+ * in milliseconds.
128
+ */
129
+ readonly baseDelay: Input;
130
+ /**
131
+ * The factor for the exponential schedule.
132
+ * Default: 2
133
+ */
134
+ readonly factor?: number | undefined;
135
+ /**
136
+ * The maximum delay for the exponential schedule.
137
+ * in milliseconds.
138
+ */
139
+ readonly maxDelay?: Input | undefined;
140
+ };
141
+ /**
142
+ * Retry immediately up to `times` times.
143
+ *
144
+ * @example
145
+ * ```ts
146
+ * import { Schedule } from "@nicolastoulemont/std"
147
+ *
148
+ * const schedule = Schedule.recurs(2)
149
+ * const delay = schedule.delayForAttempt(1)
150
+ * // => 0
151
+ * ```
152
+ */
153
+ declare const recurs: (times: number) => SyncRetrySchedule;
154
+ /**
155
+ * Retry with a fixed delay between attempts.
156
+ *
157
+ * @example
158
+ * ```ts
159
+ * import { Duration, Schedule } from "@nicolastoulemont/std"
160
+ *
161
+ * const schedule = Schedule.fixed({ times: 2, delay: Duration.millis(100) })
162
+ * const delay = schedule.delayForAttempt(2)
163
+ * // => 100
164
+ * ```
165
+ */
166
+ declare const fixed: (options: FixedScheduleOptions) => AsyncRetrySchedule;
167
+ /**
168
+ * Retry with exponential backoff:
169
+ * `baseDelay * factor^(retryAttempt - 1)`, optionally capped by `maxDelay`.
170
+ *
171
+ * @example
172
+ * ```ts
173
+ * import { Duration, Schedule } from "@nicolastoulemont/std"
174
+ *
175
+ * const schedule = Schedule.exponential({ times: 3, baseDelay: Duration.millis(100) })
176
+ * const delay = schedule.delayForAttempt(3)
177
+ * // => 400
178
+ * ```
179
+ */
180
+ declare const exponential: (options: ExponentialScheduleOptions) => AsyncRetrySchedule;
181
+ //#endregion
182
+ export { SyncRetrySchedule as n, schedule_d_exports as r, RetrySchedule as t };
183
+ //# sourceMappingURL=schedule-B9K_2Z21.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-B9K_2Z21.d.mts","names":[],"sources":["../src/schedule/schedule.ts"],"sourcesContent":[],"mappings":";;;;;;;AAoPA;AAiBA;AAmBA;;;;;;;;;;;;KAzOY,aAAA,GAAgB,oBAAoB;;;;;;;;;;;KAYpC,iBAAA;;;;;;;;;;;;;;;;KAiBA,kBAAA;;;;;;cAKX,qCAAA;;;;;;;;;;;;;;;cAgBY,8BAAA,SAAuC;;;;cAG/C,gCAAA;;;;;;;;;;;;;;;;cAiBQ,yBAAA,SAAkC;;SAEtC;;UAEC;;cACL,iCAAA;;;;;;;;;;;;;;;cAgBQ,0BAAA,SAAmC;;;;KAK3C,oBAAA;;;;;;kBAMa;;KAGb,0BAAA;;;;;;sBAMiB;;;;;;;;;;sBAUA;;;;;;;;;;;;;;cA4ET,2BAA0B;;;;;;;;;;;;;cAiB1B,iBAAkB,yBAAuB;;;;;;;;;;;;;;cAmBzC,uBAAwB,+BAA6B"}
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./chunk-oQKkju2G.mjs";import{r as t}from"./result-D3VY0qBG.mjs";import{t as n}from"./data-BHYPdqWZ.mjs";import{n as r,r as i}from"./duration-CYoDHcOR.mjs";var a=e({ScheduleInvalidDelayError:()=>s,ScheduleInvalidFactorError:()=>c,ScheduleInvalidRetryCountError:()=>o,exponential:()=>g,fixed:()=>h,recurs:()=>m}),o=class extends n(`ScheduleInvalidRetryCountError`){},s=class extends n(`ScheduleInvalidDelayError`){},c=class extends n(`ScheduleInvalidFactorError`){};const l=e=>{if(!Number.isInteger(e)||e<0)throw new o({input:e,message:`Schedule retry count must be an integer >= 0, received: ${String(e)}`})},u=(e,n)=>{let a=r(n);if(t(a))throw new s({field:e,input:n,message:a.error.message,cause:a.error});let o=i(a.value);if(!Number.isFinite(o)||o<0)throw new s({field:e,input:n,message:`Schedule ${e} must be a finite number >= 0, received: ${String(o)}`});return o},d=(e,t)=>{if(!Number.isFinite(t)||t<=0)throw new c({input:t,message:`Schedule ${e} must be a finite number > 0, received: ${String(t)}`})},f=(e,t)=>({_tag:`RetrySchedule`,_sync:!0,maxRetries:e,delayForAttempt:t}),p=(e,t)=>({_tag:`RetrySchedule`,_sync:!1,maxRetries:e,delayForAttempt:t}),m=e=>(l(e),f(e,()=>0)),h=e=>{l(e.times);let t=u(`delay`,e.delay);return p(e.times,()=>t)},g=e=>{l(e.times);let t=u(`baseDelay`,e.baseDelay),n=e.factor??2;d(`factor`,n);let r;return e.maxDelay!==void 0&&(r=u(`maxDelay`,e.maxDelay)),p(e.times,e=>{let i=t*n**(e-1);return r===void 0?i:Math.min(i,r)})};export{a as t};
2
+ //# sourceMappingURL=schedule-C6iN3oMt.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-C6iN3oMt.mjs","names":["Data.TaggedError","Duration.from","Result.isErr","Duration.toMillis"],"sources":["../src/schedule/schedule.ts"],"sourcesContent":["/**\n * Retry schedule constructors used by `Fx.retry`.\n *\n * **Mental model**\n * - A schedule defines retry count and per-attempt delay.\n * - Sync schedules have no async delay requirements.\n *\n * **Common tasks**\n * - Use `Schedule.recurs` for immediate retries.\n * - Use `Schedule.fixed` for constant-delay retries.\n * - Use `Schedule.exponential` for backoff.\n *\n * **Gotchas**\n * - `times` is the number of retries after the first attempt.\n * - Delay values must normalize to finite, non-negative milliseconds.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Schedule } from \"@nicolastoulemont/std\"\n *\n * const schedule = Schedule.recurs(2)\n * const delay = schedule.delayForAttempt(1)\n * // => 0\n * ```\n *\n * @module\n */\n/* oxlint-disable eslint/max-classes-per-file -- TaggedError classes are exported alongside schedule constructors by design. */\nimport { Data } from \"../data\"\nimport { Duration } from \"../duration\"\nimport { Result } from \"../result\"\n/**\n * Retry schedule used by Fx.retry.\n *\n * A schedule defines:\n * - how many retries are allowed after the first attempt\n * - how long to wait before each retry attempt\n *\n * @example\n * ```ts\n * import { Schedule } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Schedule\n * ```\n */\nexport type RetrySchedule = SyncRetrySchedule | AsyncRetrySchedule\n\n/**\n * Schedule that never introduces async delays.\n *\n * @example\n * ```ts\n * import { Schedule } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Schedule\n * ```\n */\nexport type SyncRetrySchedule = {\n readonly _tag: \"RetrySchedule\"\n readonly _sync: true\n readonly maxRetries: number\n readonly delayForAttempt: (retryAttempt: number) => number\n}\n\n/**\n * Schedule that may delay retries, requiring async execution.\n *\n * @example\n * ```ts\n * import { Schedule } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Schedule\n * ```\n */\nexport type AsyncRetrySchedule = {\n readonly _tag: \"RetrySchedule\"\n readonly _sync: false\n readonly maxRetries: number\n readonly delayForAttempt: (retryAttempt: number) => number\n}\n\n/**\n * Tagged error for invalid retry counts.\n *\n * @example\n * ```ts\n * import { Schedule } from \"@nicolastoulemont/std\"\n *\n * const error = new Schedule.ScheduleInvalidRetryCountError({\n * input: -1,\n * message: \"Schedule retry count must be an integer >= 0, received: -1\",\n * })\n * // => error._tag === \"ScheduleInvalidRetryCountError\"\n * ```\n */\nexport class ScheduleInvalidRetryCountError extends Data.TaggedError(\"ScheduleInvalidRetryCountError\")<{\n input: number\n message: string\n}> {}\n\n/**\n * Tagged error for invalid schedule delay inputs.\n *\n * @example\n * ```ts\n * import { Schedule } from \"@nicolastoulemont/std\"\n *\n * const error = new Schedule.ScheduleInvalidDelayError({\n * field: \"delay\",\n * input: \"oops\",\n * message: \"Invalid duration string: oops\",\n * })\n * // => error._tag === \"ScheduleInvalidDelayError\"\n * ```\n */\nexport class ScheduleInvalidDelayError extends Data.TaggedError(\"ScheduleInvalidDelayError\")<{\n field: \"delay\" | \"baseDelay\" | \"maxDelay\"\n input: Duration.Input\n message: string\n cause?: Duration.InputError\n}> {}\n\n/**\n * Tagged error for invalid exponential factors.\n *\n * @example\n * ```ts\n * import { Schedule } from \"@nicolastoulemont/std\"\n *\n * const error = new Schedule.ScheduleInvalidFactorError({\n * input: 0,\n * message: \"Schedule factor must be a finite number > 0, received: 0\",\n * })\n * // => error._tag === \"ScheduleInvalidFactorError\"\n * ```\n */\nexport class ScheduleInvalidFactorError extends Data.TaggedError(\"ScheduleInvalidFactorError\")<{\n input: number\n message: string\n}> {}\n\ntype FixedScheduleOptions = {\n readonly times: number\n /**\n * The delay for the fixed schedule.\n * in milliseconds.\n */\n readonly delay: Duration.Input\n}\n\ntype ExponentialScheduleOptions = {\n readonly times: number\n /**\n * The base delay for the exponential schedule.\n * in milliseconds.\n */\n readonly baseDelay: Duration.Input\n /**\n * The factor for the exponential schedule.\n * Default: 2\n */\n readonly factor?: number | undefined\n /**\n * The maximum delay for the exponential schedule.\n * in milliseconds.\n */\n readonly maxDelay?: Duration.Input | undefined\n}\n\nconst validateRetryCount = (times: number) => {\n if (!Number.isInteger(times) || times < 0) {\n throw new ScheduleInvalidRetryCountError({\n input: times,\n message: `Schedule retry count must be an integer >= 0, received: ${String(times)}`,\n })\n }\n}\n\nconst validateDelay = (field: \"delay\" | \"baseDelay\" | \"maxDelay\", input: Duration.Input): number => {\n const normalized = Duration.from(input)\n if (Result.isErr(normalized)) {\n throw new ScheduleInvalidDelayError({\n field,\n input,\n message: normalized.error.message,\n cause: normalized.error,\n })\n }\n\n const millis = Duration.toMillis(normalized.value)\n if (!Number.isFinite(millis) || millis < 0) {\n throw new ScheduleInvalidDelayError({\n field,\n input,\n message: `Schedule ${field} must be a finite number >= 0, received: ${String(millis)}`,\n })\n }\n\n return millis\n}\n\nconst validatePositiveFinite = (name: \"factor\", value: number) => {\n if (!Number.isFinite(value) || value <= 0) {\n throw new ScheduleInvalidFactorError({\n input: value,\n message: `Schedule ${name} must be a finite number > 0, received: ${String(value)}`,\n })\n }\n}\n\nconst makeSyncSchedule = (\n maxRetries: number,\n delayForAttempt: (retryAttempt: number) => number,\n): SyncRetrySchedule => ({\n _tag: \"RetrySchedule\",\n _sync: true,\n maxRetries,\n delayForAttempt,\n})\n\nconst makeAsyncSchedule = (\n maxRetries: number,\n delayForAttempt: (retryAttempt: number) => number,\n): AsyncRetrySchedule => ({\n _tag: \"RetrySchedule\",\n _sync: false,\n maxRetries,\n delayForAttempt,\n})\n\n/**\n * Retry immediately up to `times` times.\n *\n * @example\n * ```ts\n * import { Schedule } from \"@nicolastoulemont/std\"\n *\n * const schedule = Schedule.recurs(2)\n * const delay = schedule.delayForAttempt(1)\n * // => 0\n * ```\n */\nexport const recurs = (times: number): SyncRetrySchedule => {\n validateRetryCount(times)\n return makeSyncSchedule(times, () => 0)\n}\n\n/**\n * Retry with a fixed delay between attempts.\n *\n * @example\n * ```ts\n * import { Duration, Schedule } from \"@nicolastoulemont/std\"\n *\n * const schedule = Schedule.fixed({ times: 2, delay: Duration.millis(100) })\n * const delay = schedule.delayForAttempt(2)\n * // => 100\n * ```\n */\nexport const fixed = (options: FixedScheduleOptions): AsyncRetrySchedule => {\n validateRetryCount(options.times)\n const delay = validateDelay(\"delay\", options.delay)\n return makeAsyncSchedule(options.times, () => delay)\n}\n\n/**\n * Retry with exponential backoff:\n * `baseDelay * factor^(retryAttempt - 1)`, optionally capped by `maxDelay`.\n *\n * @example\n * ```ts\n * import { Duration, Schedule } from \"@nicolastoulemont/std\"\n *\n * const schedule = Schedule.exponential({ times: 3, baseDelay: Duration.millis(100) })\n * const delay = schedule.delayForAttempt(3)\n * // => 400\n * ```\n */\nexport const exponential = (options: ExponentialScheduleOptions): AsyncRetrySchedule => {\n validateRetryCount(options.times)\n const baseDelay = validateDelay(\"baseDelay\", options.baseDelay)\n\n const factor = options.factor ?? 2\n validatePositiveFinite(\"factor\", factor)\n\n let maxDelay: number | undefined\n if (options.maxDelay !== undefined) {\n maxDelay = validateDelay(\"maxDelay\", options.maxDelay)\n }\n\n return makeAsyncSchedule(options.times, (retryAttempt) => {\n const delay = baseDelay * Math.pow(factor, retryAttempt - 1)\n return maxDelay === undefined ? delay : Math.min(delay, maxDelay)\n })\n}\n"],"mappings":"0UAiGa,EAAb,cAAoDA,EAAiB,iCAAiC,AAGnG,GAiBU,EAAb,cAA+CA,EAAiB,4BAA4B,AAKzF,GAgBU,EAAb,cAAgDA,EAAiB,6BAA6B,AAG3F,GA8BH,MAAM,EAAsB,GAAkB,CAC5C,GAAI,CAAC,OAAO,UAAU,EAAM,EAAI,EAAQ,EACtC,MAAM,IAAI,EAA+B,CACvC,MAAO,EACP,QAAS,2DAA2D,OAAO,EAAM,GAClF,CAAC,EAIA,GAAiB,EAA2C,IAAkC,CAClG,IAAM,EAAaC,EAAc,EAAM,CACvC,GAAIC,EAAa,EAAW,CAC1B,MAAM,IAAI,EAA0B,CAClC,QACA,QACA,QAAS,EAAW,MAAM,QAC1B,MAAO,EAAW,MACnB,CAAC,CAGJ,IAAM,EAASC,EAAkB,EAAW,MAAM,CAClD,GAAI,CAAC,OAAO,SAAS,EAAO,EAAI,EAAS,EACvC,MAAM,IAAI,EAA0B,CAClC,QACA,QACA,QAAS,YAAY,EAAM,2CAA2C,OAAO,EAAO,GACrF,CAAC,CAGJ,OAAO,GAGH,GAA0B,EAAgB,IAAkB,CAChE,GAAI,CAAC,OAAO,SAAS,EAAM,EAAI,GAAS,EACtC,MAAM,IAAI,EAA2B,CACnC,MAAO,EACP,QAAS,YAAY,EAAK,0CAA0C,OAAO,EAAM,GAClF,CAAC,EAIA,GACJ,EACA,KACuB,CACvB,KAAM,gBACN,MAAO,GACP,aACA,kBACD,EAEK,GACJ,EACA,KACwB,CACxB,KAAM,gBACN,MAAO,GACP,aACA,kBACD,EAcY,EAAU,IACrB,EAAmB,EAAM,CAClB,EAAiB,MAAa,EAAE,EAe5B,EAAS,GAAsD,CAC1E,EAAmB,EAAQ,MAAM,CACjC,IAAM,EAAQ,EAAc,QAAS,EAAQ,MAAM,CACnD,OAAO,EAAkB,EAAQ,UAAa,EAAM,EAgBzC,EAAe,GAA4D,CACtF,EAAmB,EAAQ,MAAM,CACjC,IAAM,EAAY,EAAc,YAAa,EAAQ,UAAU,CAEzD,EAAS,EAAQ,QAAU,EACjC,EAAuB,SAAU,EAAO,CAExC,IAAI,EAKJ,OAJI,EAAQ,WAAa,IAAA,KACvB,EAAW,EAAc,WAAY,EAAQ,SAAS,EAGjD,EAAkB,EAAQ,MAAQ,GAAiB,CACxD,IAAM,EAAQ,EAAqB,IAAQ,EAAe,GAC1D,OAAO,IAAa,IAAA,GAAY,EAAQ,KAAK,IAAI,EAAO,EAAS,EACjE"}
@@ -0,0 +1,2 @@
1
+ import { t as schema_d_exports } from "../index-Ctg7XUOs.mjs";
2
+ export { schema_d_exports as Schema };
@@ -0,0 +1 @@
1
+ import{t as e}from"../schema-D87TVF_b.mjs";export{e as Schema};
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./chunk-oQKkju2G.mjs";import{t}from"./dual-fN6OUwN_.mjs";import{n}from"./flow-CNyLsPGb.mjs";import{n as r,t as i}from"./schema.shared-CI4eydjX.mjs";var a=e({is:()=>s,parse:()=>o});function o(e){return t=>{let r=e[`~standard`].validate(t);return n(r)?Promise.resolve(r).then(i):i(r)}}const s=t(2,(e,t)=>r(t,e,`Schema.is()`)._tag===`Ok`);export{a as t};
2
+ //# sourceMappingURL=schema-D87TVF_b.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-D87TVF_b.mjs","names":[],"sources":["../src/schema/schema.ts"],"sourcesContent":["import type { Result as ResultType } from \"../result/result.types\"\n/**\n * Standard Schema-backed parsing and refinement helpers.\n *\n * **Mental model**\n * - `Schema.parse` is for boundary validation and parsing.\n * - `Schema.is` is for sync-only refinement of values already in memory.\n *\n * **Common tasks**\n * - Parse loose external data into validated subtypes.\n * - Reuse a schema as a type guard for refinement-only narrowing.\n *\n * **Gotchas**\n * - `Schema.parse` may be sync or async based on the schema type you preserve.\n * - `Schema.is` supports both data-first and data-last styles.\n * - `Schema.is` must only be used with sync schemas that do not rely on transforms.\n *\n * @module\n */\nimport { dual } from \"../shared/dual\"\nimport { isPromise } from \"../shared/is-promise\"\nimport { toValidationResult, validateSync } from \"./schema.shared\"\nimport type { Input, Output, SyncRefinementSchema, SyncSchema, ValidationError } from \"./schema.types\"\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\"\n\nexport type {\n Input,\n Output,\n RefinementSchema,\n SyncRefinementSchema,\n SyncSchema,\n ValidationError,\n ValidationIssue,\n} from \"./schema.types\"\n\n/**\n * Create a schema-backed parser.\n *\n * For sync schemas the returned parser is sync.\n * For general Standard Schema values the returned parser is async.\n */\nexport function parse<S extends SyncSchema>(schema: S): (value: Input<S>) => ResultType<Output<S>, ValidationError>\nexport function parse<S extends StandardSchemaV1>(\n schema: S,\n): (value: Input<S>) => Promise<ResultType<Output<S>, ValidationError>>\nexport function parse<S extends StandardSchemaV1>(schema: S) {\n return (value: Input<S>) => {\n const result = schema[\"~standard\"].validate(value)\n\n if (isPromise(result)) {\n return Promise.resolve(result).then(toValidationResult)\n }\n\n return toValidationResult(result)\n }\n}\n\n/**\n * Create a sync-only schema-backed type guard.\n *\n * This is intended for refinement schemas where the validated output is a\n * subtype of the input value already in memory.\n *\n * Supports both data-first and data-last styles:\n * - Data-first: `Schema.is(value, schema)`\n * - Data-last: `Schema.is(schema)(value)`\n */\nexport type Is = {\n <Base, Sub extends Base>(value: Base, schema: SyncRefinementSchema<Base, Sub>): value is Sub\n <S extends SyncSchema>(value: unknown, schema: S): value is Output<S>\n <Base, Sub extends Base>(schema: SyncRefinementSchema<Base, Sub>): (value: Base) => value is Sub\n <S extends SyncSchema>(schema: S): (value: unknown) => value is Output<S>\n}\n\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- dual() requires a single implementation signature */\nexport const is: Is = dual(2, (value: unknown, schema: SyncSchema) => {\n return validateSync(schema, value, \"Schema.is()\")._tag === \"Ok\"\n}) as Is\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n"],"mappings":"uMA6CA,SAAgB,EAAkC,EAAW,CAC3D,MAAQ,IAAoB,CAC1B,IAAM,EAAS,EAAO,aAAa,SAAS,EAAM,CAMlD,OAJI,EAAU,EAAO,CACZ,QAAQ,QAAQ,EAAO,CAAC,KAAK,EAAmB,CAGlD,EAAmB,EAAO,EAsBrC,MAAa,EAAS,EAAK,GAAI,EAAgB,IACtC,EAAa,EAAQ,EAAO,cAAc,CAAC,OAAS,KAC3D"}
@@ -0,0 +1,2 @@
1
+ import{n as e}from"./flow-CNyLsPGb.mjs";import{i as t,t as n}from"./result-D3VY0qBG.mjs";function r(e){return typeof e==`object`&&e&&`key`in e?e.key:e}function i(e){return e.map(e=>({message:e.message,path:e.path?.map(r)}))}function a(e){return e.issues?n({issues:i(e.issues)}):t(e.value)}function o(t,n,r){let i=t[`~standard`].validate(n);if(e(i))throw TypeError(`Async validation is not supported in ${r}.`);return a(i)}export{o as n,a as t};
2
+ //# sourceMappingURL=schema.shared-CI4eydjX.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.shared-CI4eydjX.mjs","names":["Result.err","Result.ok"],"sources":["../src/schema/schema.shared.ts"],"sourcesContent":["import { Result } from \"../result\"\nimport type { Result as ResultType } from \"../result/result.types\"\nimport { isPromise } from \"../shared/is-promise\"\nimport type { ValidationError, ValidationIssue } from \"./schema.types\"\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\"\n\nfunction normalizePathSegment(segment: PropertyKey | { readonly key: PropertyKey }): PropertyKey {\n return typeof segment === \"object\" && segment !== null && \"key\" in segment ? segment.key : segment\n}\n\nfunction normalizeIssues(\n issues: NonNullable<StandardSchemaV1.Result<unknown>[\"issues\"]>,\n): ReadonlyArray<ValidationIssue> {\n return issues.map((issue) => ({\n message: issue.message,\n path: issue.path?.map(normalizePathSegment),\n }))\n}\n\nexport function toValidationResult<T>(result: StandardSchemaV1.Result<T>): ResultType<T, ValidationError> {\n if (result.issues) {\n return Result.err({ issues: normalizeIssues(result.issues) })\n }\n\n return Result.ok(result.value)\n}\n\nexport function validateSync<T>(\n schema: StandardSchemaV1<unknown, T>,\n value: unknown,\n operation: string,\n): ResultType<T, ValidationError> {\n const result = schema[\"~standard\"].validate(value)\n\n if (isPromise(result)) {\n throw new TypeError(`Async validation is not supported in ${operation}.`)\n }\n\n return toValidationResult(result)\n}\n"],"mappings":"yFAMA,SAAS,EAAqB,EAAmE,CAC/F,OAAO,OAAO,GAAY,UAAY,GAAoB,QAAS,EAAU,EAAQ,IAAM,EAG7F,SAAS,EACP,EACgC,CAChC,OAAO,EAAO,IAAK,IAAW,CAC5B,QAAS,EAAM,QACf,KAAM,EAAM,MAAM,IAAI,EAAqB,CAC5C,EAAE,CAGL,SAAgB,EAAsB,EAAoE,CAKxG,OAJI,EAAO,OACFA,EAAW,CAAE,OAAQ,EAAgB,EAAO,OAAO,CAAE,CAAC,CAGxDC,EAAU,EAAO,MAAM,CAGhC,SAAgB,EACd,EACA,EACA,EACgC,CAChC,IAAM,EAAS,EAAO,aAAa,SAAS,EAAM,CAElD,GAAI,EAAU,EAAO,CACnB,MAAU,UAAU,wCAAwC,EAAU,GAAG,CAG3E,OAAO,EAAmB,EAAO"}
@@ -0,0 +1,45 @@
1
+ import { StandardSchemaV1 } from "@standard-schema/spec";
2
+
3
+ //#region src/schema/schema.types.d.ts
4
+
5
+ /**
6
+ * Infer the input type from a Standard Schema.
7
+ */
8
+ type Input<S extends StandardSchemaV1> = NonNullable<S["~standard"]["types"]>["input"];
9
+ /**
10
+ * Infer the output type from a Standard Schema.
11
+ */
12
+ type Output<S extends StandardSchemaV1> = NonNullable<S["~standard"]["types"]>["output"];
13
+ /**
14
+ * Normalized validation issue shape used across std modules.
15
+ */
16
+ type ValidationIssue = {
17
+ readonly message: string;
18
+ readonly path?: ReadonlyArray<PropertyKey> | undefined;
19
+ };
20
+ /**
21
+ * Validation error containing normalized schema issues.
22
+ */
23
+ type ValidationError = {
24
+ readonly issues: ReadonlyArray<ValidationIssue>;
25
+ };
26
+ /**
27
+ * Standard Schema subtype with sync-only validation.
28
+ * Callers can preserve sync parse inference by annotating schemas with this type.
29
+ */
30
+ type SyncSchema<TInput = unknown, TOutput = TInput> = Omit<StandardSchemaV1<TInput, TOutput>, "~standard"> & {
31
+ readonly "~standard": Omit<StandardSchemaV1<TInput, TOutput>["~standard"], "validate"> & {
32
+ validate: (value: unknown) => StandardSchemaV1.Result<TOutput>;
33
+ };
34
+ };
35
+ /**
36
+ * Schema whose validated output is a refinement of a broader base type.
37
+ */
38
+ type RefinementSchema<Base, Sub extends Base> = StandardSchemaV1<Base, Sub>;
39
+ /**
40
+ * Sync-only refinement schema for building type guards.
41
+ */
42
+ type SyncRefinementSchema<Base, Sub extends Base> = SyncSchema<Base, Sub>;
43
+ //#endregion
44
+ export { SyncSchema as a, SyncRefinementSchema as i, Output as n, ValidationError as o, RefinementSchema as r, ValidationIssue as s, Input as t };
45
+ //# sourceMappingURL=schema.types-CFzzx4bw.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.types-CFzzx4bw.d.mts","names":[],"sources":["../src/schema/schema.types.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AAA4B,KAAhB,KAAgB,CAAA,UAAA,gBAAA,CAAA,GAAoB,WAApB,CAAgC,CAAhC,CAAA,WAAA,CAAA,CAAA,OAAA,CAAA,CAAA,CAAA,OAAA,CAAA;;;;AAKhB,KAAA,MAAM,CAAA,UAAW,gBAAX,CAAA,GAA+B,WAA/B,CAA2C,CAA3C,CAAA,WAAA,CAAA,CAAA,OAAA,CAAA,CAAA,CAAA,QAAA,CAAA;;;;AAA0C,KAKhD,eAAA,GALgD;EAKhD,SAAA,OAAA,EAAe,MAAA;EAQf,SAAA,IAAA,CAAA,EANM,aAMS,CANK,WAOC,CAAA,GAAA,SAAd;AAOnB,CAAA;;;;AAAkE,KARtD,eAAA,GAQsD;EAAL,SAAA,MAAA,EAP1C,aAO0C,CAP5B,eAO4B,CAAA;CACf;;;;;AACZ,KAFtB,UAEuC,CAAA,SAAA,OAAA,EAAA,UAFA,MAEA,CAAA,GAFU,IAEV,CAFe,gBAEf,CAFgC,MAEhC,EAFwC,OAExC,CAAA,EAAA,WAAA,CAAA,GAAA;EAAM,SAAA,WAAA,EADjC,IACiC,CAD5B,gBAC4B,CADX,MACW,EADH,OACG,CAAA,CAAA,WAAA,CAAA,EAAA,UAAA,CAAA,GAAA;IAO7C,QAAA,EAAA,CAAA,KAAgB,EAAA,OAAA,EAAA,GAPM,gBAAA,CAAiB,MAOvB,CAP8B,OAO9B,CAAA;EAAmB,CAAA;CAAyB;;;;AAK5D,KALA,gBAKoB,CAAA,IAAA,EAAA,YALe,IAKf,CAAA,GALuB,gBAKvB,CALwC,IAKxC,EAL8C,GAK9C,CAAA;;;;AAA2B,KAA/C,oBAA+C,CAAA,IAAA,EAAA,YAAR,IAAQ,CAAA,GAAA,UAAA,CAAW,IAAX,EAAiB,GAAjB,CAAA"}
@@ -1,2 +1,2 @@
1
- import { r as scope_d_exports } from "../scope-CZdp4wKX.mjs";
1
+ import { r as scope_d_exports } from "../scope-CuM3CzwG.mjs";
2
2
  export { scope_d_exports as Scope };
@@ -1 +1 @@
1
- import{n as e}from"../scope-D_kzd1nT.mjs";export{e as Scope};
1
+ import{n as e}from"../scope-gVt4PESc.mjs";export{e as Scope};
@@ -1,5 +1,5 @@
1
- import { m as SyncFx, t as AsyncFx } from "./fx.types-DeEWEltG.mjs";
2
- import { t as Result } from "./result.types-_xDAei3-.mjs";
1
+ import { m as SyncFx, t as AsyncFx } from "./fx.types-BdN1EWxr.mjs";
2
+ import { t as Result } from "./result.types-BKzChyWY.mjs";
3
3
 
4
4
  //#region src/scope/scope.d.ts
5
5
  declare namespace scope_d_exports {
@@ -15,8 +15,6 @@ declare namespace scope_d_exports {
15
15
  *
16
16
  * type Example = typeof Scope
17
17
  * ```
18
- *
19
- * @category Type-level
20
18
  */
21
19
  type ScopeService = {
22
20
  /**
@@ -56,8 +54,6 @@ type ScopeService = {
56
54
  * const closeFx = scope.close(Result.ok(undefined))
57
55
  * // => SyncFx<void> | AsyncFx<void>
58
56
  * ```
59
- *
60
- * @category Constructors
61
57
  */
62
58
  declare function make(): ScopeService;
63
59
  /**
@@ -70,10 +66,8 @@ declare function make(): ScopeService;
70
66
  *
71
67
  * type Example = typeof Scope
72
68
  * ```
73
- *
74
- * @category Type-level
75
69
  */
76
70
  type ExcludeScope<R> = Exclude<R, ScopeService>;
77
71
  //#endregion
78
72
  export { ScopeService as n, scope_d_exports as r, ExcludeScope as t };
79
- //# sourceMappingURL=scope-CZdp4wKX.d.mts.map
73
+ //# sourceMappingURL=scope-CuM3CzwG.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-CuM3CzwG.d.mts","names":[],"sources":["../src/scope/scope.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;AAqDA;;;AAQ+D,KARnD,YAAA,GAQmD;EAQjD;;;;;AA0Bd;AA4HA;EAAsC,YAAA,CAAA,SAAA,EAAA,GAAA,GA9JN,MA8JM,CAAA,IAAA,CAAA,GA9JS,OA8JT,CAAA,IAAA,CAAA,CAAA,EA9JyB,MA8JzB,CAAA,IAAA,CAAA;EAAG;;;;;;cAtJ3B,2BAA2B,eAAe;;;;;;;UAQ9C;;;;;;;;;;;;;;;;;iBAkBM,IAAA,CAAA,GAAQ;;;;;;;;;;;;KA4HZ,kBAAkB,QAAQ,GAAG"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./chunk-C934ptG5.mjs";import{t}from"./fx.types-Bg-Mmdm5.mjs";import{n,t as r}from"./fx.runtime-DclEDyjY.mjs";var i=e({make:()=>a});function a(){let e=[],i=!1,o=[];return{addFinalizer(n){return{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){i||e.push(n)}}},close(a){return e.some(e=>e()._tag===`AsyncFx`)?{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},async*[Symbol.asyncIterator](){if(i)return;i=!0;for(let e of[...o].toReversed()){let t=e.close(a);t._tag===`AsyncFx`?await r(t):n(t)}let t=[...e].toReversed();for(let e of t){let t=e();t._tag===`AsyncFx`?await r(t):n(t)}}}:{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){if(i)return;i=!0;for(let e of[...o].toReversed())n(e.close(a));let t=[...e].toReversed();for(let e of t)n(e())}}},fork(){let e=a();return o.push(e),e}}}export{i as n,a as t};
2
- //# sourceMappingURL=scope-D_kzd1nT.mjs.map
1
+ import{t as e}from"./chunk-oQKkju2G.mjs";import{t}from"./fx.types-DyQVgTS8.mjs";import{n,t as r}from"./fx.runtime-jQxh77s3.mjs";var i=e({make:()=>a});function a(){let e=[],i=!1,o=[];return{addFinalizer(n){return{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){i||e.push(n)}}},close(a){return e.some(e=>e()._tag===`AsyncFx`)?{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},async*[Symbol.asyncIterator](){if(i)return;i=!0;for(let e of[...o].toReversed()){let t=e.close(a);t._tag===`AsyncFx`?await r(t):n(t)}let t=[...e].toReversed();for(let e of t){let t=e();t._tag===`AsyncFx`?await r(t):n(t)}}}:{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){if(i)return;i=!0;for(let e of[...o].toReversed())n(e.close(a));let t=[...e].toReversed();for(let e of t)n(e())}}},fork(){let e=a();return o.push(e),e}}}export{i as n,a as t};
2
+ //# sourceMappingURL=scope-gVt4PESc.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-gVt4PESc.mjs","names":[],"sources":["../src/scope/scope.ts"],"sourcesContent":["/**\n * Scope lifecycle management for registering and running finalizers.\n *\n * **Mental model**\n * - A scope tracks cleanup actions and executes them in LIFO order.\n * - `Layer.scoped` and `Provide.layer` rely on scope semantics.\n *\n * **Common tasks**\n * - Create scopes with `Scope.make`.\n * - Register cleanup with `scope.addFinalizer`.\n * - Close scopes with `scope.close`.\n *\n * **Gotchas**\n * - Child scopes close before parent finalizers.\n * - Async finalizers force async scope close.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Scope } from \"@nicolastoulemont/std\"\n *\n * import { Result } from \"@nicolastoulemont/std\"\n *\n * const scope = Scope.make()\n * const closeFx = scope.close(Result.ok(undefined))\n * // => SyncFx<void> | AsyncFx<void>\n * ```\n *\n * @module\n */\nimport { runSync, runAsync } from \"../fx/fx.runtime\"\nimport { FxTypeId } from \"../fx/fx.types\"\nimport type { SyncFx, AsyncFx, FxYield } from \"../fx/fx.types\"\nimport type { Result } from \"../result/result.types\"\n\n/* oxlint-disable no-unsafe-type-assertion -- Scope encodes Fx phantom type slots and sync/async branch narrowing via assertions. */\n\n// ============================================================================\n// Scope Service\n// ============================================================================\n\n/**\n * Scope manages resource lifecycles with finalizers.\n * Finalizers run in LIFO (Last In, First Out) order when the scope closes.\n *\n * @example\n * ```ts\n * import { Scope } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Scope\n * ```\n */\nexport type ScopeService = {\n /**\n * Add a finalizer to be run when the scope closes.\n * Finalizers are run in LIFO order.\n *\n * @param finalizer - A function that returns an Fx to run on cleanup\n * @returns An Fx that completes when the finalizer is registered\n */\n addFinalizer(finalizer: () => SyncFx<void> | AsyncFx<void>): SyncFx<void>\n\n /**\n * Close the scope, running all finalizers in LIFO order.\n *\n * @param exit - The exit status of the computation\n * @returns An Fx that completes when all finalizers have run\n */\n close(exit: Result<unknown, unknown>): SyncFx<void> | AsyncFx<void>\n\n /**\n * Fork a child scope.\n * The child scope will be closed when the parent scope closes.\n *\n * @returns A new child scope\n */\n fork(): ScopeService\n}\n\n/**\n * Create a new Scope instance.\n * This is the concrete implementation of the ScopeService interface.\n *\n * @example\n * ```ts\n * import { Scope } from \"@nicolastoulemont/std\"\n *\n * import { Result } from \"@nicolastoulemont/std\"\n *\n * const scope = Scope.make()\n * const closeFx = scope.close(Result.ok(undefined))\n * // => SyncFx<void> | AsyncFx<void>\n * ```\n */\nexport function make(): ScopeService {\n type Finalizer = () => SyncFx<void> | AsyncFx<void>\n const finalizers: Finalizer[] = []\n let closed = false\n const children: ScopeService[] = []\n\n const scope: ScopeService = {\n addFinalizer(finalizer: Finalizer): SyncFx<void> {\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as void,\n _E: () => undefined as never,\n _R: () => undefined as never,\n },\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<FxYield<never, never>, void, unknown> {\n if (!closed) {\n finalizers.push(finalizer)\n }\n },\n } as SyncFx<void>\n },\n\n close(exit: Result<unknown, unknown>): SyncFx<void> | AsyncFx<void> {\n // Check if any finalizer is async\n const hasAsyncFinalizer = finalizers.some((f) => {\n const fx = f()\n return fx._tag === \"AsyncFx\"\n })\n\n if (hasAsyncFinalizer) {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as void,\n _E: () => undefined as never,\n _R: () => undefined as never,\n },\n // oxlint-disable-next-line require-yield\n async *[Symbol.asyncIterator](): AsyncGenerator<FxYield<never, never>, void, unknown> {\n if (closed) return\n closed = true\n\n // Close children first\n for (const child of [...children].toReversed()) {\n const childClose = child.close(exit)\n if (childClose._tag === \"AsyncFx\") {\n // oxlint-disable-next-line no-await-in-loop\n await runAsync(childClose)\n } else {\n runSync(childClose)\n }\n }\n\n // Run finalizers in LIFO order\n const reversed = [...finalizers].toReversed()\n for (const finalizer of reversed) {\n const fx = finalizer()\n if (fx._tag === \"AsyncFx\") {\n // oxlint-disable-next-line no-await-in-loop\n await runAsync(fx)\n } else {\n runSync(fx)\n }\n }\n },\n } as AsyncFx<void>\n }\n\n // Sync version\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as void,\n _E: () => undefined as never,\n _R: () => undefined as never,\n },\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<FxYield<never, never>, void, unknown> {\n if (closed) return\n closed = true\n\n // Close children first\n for (const child of [...children].toReversed()) {\n const childClose = child.close(exit)\n runSync(childClose as SyncFx<void>)\n }\n\n // Run finalizers in LIFO order\n const reversed = [...finalizers].toReversed()\n for (const finalizer of reversed) {\n const fx = finalizer()\n runSync(fx as SyncFx<void>)\n }\n },\n } as SyncFx<void>\n },\n\n fork(): ScopeService {\n const child = make()\n children.push(child)\n return child\n },\n }\n\n return scope\n}\n\n// ============================================================================\n// Helper Types\n// ============================================================================\n\n/**\n * Type utility to exclude Scope from requirements.\n * Used by Layer.scoped to auto-provide Scope.\n *\n * @example\n * ```ts\n * import { Scope } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Scope\n * ```\n */\nexport type ExcludeScope<R> = Exclude<R, ScopeService>\n\n/* oxlint-enable no-unsafe-type-assertion */\n"],"mappings":"sJA+FA,SAAgB,GAAqB,CAEnC,IAAM,EAA0B,EAAE,CAC9B,EAAS,GACP,EAA2B,EAAE,CAsGnC,MApG4B,CAC1B,aAAa,EAAoC,CAC/C,MAAO,CACL,KAAM,UACL,GAAW,CACV,OAAU,IAAA,GACV,OAAU,IAAA,GACV,OAAU,IAAA,GACX,CAED,EAAE,OAAO,WAA6D,CAC/D,GACH,EAAW,KAAK,EAAU,EAG/B,EAGH,MAAM,EAA8D,CA+ClE,OA7C0B,EAAW,KAAM,GAC9B,GAAG,CACJ,OAAS,UACnB,CAGO,CACL,KAAM,WACL,GAAW,CACV,OAAU,IAAA,GACV,OAAU,IAAA,GACV,OAAU,IAAA,GACX,CAED,OAAQ,OAAO,gBAAuE,CACpF,GAAI,EAAQ,OACZ,EAAS,GAGT,IAAK,IAAM,IAAS,CAAC,GAAG,EAAS,CAAC,YAAY,CAAE,CAC9C,IAAM,EAAa,EAAM,MAAM,EAAK,CAChC,EAAW,OAAS,UAEtB,MAAM,EAAS,EAAW,CAE1B,EAAQ,EAAW,CAKvB,IAAM,EAAW,CAAC,GAAG,EAAW,CAAC,YAAY,CAC7C,IAAK,IAAM,KAAa,EAAU,CAChC,IAAM,EAAK,GAAW,CAClB,EAAG,OAAS,UAEd,MAAM,EAAS,EAAG,CAElB,EAAQ,EAAG,GAIlB,CAII,CACL,KAAM,UACL,GAAW,CACV,OAAU,IAAA,GACV,OAAU,IAAA,GACV,OAAU,IAAA,GACX,CAED,EAAE,OAAO,WAA6D,CACpE,GAAI,EAAQ,OACZ,EAAS,GAGT,IAAK,IAAM,IAAS,CAAC,GAAG,EAAS,CAAC,YAAY,CAE5C,EADmB,EAAM,MAAM,EAAK,CACD,CAIrC,IAAM,EAAW,CAAC,GAAG,EAAW,CAAC,YAAY,CAC7C,IAAK,IAAM,KAAa,EAEtB,EADW,GAAW,CACK,EAGhC,EAGH,MAAqB,CACnB,IAAM,EAAQ,GAAM,CAEpB,OADA,EAAS,KAAK,EAAM,CACb,GAEV"}
@@ -1,2 +1,2 @@
1
- import { n as service_d_exports } from "../service-DrXU7KJG.mjs";
1
+ import { n as service_d_exports } from "../service-D8mr0wwg.mjs";
2
2
  export { service_d_exports as Service };
@@ -1 +1 @@
1
- import{t as e}from"../service-3PYQTUdH.mjs";export{e as Service};
1
+ import{t as e}from"../service-CWAIEH46.mjs";export{e as Service};
@@ -1,2 +1,2 @@
1
- import{t as e}from"./chunk-C934ptG5.mjs";import{t}from"./fx.types-Bg-Mmdm5.mjs";var n=e({Service:()=>r,tag:()=>i});function r(){return e=>{let n=class{static _tag=`Service`;static key=e;static _Self=void 0;static[t]={_A:()=>void 0,_E:()=>void 0,_R:()=>void 0};static*[Symbol.iterator](){return yield n}};return n}}function i(e){let n={_tag:`Service`,key:e,_Self:void 0,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){return yield n}};return n}export{n as t};
2
- //# sourceMappingURL=service-3PYQTUdH.mjs.map
1
+ import{t as e}from"./chunk-oQKkju2G.mjs";import{t}from"./fx.types-DyQVgTS8.mjs";var n=e({Service:()=>r,tag:()=>i});function r(){return e=>{let n=class{static _tag=`Service`;static key=e;static _Self=void 0;static[t]={_A:()=>void 0,_E:()=>void 0,_R:()=>void 0};static*[Symbol.iterator](){return yield n}};return n}}function i(e){let n={_tag:`Service`,key:e,_Self:void 0,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){return yield n}};return n}export{n as t};
2
+ //# sourceMappingURL=service-CWAIEH46.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-CWAIEH46.mjs","names":["tag"],"sources":["../src/service/service.ts"],"sourcesContent":["/**\n * Service tag constructors for `Fx` dependency injection.\n *\n * **Mental model**\n * - A service tag is both a runtime lookup key and a typed requirement marker.\n * - `Service()` and `tag()` create values that can be yielded in `Fx.gen`.\n *\n * **Common tasks**\n * - Define class-based services with `Service`.\n * - Define interface-only tags with `tag`.\n *\n * **Gotchas**\n * - Service keys must be globally unique in a context.\n * - Yielding a service tag requires the service to be provided.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Service } from \"@nicolastoulemont/std\"\n *\n * const Logger = Service.Service<{ log: (message: string) => void }>()(\"Logger\")\n * // => service class with key \"Logger\"\n * ```\n *\n * @module\n */\nimport { FxTypeId } from \"../fx/fx.types\"\nimport type { Fx } from \"../fx/fx.types\"\n\n/* oxlint-disable no-unsafe-type-assertion -- Service tags carry phantom generic metadata at runtime and require explicit type assertions. */\n\n// ============================================================================\n// Service Class Types\n// ============================================================================\n\n/**\n * The interface returned by Service()().\n * Acts as both a type tag and a runtime lookup key.\n * Implements Fx protocol with E = never (no errors) and R = Self (requires itself).\n * When yielded, yields itself (as Fx) for proper type inference.\n *\n * @example\n * ```ts\n * import { Service } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Service\n * ```\n */\nexport type ServiceClass<Self, Key extends string = string> = Fx<Self, never, Self> & {\n readonly _tag: \"Service\"\n readonly key: Key\n // Phantom type\n readonly _Self: Self\n\n /**\n * Yielding the service class in a gen computation\n * returns the service instance from context.\n * Yields the ServiceClass itself (which implements Fx) for type inference.\n */\n [Symbol.iterator](): Generator<ServiceClass<Self, Key>, Self, unknown>\n}\n\n// ============================================================================\n// Service Factory\n// ============================================================================\n\n/**\n * Define a service with a unique key.\n * The returned class acts as both a type and a runtime tag for lookup.\n *\n * Usage follows a double-invocation pattern:\n * - First call provides the Self type parameter\n * - Second call provides the unique key\n *\n * @example\n * ```ts\n * import { Service } from \"@nicolastoulemont/std\"\n *\n * const Logger = Service.Service<string>()(\"Logger\")\n * // => service class with key \"Logger\"\n * ```\n */\nexport function Service<Self>(): <Key extends string>(key: Key) => ServiceClass<Self, Key> & (new () => Self) {\n return <Key extends string>(key: Key): ServiceClass<Self, Key> & (new () => Self) => {\n // Create the base class with proper prototype\n // oxlint-disable-next-line typescript/no-extraneous-class\n const ServiceBase = class {\n static readonly _tag = \"Service\" as const\n static readonly key: Key = key\n static readonly _Self: Self = undefined as unknown as Self\n\n static readonly [FxTypeId] = {\n _A: () => undefined as unknown as Self,\n _E: () => undefined as never,\n _R: () => undefined as unknown as Self,\n };\n\n /**\n * Yielding the class returns the class itself (for type inference).\n * The runtime intercepts this and provides the actual service instance.\n */\n static *[Symbol.iterator](): Generator<typeof ServiceBase, Self, Self> {\n // Yield the class itself - it implements Fx<Self, never, Self>\n // The runtime will recognize ServiceClass and inject the service\n const serviceInstance = yield ServiceBase\n return serviceInstance\n }\n }\n\n // Return with correct typing\n return ServiceBase as unknown as ServiceClass<Self, Key> & (new () => Self)\n }\n}\n\n/**\n * Create a service tag without class syntax.\n * Useful for simple services that don't need class inheritance.\n *\n * @example\n * ```ts\n * import { Service } from \"@nicolastoulemont/std\"\n *\n * const Logger = Service.tag<string>(\"Logger\")\n * // => plain service tag with key \"Logger\"\n * ```\n */\nexport function tag<S>(key: string): ServiceClass<S> {\n const tag: ServiceClass<S> = {\n _tag: \"Service\",\n key,\n _Self: undefined as unknown as S,\n [FxTypeId]: {\n _A: () => undefined as unknown as S,\n _E: () => undefined as never,\n _R: () => undefined as unknown as S,\n },\n *[Symbol.iterator](): Generator<ServiceClass<S>, S, S> {\n // Yield the tag itself - it implements Fx<S, never, S>\n // The runtime will recognize ServiceClass and inject the service\n const serviceInstance = yield tag\n return serviceInstance\n },\n }\n return tag\n}\n\n/* oxlint-enable no-unsafe-type-assertion */\n"],"mappings":"mHAmFA,SAAgB,GAA8F,CAC5G,MAA4B,IAAyD,CAGnF,IAAM,EAAc,KAAM,CACxB,OAAgB,KAAO,UACvB,OAAgB,IAAW,EAC3B,OAAgB,MAAc,IAAA,GAE9B,OAAiB,GAAY,CAC3B,OAAU,IAAA,GACV,OAAU,IAAA,GACV,OAAU,IAAA,GACX,CAMD,QAAS,OAAO,WAAuD,CAIrE,OADwB,MAAM,IAMlC,OAAO,GAgBX,SAAgB,EAAO,EAA8B,CACnD,IAAMA,EAAuB,CAC3B,KAAM,UACN,MACA,MAAO,IAAA,IACN,GAAW,CACV,OAAU,IAAA,GACV,OAAU,IAAA,GACV,OAAU,IAAA,GACX,CACD,EAAE,OAAO,WAA8C,CAIrD,OADwB,MAAMA,GAGjC,CACD,OAAOA"}
@@ -1,4 +1,4 @@
1
- import { i as Fx } from "./fx.types-DeEWEltG.mjs";
1
+ import { i as Fx } from "./fx.types-BdN1EWxr.mjs";
2
2
 
3
3
  //#region src/service/service.d.ts
4
4
  declare namespace service_d_exports {
@@ -16,8 +16,6 @@ declare namespace service_d_exports {
16
16
  *
17
17
  * type Example = typeof Service
18
18
  * ```
19
- *
20
- * @category Models
21
19
  */
22
20
  type ServiceClass<Self, Key extends string = string> = Fx<Self, never, Self> & {
23
21
  readonly _tag: "Service";
@@ -45,8 +43,6 @@ type ServiceClass<Self, Key extends string = string> = Fx<Self, never, Self> & {
45
43
  * const Logger = Service.Service<string>()("Logger")
46
44
  * // => service class with key "Logger"
47
45
  * ```
48
- *
49
- * @category Utilities
50
46
  */
51
47
  declare function Service<Self>(): <Key extends string>(key: Key) => ServiceClass<Self, Key> & (new () => Self);
52
48
  /**
@@ -60,10 +56,8 @@ declare function Service<Self>(): <Key extends string>(key: Key) => ServiceClass
60
56
  * const Logger = Service.tag<string>("Logger")
61
57
  * // => plain service tag with key "Logger"
62
58
  * ```
63
- *
64
- * @category Utilities
65
59
  */
66
60
  declare function tag<S>(key: string): ServiceClass<S>;
67
61
  //#endregion
68
62
  export { service_d_exports as n, ServiceClass as t };
69
- //# sourceMappingURL=service-DrXU7KJG.d.mts.map
63
+ //# sourceMappingURL=service-D8mr0wwg.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-D8mr0wwg.d.mts","names":[],"sources":["../src/service/service.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;AAiDA;;;;;AAIkB,KAJN,YAIM,CAAA,IAAA,EAAA,YAAA,MAAA,GAAA,MAAA,CAAA,GAJ4C,EAI5C,CAJ+C,IAI/C,EAAA,KAAA,EAJ4D,IAI5D,CAAA,GAAA;EAO4B,SAAA,IAAA,EAAA,SAAA;EAAM,SAAA,GAAA,EATpC,GASoC;EAAnB,SAAA,KAAA,EAPf,IAOe;EAAyB;;;AAuB1D;;EAAgF,CAAA,MAAA,CAAA,QAAA,GAAA,EAvBzD,SAuByD,CAvB/C,YAuB+C,CAvBlC,IAuBkC,EAvB5B,GAuB4B,CAAA,EAvBtB,IAuBsB,EAAA,OAAA,CAAA;CAAM;;;;AA4CtF;;;;;;;;;;;;;iBA5CgB,2CAA2C,QAAQ,aAAa,MAAM,kBAAkB;;;;;;;;;;;;;iBA4CxF,qBAAqB,aAAa"}
@@ -1,2 +1,2 @@
1
1
  function e(e){return typeof e==`object`&&!!e&&`_tag`in e&&e._tag===`Service`&&`key`in e&&typeof e.key==`string`}function t(t){return e(t)?t:void 0}function n(e,n){let r=t(n);if(r!==void 0)return e._services.get(r.key)}export{n,t};
2
- //# sourceMappingURL=service-resolution-C19smeaO.mjs.map
2
+ //# sourceMappingURL=service-resolution-BefYr4nR.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"service-resolution-C19smeaO.mjs","names":[],"sources":["../src/service/service-resolution.ts"],"sourcesContent":["import type { Context } from \"../context/context\"\n\ntype ServiceRequest = {\n _tag: \"Service\"\n key: string\n}\n\n/**\n * Narrow an unknown yielded value to a service request.\n */\nfunction isServiceRequest(value: unknown): value is ServiceRequest {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"_tag\" in value &&\n value._tag === \"Service\" &&\n \"key\" in value &&\n typeof value.key === \"string\"\n )\n}\n\nexport function asServiceRequest(value: unknown) {\n return isServiceRequest(value) ? value : undefined\n}\n\n/**\n * Resolve a yielded service request from a context.\n */\nexport function resolveService<R>(ctx: Context<R>, value: unknown) {\n const request = asServiceRequest(value)\n if (request === undefined) return undefined\n return ctx._services.get(request.key)\n}\n"],"mappings":"AAUA,SAAS,EAAiB,EAAyC,CACjE,OACE,OAAO,GAAU,YACjB,GACA,SAAU,GACV,EAAM,OAAS,WACf,QAAS,GACT,OAAO,EAAM,KAAQ,SAIzB,SAAgB,EAAiB,EAAgB,CAC/C,OAAO,EAAiB,EAAM,CAAG,EAAQ,IAAA,GAM3C,SAAgB,EAAkB,EAAiB,EAAgB,CACjE,IAAM,EAAU,EAAiB,EAAM,CACnC,OAAY,IAAA,GAChB,OAAO,EAAI,UAAU,IAAI,EAAQ,IAAI"}
1
+ {"version":3,"file":"service-resolution-BefYr4nR.mjs","names":[],"sources":["../src/service/service-resolution.ts"],"sourcesContent":["import type { Context } from \"../context/context\"\n\ntype ServiceRequest = {\n _tag: \"Service\"\n key: string\n}\n\n/**\n * Narrow an unknown yielded value to a service request.\n */\nfunction isServiceRequest(value: unknown): value is ServiceRequest {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"_tag\" in value &&\n value._tag === \"Service\" &&\n \"key\" in value &&\n typeof value.key === \"string\"\n )\n}\n\nexport function asServiceRequest(value: unknown) {\n return isServiceRequest(value) ? value : undefined\n}\n\n/**\n * Resolve a yielded service request from a context.\n */\nexport function resolveService<R>(ctx: Context<R>, value: unknown) {\n const request = asServiceRequest(value)\n if (request === undefined) return undefined\n return ctx._services.get(request.key)\n}\n"],"mappings":"AAUA,SAAS,EAAiB,EAAyC,CACjE,OACE,OAAO,GAAU,YACjB,GACA,SAAU,GACV,EAAM,OAAS,WACf,QAAS,GACT,OAAO,EAAM,KAAQ,SAIzB,SAAgB,EAAiB,EAAgB,CAC/C,OAAO,EAAiB,EAAM,CAAG,EAAQ,IAAA,GAM3C,SAAgB,EAAkB,EAAiB,EAAgB,CACjE,IAAM,EAAU,EAAiB,EAAM,CACnC,OAAY,IAAA,GAChB,OAAO,EAAI,UAAU,IAAI,EAAQ,IAAI"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nicolastoulemont/std",
3
- "version": "0.7.2",
3
+ "version": "0.8.0",
4
4
  "description": "Collection of utility functions",
5
5
  "homepage": "https://github.com/nicolastoulemont/toolbelt/tree/main/packages/std",
6
6
  "license": "ISC",
@@ -32,6 +32,10 @@
32
32
  "types": "./dist/data/index.d.mts",
33
33
  "default": "./dist/data/index.mjs"
34
34
  },
35
+ "./duration": {
36
+ "types": "./dist/duration/index.d.mts",
37
+ "default": "./dist/duration/index.mjs"
38
+ },
35
39
  "./either": {
36
40
  "types": "./dist/either/index.d.mts",
37
41
  "default": "./dist/either/index.mjs"
@@ -80,6 +84,10 @@
80
84
  "types": "./dist/schedule/index.d.mts",
81
85
  "default": "./dist/schedule/index.mjs"
82
86
  },
87
+ "./schema": {
88
+ "types": "./dist/schema/index.d.mts",
89
+ "default": "./dist/schema/index.mjs"
90
+ },
83
91
  "./scope": {
84
92
  "types": "./dist/scope/index.d.mts",
85
93
  "default": "./dist/scope/index.mjs"
@@ -1,2 +0,0 @@
1
- import{t as e}from"./chunk-C934ptG5.mjs";import{i as t,n,r,t as i}from"./equality-CoyUHWh9.mjs";import{n as a}from"./flow-D8_tllWl.mjs";import{r as o,t as s}from"./result-BEzV0DYC.mjs";function c(e,t){let n=t[e._tag];return n(e)}function l(e){return typeof e!=`object`||!e?!1:Object.getPrototypeOf(e)===null||Object.getPrototypeOf(e)===Object.prototype}function u(e){return typeof e==`function`&&`_variant`in e&&e._variant===!0}function d(e){return e.issues?s({issues:e.issues.map(e=>({message:e.message,path:e.path?.map(e=>typeof e==`object`&&`key`in e?e.key:e)}))}):o(e.value)}function f(e,t,n){let r=e[`~standard`].validate(t);if(a(r))throw Error(`Async validation not supported. Schema for "${n}" returned a Promise. Use a synchronous schema or handle async validation separately.`);return d(r)}function p(e){return t=>l(t)&&`_tag`in t&&t._tag===e}function m(e){let t=new Set(e);return e=>l(e)&&`_tag`in e&&typeof e._tag==`string`&&t.has(e._tag)}function h(e,t,n,r){return n!==void 0&&r!==void 0?{kind:e,message:t,cause:n,validationIssues:r}:n===void 0?r===void 0?{kind:e,message:t}:{kind:e,message:t,validationIssues:r}:{kind:e,message:t,cause:n}}function g(e){return{to:e=>JSON.stringify(e),from:e=>{try{let t=JSON.parse(e);if(typeof t==`object`&&t&&`_tag`in t){let{_tag:e,...n}=t;return n}return t}catch{return null}}}}function _(e,t,n){let r=g(e),i={json:n=>{let i=f(t,{...n,_tag:e},e);if(i._tag===`Err`)return s(h(`ValidationError`,`Cannot encode invalid data: ${i.error.issues.map(e=>e.message).join(`, `)}`,void 0,i.error.issues));try{return o(r.to(i.value))}catch(e){return s(h(`EncodingError`,`JSON encoding failed: ${e instanceof Error?e.message:String(e)}`,e))}}};if(n)for(let[r,a]of Object.entries(n))i[r]=n=>{let i=f(t,{...n,_tag:e},e);if(i._tag===`Err`)return s(h(`ValidationError`,`Cannot encode invalid data: ${i.error.issues.map(e=>e.message).join(`, `)}`,void 0,i.error.issues));try{return o(a.to(i.value))}catch(e){return s(h(`EncodingError`,`Encoding with codec '${r}' failed: ${e instanceof Error?e.message:String(e)}`,e))}};return i}function v(e,t,n){let r=g(e),i={json:n=>{let i=r.from(n);if(i===null)return s(h(`DecodingError`,`Invalid JSON format`));let a=f(t,{...i,_tag:e},e);return a._tag===`Err`?s(h(`ValidationError`,`Decoded data failed schema validation`,void 0,a.error.issues)):o({...a.value,_tag:e})}};if(n)for(let[r,a]of Object.entries(n))i[r]=n=>{let i;try{i=a.from(n)}catch(e){return s(h(`DecodingError`,`Decoding with codec '${r}' threw an error`,e))}if(i===null)return s(h(`DecodingError`,`Codec '${r}' failed to decode input`));let c=f(t,{...i,_tag:e},e);return c._tag===`Err`?s(h(`ValidationError`,`Decoded data failed schema validation`,void 0,c.error.issues)):o({...c.value,_tag:e})};return i}function y(e,n,i){let a=p(e),c=_(e,n,i),l=v(e,n,i),u=r(e),d=t(e),m=t=>{let r=f(n,{...t,_tag:e},e);return r._tag===`Err`?s(r.error):o({...r.value,_tag:e})};return m._variant=!0,m._tag=e,m.schema=n,i&&(m.codecs=i),m.is=a,m.to=c,m.from=l,m.equals=u,m.hash=d,m}function b(e,t){let r=Object.keys(t),a={};for(let[e,n]of Object.entries(t))u(n)?n._tag===e?a[e]=n:n.codecs?a[e]=y(e,n.schema,n.codecs):a[e]=y(e,n.schema):a[e]=y(e,n);return{_name:e,is:m(r),equals:i(r),hash:n(r),...a}}var x=e({match:()=>w,union:()=>S,variant:()=>C});const S=b,C=y,w=c;export{x as t};
2
- //# sourceMappingURL=adt-DajUZvJe.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"adt-DajUZvJe.mjs","names":["match","variant","union","variant","unionImpl","variantImpl","matchImpl"],"sources":["../src/adt/adt.match.ts","../src/shared/is-plain-object.ts","../src/adt/adt.utils.ts","../src/adt/adt.codec.ts","../src/adt/adt.variant.ts","../src/adt/adt.union.ts","../src/adt/adt.ts"],"sourcesContent":["/**\n * Handler functions for each variant in a discriminated union.\n * Each key maps to a function that receives the variant value and returns TResult.\n *\n * @template T - The discriminated union type (must have readonly _tag)\n * @template TResult - The return type of all handlers\n */\ntype AdtMatchHandlers<T extends { readonly _tag: string }, TResult> = {\n [K in T[\"_tag\"]]: (value: Extract<T, { readonly _tag: K }>) => TResult\n}\n\n/**\n * Exhaustive pattern matching for discriminated unions.\n *\n * TypeScript will error if any variant is missing from handlers,\n * ensuring exhaustive handling of all cases.\n *\n * @template T - The discriminated union type (must have readonly _tag)\n * @template TResult - The return type of all handlers\n * @template Handlers - The handler object type (inferred)\n * @param value - A discriminated union value with _tag\n * @param handlers - An object with a handler function for each variant\n * @returns The result of calling the matching handler\n *\n * @see {@link union} for creating discriminated unions\n * @see {@link variant} for creating individual variant types\n *\n * @example\n * ```ts\n * const Shape = union('Shape', { Circle, Square })\n * type Shape = AdtInfer<typeof Shape>\n *\n * function describeShape(shape: Shape): string {\n * return match(shape, {\n * Circle: (c) => `Circle with radius ${c.radius}`,\n * Square: (s) => `Square with size ${s.size}`,\n * })\n * }\n * ```\n */\nexport function match<\n T extends { readonly _tag: string },\n TResult,\n Handlers extends AdtMatchHandlers<T, TResult> = AdtMatchHandlers<T, TResult>,\n>(value: T, handlers: Handlers): TResult {\n const tag = value._tag as keyof Handlers\n const handler = handlers[tag]\n // oxlint-disable-next-line no-explicit-any, no-unsafe-argument, no-unsafe-type-assertion -- Required for variant dispatch\n return handler(value as any)\n}\n","/**\n * Check if a value is a plain object.\n * A plain object is an object created with `{}`, `Object.create(null)`, or `new Object()`.\n * Arrays, functions, dates, maps, etc. are not considered plain objects.\n */\nexport function isPlainObject(value: unknown): value is Record<PropertyKey, unknown> {\n if (value === null || typeof value !== \"object\") {\n return false\n }\n\n return Object.getPrototypeOf(value) === null || Object.getPrototypeOf(value) === Object.prototype\n}\n","import { ok, err } from \"../result/result\"\nimport type { Result } from \"../result/result.types\"\nimport { isPlainObject } from \"../shared/is-plain-object\"\nimport { isPromise } from \"../shared/is-promise\"\nimport type { AdtVariant, AdtValidationError } from \"./adt.types\"\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\"\n\n/**\n * Check if a value is an AdtVariant created by variant().\n * AdtVariants are callable functions with static properties.\n */\nexport function isVariant(value: unknown): value is AdtVariant {\n return typeof value === \"function\" && \"_variant\" in value && value[\"_variant\"] === true\n}\n\n/**\n * Wrap Standard Schema validation result into our Result type.\n */\nfunction wrapValidationResult<T>(result: StandardSchemaV1.Result<T>): Result<T, AdtValidationError> {\n if (result.issues) {\n return err({\n issues: result.issues.map((issue) => ({\n message: issue.message,\n path: issue.path?.map((segment) => (typeof segment === \"object\" && \"key\" in segment ? segment.key : segment)),\n })),\n })\n }\n return ok(result.value)\n}\n\n/**\n * Validate data using a Standard Schema, enforcing sync-only validation.\n * Throws if the schema returns a Promise.\n */\nexport function validateSync<T>(\n schema: StandardSchemaV1<unknown, T>,\n data: unknown,\n _tag: string,\n): Result<T, AdtValidationError> {\n const result = schema[\"~standard\"].validate(data)\n\n if (isPromise(result)) {\n throw new Error(\n `Async validation not supported. Schema for \"${_tag}\" returned a Promise. ` +\n `Use a synchronous schema or handle async validation separately.`,\n )\n }\n\n return wrapValidationResult(result)\n}\n\n/**\n * Create a type guard function for a specific _tag.\n */\nexport function createIsGuard<Tag extends string, T>(\n _tag: Tag,\n): (value: unknown) => value is T & { readonly _tag: Tag } {\n return (value: unknown): value is T & { readonly _tag: Tag } => {\n return isPlainObject(value) && \"_tag\" in value && value[\"_tag\"] === _tag\n }\n}\n\n/**\n * Create a type guard function for multiple _tags (AdtUnion root guard).\n */\nexport function createIsAnyGuard<T>(_tags: readonly string[]): (value: unknown) => value is T {\n const _tagSet = new Set(_tags)\n return (value: unknown): value is T => {\n return isPlainObject(value) && \"_tag\" in value && typeof value[\"_tag\"] === \"string\" && _tagSet.has(value[\"_tag\"])\n }\n}\n","import { ok, err } from \"../result/result\"\nimport type { Result } from \"../result/result.types\"\nimport type { Discriminator } from \"../shared/discriminator.types\"\nimport type {\n AdtCodecConstraint,\n AdtCodecDef,\n AdtCodecError,\n AdtInferInput,\n AdtInferOutput,\n AdtValidationError,\n ToMethods,\n FromMethods,\n} from \"./adt.types\"\nimport { validateSync } from \"./adt.utils\"\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\"\n\n/**\n * Create a AdtCodecError with consistent structure.\n */\nfunction createCodecError(\n kind: AdtCodecError[\"kind\"],\n message: string,\n cause?: unknown,\n validationIssues?: AdtValidationError[\"issues\"],\n): AdtCodecError {\n if (cause !== undefined && validationIssues !== undefined) {\n return { kind, message, cause, validationIssues }\n }\n if (cause !== undefined) {\n return { kind, message, cause }\n }\n if (validationIssues !== undefined) {\n return { kind, message, validationIssues }\n }\n return { kind, message }\n}\n\n/**\n * Built-in JSON codec that works with any schema.\n * Encodes to JSON string and decodes with JSON.parse.\n */\nfunction createJsonCodec<Tag extends string, S extends StandardSchemaV1>(\n _tag: Tag,\n): AdtCodecDef<AdtInferOutput<S> & Discriminator<Tag>, string, AdtInferInput<S>> {\n return {\n to: (value) => {\n // JSON.stringify can throw for circular references, BigInt, etc.\n // We let it throw and catch it in the wrapper\n return JSON.stringify(value)\n },\n /* oxlint-disable no-unsafe-assignment, no-unsafe-type-assertion, no-unsafe-return -- Required for JSON parsing which returns unknown types */\n from: (input: string) => {\n try {\n const parsed = JSON.parse(input)\n // Return parsed object without _tag - it will be added during validation\n if (typeof parsed === \"object\" && parsed !== null && \"_tag\" in parsed) {\n const { _tag: _, ...rest } = parsed\n return rest as AdtInferInput<S>\n }\n return parsed\n } catch {\n return null\n }\n },\n /* oxlint-enable no-unsafe-assignment, no-unsafe-type-assertion, no-unsafe-return */\n }\n}\n\n/**\n * Create the \"to\" methods object with JSON codec and custom codecs.\n * All methods return Result<T, AdtCodecError> for consistent error handling.\n */\nexport function createToMethods<\n Tag extends string,\n S extends StandardSchemaV1,\n Codecs extends AdtCodecConstraint<Tag, S> | undefined = undefined,\n>(_tag: Tag, schema: S, customCodecs?: Codecs): ToMethods<S, Codecs> {\n type Output = AdtInferOutput<S> & Discriminator<Tag>\n\n const jsonCodec = createJsonCodec<Tag, S>(_tag)\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const to: Record<string, (value: AdtInferInput<S>) => Result<any, AdtCodecError>> = {\n json: (value: AdtInferInput<S>): Result<string, AdtCodecError> => {\n // First, create a validated variant to ensure the encoded payload is well-typed.\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for spreading generic input into object\n const taggedInput = { ...(value as object), _tag }\n const result = validateSync(schema, taggedInput, _tag)\n\n if (result._tag === \"Err\") {\n return err(\n createCodecError(\n \"ValidationError\",\n `Cannot encode invalid data: ${result.error.issues.map((i) => i.message).join(\", \")}`,\n undefined,\n result.error.issues,\n ),\n )\n }\n\n try {\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for validated value cast\n return ok(jsonCodec.to(result.value as Output))\n } catch (e) {\n return err(\n createCodecError(\"EncodingError\", `JSON encoding failed: ${e instanceof Error ? e.message : String(e)}`, e),\n )\n }\n },\n }\n\n // Add custom codecs\n if (customCodecs) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [name, codec] of Object.entries(customCodecs) as Array<[string, AdtCodecDef<Output, any, any>]>) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n to[name] = (value: AdtInferInput<S>): Result<any, AdtCodecError> => {\n // Validate input first\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for spreading generic input\n const taggedInput = { ...(value as object), _tag }\n const result = validateSync(schema, taggedInput, _tag)\n\n if (result._tag === \"Err\") {\n return err(\n createCodecError(\n \"ValidationError\",\n `Cannot encode invalid data: ${result.error.issues.map((i) => i.message).join(\", \")}`,\n undefined,\n result.error.issues,\n ),\n )\n }\n\n try {\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for validated value cast\n return ok(codec.to(result.value as Output))\n } catch (e) {\n return err(\n createCodecError(\n \"EncodingError\",\n `Encoding with codec '${name}' failed: ${e instanceof Error ? e.message : String(e)}`,\n e,\n ),\n )\n }\n }\n }\n }\n\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for generic return type\n return to as ToMethods<S, Codecs>\n}\n\n/**\n * Create the \"from\" methods object with JSON codec and custom codecs.\n * All methods return Result<T, AdtCodecError> for consistent error handling.\n */\nexport function createFromMethods<\n Tag extends string,\n S extends StandardSchemaV1,\n Codecs extends AdtCodecConstraint<Tag, S> | undefined = undefined,\n>(_tag: Tag, schema: S, customCodecs?: Codecs): FromMethods<Tag, S, Codecs> {\n type Output = AdtInferOutput<S> & Discriminator<Tag>\n\n const jsonCodec = createJsonCodec<Tag, S>(_tag)\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const from: Record<string, (input: any) => Result<Output, AdtCodecError>> = {\n json: (input: string): Result<Output, AdtCodecError> => {\n // Decode\n const decoded = jsonCodec.from(input)\n if (decoded === null) {\n return err(createCodecError(\"DecodingError\", \"Invalid JSON format\"))\n }\n\n // Validate through schema\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for spreading decoded value\n const taggedInput = { ...(decoded as object), _tag }\n const result = validateSync(schema, taggedInput, _tag)\n\n if (result._tag === \"Err\") {\n return err(\n createCodecError(\"ValidationError\", \"Decoded data failed schema validation\", undefined, result.error.issues),\n )\n }\n\n // Ensure _tag in output\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for output construction\n const output = { ...(result.value as object), _tag } as Output\n return ok(output)\n },\n }\n\n // Add custom codecs\n if (customCodecs) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n for (const [name, codec] of Object.entries(customCodecs) as Array<[string, AdtCodecDef<Output, any, any>]>) {\n from[name] = (input: unknown): Result<Output, AdtCodecError> => {\n // Decode\n let decoded: unknown\n try {\n decoded = codec.from(input)\n } catch (e) {\n return err(createCodecError(\"DecodingError\", `Decoding with codec '${name}' threw an error`, e))\n }\n\n if (decoded === null) {\n return err(createCodecError(\"DecodingError\", `Codec '${name}' failed to decode input`))\n }\n\n // Validate through schema\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for spreading decoded value\n const taggedInput = { ...(decoded as object), _tag }\n const result = validateSync(schema, taggedInput, _tag)\n\n if (result._tag === \"Err\") {\n return err(\n createCodecError(\n \"ValidationError\",\n \"Decoded data failed schema validation\",\n undefined,\n result.error.issues,\n ),\n )\n }\n\n // Ensure _tag in output\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for output construction\n const output = { ...(result.value as object), _tag } as Output\n return ok(output)\n }\n }\n }\n\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for generic return type\n return from as FromMethods<Tag, S, Codecs>\n}\n","import { createEqualsMethod, createHashMethod } from \"../equality/equality\"\nimport { ok, err } from \"../result/result\"\nimport type { Result } from \"../result/result.types\"\nimport type { Discriminator } from \"../shared/discriminator.types\"\nimport { createToMethods, createFromMethods } from \"./adt.codec\"\nimport type { AdtCodecConstraint, AdtInferInput, AdtInferOutput, AdtVariant, AdtValidationError } from \"./adt.types\"\nimport { createIsGuard, validateSync } from \"./adt.utils\"\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\"\n\n/**\n * Create a standalone tagged variant from a Standard Schema with optional codecs.\n *\n * Variants can be used independently or composed into an AdtUnion via union().\n * All defaults should be defined at the schema level (e.g., Zod's .default()).\n *\n * @template Tag - The string literal type for the _tag discriminator\n * @template S - The Standard Schema type for validation\n * @template Codecs - Optional codec definitions for custom serialization formats\n * @param _tag - The _tag discriminator value\n * @param schema - A Standard Schema compliant validator\n * @param codecs - Optional codec definitions for custom serialization formats\n * @returns A callable AdtVariant with is(), to, and from methods\n *\n * @see {@link union} for composing variants into discriminated unions\n * @see {@link tagged} for unvalidated tagged value constructors\n *\n * @example\n * ```ts\n * const CircleSchema = z.object({\n * radius: z.number().positive(),\n * color: z.string().default('blue')\n * })\n *\n * // Basic variant with JSON codec (always included)\n * const Circle = variant('Circle', CircleSchema)\n *\n * const result = Circle({ radius: 10 })\n * // { _tag: \"Ok\", value: { _tag: \"Circle\", radius: 10, color: \"blue\" } }\n *\n * Circle.is(someValue) // type guard\n *\n * const json = Circle.to.json({ radius: 10 }) // JSON string\n * const result2 = Circle.from.json(json) // Result<Circle, AdtCodecError>\n *\n * // Variant with custom codec\n * const Circle2 = variant('Circle', CircleSchema, {\n * graphic: {\n * to: (circle) => `(${circle.radius})`,\n * from: (input: string) => {\n * const match = input.match(/^\\((\\d+)\\)$/)\n * return match ? { radius: parseInt(match[1]!) } : null\n * }\n * }\n * })\n *\n * const graphic = Circle2.to.graphic({ radius: 10 }) // \"(10)\"\n * const result3 = Circle2.from.graphic(\"(10)\") // Result<Circle, AdtCodecError>\n * ```\n */\n// Overload: with codecs\nexport function variant<Tag extends string, S extends StandardSchemaV1, Codecs extends AdtCodecConstraint<Tag, S>>(\n _tag: Tag,\n schema: S,\n codecs: Codecs,\n): AdtVariant<Tag, S, Codecs>\n\n// Overload: without codecs\nexport function variant<Tag extends string, S extends StandardSchemaV1>(_tag: Tag, schema: S): AdtVariant<Tag, S>\n\n// Implementation\nexport function variant<\n Tag extends string,\n S extends StandardSchemaV1,\n Codecs extends AdtCodecConstraint<Tag, S> | undefined,\n>(_tag: Tag, schema: S, codecs?: Codecs): AdtVariant<Tag, S, Codecs> {\n type Output = AdtInferOutput<S> & Discriminator<Tag>\n\n const isGuard = createIsGuard<Tag, Output>(_tag)\n const to = createToMethods(_tag, schema, codecs)\n const from = createFromMethods(_tag, schema, codecs)\n const equals = createEqualsMethod<Tag, AdtInferOutput<S>>(_tag)\n const hash = createHashMethod<Tag, AdtInferOutput<S>>(_tag)\n\n // Constructor function\n const constructor = (input: AdtInferInput<S>): Result<Output, AdtValidationError> => {\n // Add _tag to the input before validation\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for spreading generic input\n const taggedInput = { ...(input as object), _tag }\n\n // Validate using the schema\n const result = validateSync(schema, taggedInput, _tag)\n\n if (result._tag === \"Err\") {\n return err(result.error)\n }\n\n // Ensure _tag is in the output (schema might strip unknown keys)\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for output construction\n const output = { ...(result.value as object), _tag } as Output\n return ok(output)\n }\n\n // Attach static properties to constructor function\n constructor._variant = true as const\n constructor._tag = _tag\n constructor.schema = schema\n if (codecs) {\n // oxlint-disable-next-line no-unsafe-type-assertion -- Conditional assignment of codecs\n ;(constructor as { codecs?: Codecs }).codecs = codecs\n }\n constructor.is = isGuard\n constructor.to = to\n constructor.from = from\n constructor.equals = equals\n constructor.hash = hash\n\n return constructor as AdtVariant<Tag, S, Codecs>\n}\n","import { createADTEqualsMethod, createADTHashMethod } from \"../equality/equality\"\nimport type { AdtUnion, AdtVariantDef, AdtVariant } from \"./adt.types\"\nimport { createIsAnyGuard, isVariant } from \"./adt.utils\"\nimport { variant } from \"./adt.variant\"\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\"\n\n/**\n * Compose records or schemas into a discriminated union (AdtUnion).\n *\n * Accepts either:\n * - Pre-built AdtVariants from variant() (codecs are preserved)\n * - Raw Standard Schema validators (will be wrapped internally)\n *\n * When using pre-built records, the object key overrides the original _tag.\n *\n * @template R - Record of variant names to AdtVariants or StandardSchema validators\n * @param name - The name of this AdtUnion (for identification)\n * @param records - An object mapping _tag names to AdtVariants or schemas\n * @returns An AdtUnion object with accessors for each variant\n *\n * @see {@link variant} for creating individual variant types\n * @see {@link match} for exhaustive pattern matching on AdtUnion values\n *\n * @example\n * ```ts\n * // From pre-built variants\n * const Circle = variant('Circle', CircleSchema)\n * const Square = variant('Square', SquareSchema)\n * const Shape = union('Shape', { Circle, Square })\n *\n * // From raw schemas (JSON codec is automatically included)\n * const Shape = union('Shape', {\n * Circle: CircleSchema,\n * Square: SquareSchema\n * })\n *\n * // JSON codec works on all variants\n * Shape.Circle.to.json({ radius: 10 })\n * Shape.Circle.from.json(jsonString)\n *\n * // Mixed\n * const Shape = union('Shape', {\n * Circle, // Pre-built variant\n * Square: SquareSchema // Raw schema\n * })\n *\n * // Usage\n * Shape.Circle({ radius: 10 })\n * Shape.is(someValue) // type guard for any variant\n * Shape.Circle.is(someValue) // type guard for Circle\n * ```\n */\nexport function union<R extends Record<string, AdtVariantDef>>(name: string, records: R): AdtUnion<R> {\n const tags = Object.keys(records)\n const variants: Record<string, AdtVariant> = {}\n\n for (const [_tag, def] of Object.entries(records)) {\n if (isVariant(def)) {\n // Pre-built AdtVariant - key overrides original _tag\n if (def._tag === _tag) {\n // _tag matches key, use as-is (preserves codecs)\n variants[_tag] = def\n // oxlint-disable-next-line strict-boolean-expressions -- codecs can be undefined\n } else if (def.codecs) {\n // _tag differs from key - create new variant with key as _tag\n // Preserve codecs\n variants[_tag] = variant(_tag, def.schema, def.codecs)\n } else {\n // _tag differs from key and no codecs\n variants[_tag] = variant(_tag, def.schema)\n }\n } else {\n // Raw schema - wrap in variant\n // Note: Even without custom codecs, this still gets JSON codec!\n // oxlint-disable-next-line no-unsafe-type-assertion -- def is a StandardSchemaV1 in this branch\n variants[_tag] = variant(_tag, def as StandardSchemaV1)\n }\n }\n\n // Create the root type guard for any variant\n const isAnyVariant = createIsAnyGuard(tags)\n const equals = createADTEqualsMethod(tags)\n const hash = createADTHashMethod(tags)\n\n // oxlint-disable-next-line no-unsafe-type-assertion -- Required for generic AdtUnion return type\n return {\n _name: name,\n is: isAnyVariant,\n equals,\n hash,\n ...variants,\n } as AdtUnion<R>\n}\n","/**\n * Tagged union builders and match helpers.\n *\n * **Mental model**\n * - `Adt` helps build discriminated unions with runtime validation.\n * - Use `union`, `variant`, and `match` to model algebraic data types.\n *\n * **Common tasks**\n * - Define variants with `Adt.variant`.\n * - Combine variants with `Adt.union`.\n * - Pattern-match with `Adt.match`.\n *\n * **Gotchas**\n * - `Adt` codec/type helpers are mostly type-level.\n * - Prefer namespace imports from `@nicolastoulemont/std`.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Adt } from \"@nicolastoulemont/std\"\n *\n * const Shape = Adt.union(\"Shape\", {} as never)\n * // => union helper with tagged constructors\n * ```\n *\n * @module\n */\nimport { match as matchImpl } from \"./adt.match\"\nimport type {\n AdtInfer as AdtInferType,\n AdtVariantNames as AdtVariantNamesType,\n AdtVariantOf as AdtVariantOfType,\n} from \"./adt.types\"\nimport { union as unionImpl } from \"./adt.union\"\nimport { variant as variantImpl } from \"./adt.variant\"\n\n/**\n * Re-exported ADT inferred union helper.\n *\n * @example\n * ```ts\n * import { Adt } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Adt\n * ```\n *\n * @category Type-level\n */\nexport type AdtInfer<T> = AdtInferType<T>\n\n/**\n * Re-exported union variant name helper.\n *\n * @example\n * ```ts\n * import { Adt } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Adt\n * ```\n *\n * @category Type-level\n */\nexport type AdtVariantNames<T> = AdtVariantNamesType<T>\n\n/**\n * Re-exported helper to extract a specific variant from an ADT.\n *\n * @example\n * ```ts\n * import { Adt } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Adt\n * ```\n *\n * @category Type-level\n */\nexport type AdtVariantOf<T, K extends string> = AdtVariantOfType<T, K>\n\n/**\n * Build an ADT union from named variants.\n *\n * @example\n * ```ts\n * import { Adt } from \"@nicolastoulemont/std\"\n *\n * const Shape = Adt.union(\"Shape\", {} as never)\n * // => union helper with tagged constructors\n * ```\n *\n * @category Constructors\n */\nexport const union = unionImpl\n\n/**\n * Define one ADT variant with schema-backed validation.\n *\n * @example\n * ```ts\n * import { Adt } from \"@nicolastoulemont/std\"\n *\n * const Circle = Adt.variant(\"Circle\", {} as never)\n * // => callable variant constructor\n * ```\n *\n * @category Constructors\n */\nexport const variant = variantImpl\n\n/**\n * Match over ADT variants by discriminator tag.\n *\n * @example\n * ```ts\n * import { Adt } from \"@nicolastoulemont/std\"\n *\n * const label = Adt.match({ _tag: \"Circle\", radius: 2 } as const, {\n * Circle: (circle) => `r=${circle.radius}` ,\n * })\n * // => \"r=2\"\n * ```\n *\n * @category Pattern Matching\n */\nexport const match = matchImpl\n"],"mappings":"yLAwCA,SAAgBA,EAId,EAAU,EAA6B,CAEvC,IAAM,EAAU,EADJ,EAAM,MAGlB,OAAO,EAAQ,EAAa,CC3C9B,SAAgB,EAAc,EAAuD,CAKnF,OAJsB,OAAO,GAAU,WAAnC,EACK,GAGF,OAAO,eAAe,EAAM,GAAK,MAAQ,OAAO,eAAe,EAAM,GAAK,OAAO,UCC1F,SAAgB,EAAU,EAAqC,CAC7D,OAAO,OAAO,GAAU,YAAc,aAAc,GAAS,EAAM,WAAgB,GAMrF,SAAS,EAAwB,EAAmE,CASlG,OARI,EAAO,OACF,EAAI,CACT,OAAQ,EAAO,OAAO,IAAK,IAAW,CACpC,QAAS,EAAM,QACf,KAAM,EAAM,MAAM,IAAK,GAAa,OAAO,GAAY,UAAY,QAAS,EAAU,EAAQ,IAAM,EAAS,CAC9G,EAAE,CACJ,CAAC,CAEG,EAAG,EAAO,MAAM,CAOzB,SAAgB,EACd,EACA,EACA,EAC+B,CAC/B,IAAM,EAAS,EAAO,aAAa,SAAS,EAAK,CAEjD,GAAI,EAAU,EAAO,CACnB,MAAU,MACR,+CAA+C,EAAK,uFAErD,CAGH,OAAO,EAAqB,EAAO,CAMrC,SAAgB,EACd,EACyD,CACzD,MAAQ,IACC,EAAc,EAAM,EAAI,SAAU,GAAS,EAAM,OAAY,EAOxE,SAAgB,EAAoB,EAA0D,CAC5F,IAAM,EAAU,IAAI,IAAI,EAAM,CAC9B,MAAQ,IACC,EAAc,EAAM,EAAI,SAAU,GAAS,OAAO,EAAM,MAAY,UAAY,EAAQ,IAAI,EAAM,KAAQ,CCjDrH,SAAS,EACP,EACA,EACA,EACA,EACe,CAUf,OATI,IAAU,IAAA,IAAa,IAAqB,IAAA,GACvC,CAAE,OAAM,UAAS,QAAO,mBAAkB,CAE/C,IAAU,IAAA,GAGV,IAAqB,IAAA,GAGlB,CAAE,OAAM,UAAS,CAFf,CAAE,OAAM,UAAS,mBAAkB,CAHnC,CAAE,OAAM,UAAS,QAAO,CAYnC,SAAS,EACP,EAC+E,CAC/E,MAAO,CACL,GAAK,GAGI,KAAK,UAAU,EAAM,CAG9B,KAAO,GAAkB,CACvB,GAAI,CACF,IAAM,EAAS,KAAK,MAAM,EAAM,CAEhC,GAAI,OAAO,GAAW,UAAY,GAAmB,SAAU,EAAQ,CACrE,GAAM,CAAE,KAAM,EAAG,GAAG,GAAS,EAC7B,OAAO,EAET,OAAO,OACD,CACN,OAAO,OAIZ,CAOH,SAAgB,EAId,EAAW,EAAW,EAA6C,CAGnE,IAAM,EAAY,EAAwB,EAAK,CAGzC,EAA8E,CAClF,KAAO,GAA2D,CAIhE,IAAM,EAAS,EAAa,EADR,CAAE,GAAI,EAAkB,OAAM,CACD,EAAK,CAEtD,GAAI,EAAO,OAAS,MAClB,OAAO,EACL,EACE,kBACA,+BAA+B,EAAO,MAAM,OAAO,IAAK,GAAM,EAAE,QAAQ,CAAC,KAAK,KAAK,GACnF,IAAA,GACA,EAAO,MAAM,OACd,CACF,CAGH,GAAI,CAEF,OAAO,EAAG,EAAU,GAAG,EAAO,MAAgB,CAAC,OACxC,EAAG,CACV,OAAO,EACL,EAAiB,gBAAiB,yBAAyB,aAAa,MAAQ,EAAE,QAAU,OAAO,EAAE,GAAI,EAAE,CAC5G,GAGN,CAGD,GAAI,EAEF,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,EAAa,CAEtD,EAAG,GAAS,GAAwD,CAIlE,IAAM,EAAS,EAAa,EADR,CAAE,GAAI,EAAkB,OAAM,CACD,EAAK,CAEtD,GAAI,EAAO,OAAS,MAClB,OAAO,EACL,EACE,kBACA,+BAA+B,EAAO,MAAM,OAAO,IAAK,GAAM,EAAE,QAAQ,CAAC,KAAK,KAAK,GACnF,IAAA,GACA,EAAO,MAAM,OACd,CACF,CAGH,GAAI,CAEF,OAAO,EAAG,EAAM,GAAG,EAAO,MAAgB,CAAC,OACpC,EAAG,CACV,OAAO,EACL,EACE,gBACA,wBAAwB,EAAK,YAAY,aAAa,MAAQ,EAAE,QAAU,OAAO,EAAE,GACnF,EACD,CACF,GAOT,OAAO,EAOT,SAAgB,EAId,EAAW,EAAW,EAAoD,CAG1E,IAAM,EAAY,EAAwB,EAAK,CAGzC,EAAsE,CAC1E,KAAO,GAAiD,CAEtD,IAAM,EAAU,EAAU,KAAK,EAAM,CACrC,GAAI,IAAY,KACd,OAAO,EAAI,EAAiB,gBAAiB,sBAAsB,CAAC,CAMtE,IAAM,EAAS,EAAa,EADR,CAAE,GAAI,EAAoB,OAAM,CACH,EAAK,CAWtD,OATI,EAAO,OAAS,MACX,EACL,EAAiB,kBAAmB,wCAAyC,IAAA,GAAW,EAAO,MAAM,OAAO,CAC7G,CAMI,EADQ,CAAE,GAAI,EAAO,MAAkB,OAAM,CACnC,EAEpB,CAGD,GAAI,EAEF,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,EAAa,CACtD,EAAK,GAAS,GAAkD,CAE9D,IAAI,EACJ,GAAI,CACF,EAAU,EAAM,KAAK,EAAM,OACpB,EAAG,CACV,OAAO,EAAI,EAAiB,gBAAiB,wBAAwB,EAAK,kBAAmB,EAAE,CAAC,CAGlG,GAAI,IAAY,KACd,OAAO,EAAI,EAAiB,gBAAiB,UAAU,EAAK,0BAA0B,CAAC,CAMzF,IAAM,EAAS,EAAa,EADR,CAAE,GAAI,EAAoB,OAAM,CACH,EAAK,CAgBtD,OAdI,EAAO,OAAS,MACX,EACL,EACE,kBACA,wCACA,IAAA,GACA,EAAO,MAAM,OACd,CACF,CAMI,EADQ,CAAE,GAAI,EAAO,MAAkB,OAAM,CACnC,EAMvB,OAAO,ECrKT,SAAgBC,EAId,EAAW,EAAW,EAA6C,CAGnE,IAAM,EAAU,EAA2B,EAAK,CAC1C,EAAK,EAAgB,EAAM,EAAQ,EAAO,CAC1C,EAAO,EAAkB,EAAM,EAAQ,EAAO,CAC9C,EAAS,EAA2C,EAAK,CACzD,EAAO,EAAyC,EAAK,CAGrD,EAAe,GAAgE,CAMnF,IAAM,EAAS,EAAa,EAHR,CAAE,GAAI,EAAkB,OAAM,CAGD,EAAK,CAStD,OAPI,EAAO,OAAS,MACX,EAAI,EAAO,MAAM,CAMnB,EADQ,CAAE,GAAI,EAAO,MAAkB,OAAM,CACnC,EAiBnB,MAbA,GAAY,SAAW,GACvB,EAAY,KAAO,EACnB,EAAY,OAAS,EACjB,IAEA,EAAoC,OAAS,GAEjD,EAAY,GAAK,EACjB,EAAY,GAAK,EACjB,EAAY,KAAO,EACnB,EAAY,OAAS,EACrB,EAAY,KAAO,EAEZ,EChET,SAAgBC,EAA+C,EAAc,EAAyB,CACpG,IAAM,EAAO,OAAO,KAAK,EAAQ,CAC3B,EAAuC,EAAE,CAE/C,IAAK,GAAM,CAAC,EAAM,KAAQ,OAAO,QAAQ,EAAQ,CAC3C,EAAU,EAAI,CAEZ,EAAI,OAAS,EAEf,EAAS,GAAQ,EAER,EAAI,OAGb,EAAS,GAAQC,EAAQ,EAAM,EAAI,OAAQ,EAAI,OAAO,CAGtD,EAAS,GAAQA,EAAQ,EAAM,EAAI,OAAO,CAM5C,EAAS,GAAQA,EAAQ,EAAM,EAAwB,CAU3D,MAAO,CACL,MAAO,EACP,GAPmB,EAAiB,EAAK,CAQzC,OAPa,EAAsB,EAAK,CAQxC,KAPW,EAAoB,EAAK,CAQpC,GAAG,EACJ,kDCCH,MAAa,EAAQC,EAeR,EAAUC,EAiBV,EAAQC"}
@@ -1,2 +0,0 @@
1
- import{t as e}from"./chunk-C934ptG5.mjs";import{r as t,t as n}from"./result-BEzV0DYC.mjs";var r=e({is:()=>o,make:()=>i,refine:()=>s,unsafeMake:()=>a});const i=e=>e,a=e=>e,o=e=>t=>e(t),s=(e,r)=>i=>e(i)?t(i):n({_tag:`BrandError`,value:i,message:typeof r==`function`?r(i):r??`Brand validation failed`});export{r as t};
2
- //# sourceMappingURL=brand-Bia3Vj6l.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"brand-Bia3Vj6l.mjs","names":["Result.err","Result.ok"],"sources":["../src/brand/brand.ts"],"sourcesContent":["/**\n * Nominal branding utilities for lightweight domain types.\n *\n * **Mental model**\n * - Brands let you distinguish semantically different values with the same runtime shape.\n * - `Brand.refine` validates and returns `Result`, while `Brand.make` is unchecked.\n *\n * **Common tasks**\n * - Create branded values with `Brand.make`.\n * - Add runtime validation with `Brand.refine`.\n * - Build guards with `Brand.is`.\n *\n * **Gotchas**\n * - Branding is a type-level operation and does not change runtime representation.\n * - `unsafeMake` should be reserved for trusted sources.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Brand } from \"@nicolastoulemont/std\"\n *\n * type UserId = Brand.Branded<string, \"UserId\">\n * const raw = \"user_123\" as UserId\n * const userId = Brand.make<UserId>(raw)\n * // => brand-preserving cast\n * ```\n *\n * @module\n */\nimport { Result } from \"../result\"\nimport type { Result as ResultType } from \"../result/result.types\"\nimport type { BrandError as BrandErrorType, Branded as BrandedType, Unbrand, Validator } from \"./brand.types\"\n\n/**\n * Re-exported nominal brand helper type.\n *\n * @example\n * ```ts\n * import { Brand } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Brand\n * ```\n *\n * @category Type-level\n */\nexport type Branded<T, K extends string> = BrandedType<T, K>\n\n/**\n * Re-exported brand validation error type.\n *\n * @example\n * ```ts\n * import { Brand } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Brand\n * ```\n *\n * @category Type-level\n */\nexport type BrandError<T> = BrandErrorType<T>\n\n/* oxlint-disable no-unsafe-type-assertion -- Branding is a deliberate nominal cast at the type level and requires explicit assertions. */\n\n/**\n * Create a branded value without validation.\n * This is a type-level cast with zero runtime cost.\n *\n * Use this when you trust the value source (e.g., from a database)\n * or when validation happens elsewhere.\n *\n * @template B - The branded type\n * @param value - The value to brand\n * @returns The value as a branded type\n *\n * @example\n * ```ts\n * import { Brand } from \"@nicolastoulemont/std\"\n *\n * type UserId = Brand.Branded<string, \"UserId\">\n * const raw = \"user_123\" as UserId\n * const userId = Brand.make<UserId>(raw)\n * // => brand-preserving cast\n * ```\n *\n * @category Utilities\n */\nexport const make = <B extends Branded<unknown, string>>(value: Unbrand<B>): B => {\n return value as B\n}\n\n/**\n * Alias for make() - explicitly indicates no validation occurs.\n * Prefer this when readability about the lack of validation is important.\n *\n * @template B - The branded type\n * @param value - The value to brand (unchecked)\n * @returns The value as a branded type\n *\n * @example\n * ```ts\n * import { Brand } from \"@nicolastoulemont/std\"\n *\n * type UserId = Brand.Branded<string, \"UserId\">\n * const raw = \"user_123\" as UserId\n * const userId = Brand.unsafeMake<UserId>(raw)\n * // => unchecked brand cast\n * ```\n *\n * @category Utilities\n */\nexport const unsafeMake = <B extends Branded<unknown, string>>(value: Unbrand<B>): B => {\n return value as B\n}\n\n/**\n * Create a type guard with validation for a branded type.\n * Returns a refinement predicate that narrows to the branded type.\n *\n * @template T - The base type\n * @template K - The brand key (string literal)\n * @param validator - A function that validates the base value\n * @returns A type guard that returns true if validation passes\n *\n * @example\n * ```ts\n * import { Brand } from \"@nicolastoulemont/std\"\n *\n * type UserId = Brand.Branded<string, \"UserId\">\n * const isUserId = Brand.is<string, \"UserId\">((value) => value.startsWith(\"user_\"))\n * const valid = isUserId(\"user_123\")\n * // => true\n * ```\n *\n * @category Utilities\n */\nexport const is = <T, K extends string>(validator: Validator<T>): ((value: T) => value is Branded<T, K>) => {\n return (value: T): value is Branded<T, K> => validator(value)\n}\n\n/**\n * Create a validated branded value wrapped in a Result.\n * Returns `Result.ok(brandedValue)` on success, `Result.err(BrandError)` on failure.\n *\n * The returned Result is yieldable in Fx.gen computations via `yield*`.\n *\n * @template B - The branded type\n * @param validator - A function that validates the base value\n * @param errorMessage - Optional custom error message (or function)\n * @returns A function that takes a value and returns a Result\n *\n * @example\n * ```ts\n * import { Brand } from \"@nicolastoulemont/std\"\n *\n * type UserId = Brand.Branded<string, \"UserId\">\n * const toUserId = Brand.refine<UserId>((value) => value.startsWith(\"user_\"), \"Invalid user id\")\n * const parsed = toUserId(\"user_123\" as UserId)\n * // => { _tag: \"Ok\", value: \"user_123\" }\n * ```\n *\n * @category Utilities\n */\nexport const refine = <B extends Branded<unknown, string>>(\n validator: Validator<Unbrand<B>>,\n errorMessage?: string | ((value: Unbrand<B>) => string),\n): ((value: Unbrand<B>) => ResultType<B, BrandError<Unbrand<B>>>) => {\n return (value: Unbrand<B>) => {\n if (!validator(value)) {\n const msg = typeof errorMessage === \"function\" ? errorMessage(value) : (errorMessage ?? \"Brand validation failed\")\n return Result.err({ _tag: \"BrandError\" as const, value, message: msg })\n }\n return Result.ok(value as B)\n }\n}\n\n/* oxlint-enable no-unsafe-type-assertion */\n"],"mappings":"uJAuFA,MAAa,EAA4C,GAChD,EAuBI,EAAkD,GACtD,EAwBI,EAA2B,GAC9B,GAAqC,EAAU,EAAM,CA0BlD,GACX,EACA,IAEQ,GACD,EAAU,EAAM,CAIdC,EAAU,EAAW,CAFnBD,EAAW,CAAE,KAAM,aAAuB,QAAO,QAD5C,OAAO,GAAiB,WAAa,EAAa,EAAM,CAAI,GAAgB,0BAClB,CAAC"}