effect 3.10.18 → 3.11.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 (448) hide show
  1. package/dist/cjs/Array.js +206 -0
  2. package/dist/cjs/Array.js.map +1 -1
  3. package/dist/cjs/BigDecimal.js +181 -24
  4. package/dist/cjs/BigDecimal.js.map +1 -1
  5. package/dist/cjs/BigInt.js +54 -0
  6. package/dist/cjs/BigInt.js.map +1 -1
  7. package/dist/cjs/Boolean.js +24 -0
  8. package/dist/cjs/Boolean.js.map +1 -1
  9. package/dist/cjs/Brand.js +4 -0
  10. package/dist/cjs/Brand.js.map +1 -1
  11. package/dist/cjs/Channel.js +44 -4
  12. package/dist/cjs/Channel.js.map +1 -1
  13. package/dist/cjs/Chunk.js +8 -0
  14. package/dist/cjs/Chunk.js.map +1 -1
  15. package/dist/cjs/Config.js +10 -1
  16. package/dist/cjs/Config.js.map +1 -1
  17. package/dist/cjs/Context.js +50 -1
  18. package/dist/cjs/Context.js.map +1 -1
  19. package/dist/cjs/Cron.js +81 -67
  20. package/dist/cjs/Cron.js.map +1 -1
  21. package/dist/cjs/Data.js +14 -0
  22. package/dist/cjs/Data.js.map +1 -1
  23. package/dist/cjs/DateTime.js +178 -664
  24. package/dist/cjs/DateTime.js.map +1 -1
  25. package/dist/cjs/Duration.js +2 -0
  26. package/dist/cjs/Duration.js.map +1 -1
  27. package/dist/cjs/Effect.js +296 -4
  28. package/dist/cjs/Effect.js.map +1 -1
  29. package/dist/cjs/Either.js +38 -2
  30. package/dist/cjs/Either.js.map +1 -1
  31. package/dist/cjs/FiberHandle.js +6 -0
  32. package/dist/cjs/FiberHandle.js.map +1 -1
  33. package/dist/cjs/FiberMap.js +6 -0
  34. package/dist/cjs/FiberMap.js.map +1 -1
  35. package/dist/cjs/FiberSet.js +6 -0
  36. package/dist/cjs/FiberSet.js.map +1 -1
  37. package/dist/cjs/Function.js +34 -0
  38. package/dist/cjs/Function.js.map +1 -1
  39. package/dist/cjs/GlobalValue.js +2 -0
  40. package/dist/cjs/GlobalValue.js.map +1 -1
  41. package/dist/cjs/HashMap.js.map +1 -1
  42. package/dist/cjs/Inspectable.js +8 -4
  43. package/dist/cjs/Inspectable.js.map +1 -1
  44. package/dist/cjs/Iterable.js +18 -0
  45. package/dist/cjs/Iterable.js.map +1 -1
  46. package/dist/cjs/JSONSchema.js.map +1 -1
  47. package/dist/cjs/List.js +4 -0
  48. package/dist/cjs/List.js.map +1 -1
  49. package/dist/cjs/Logger.js +26 -0
  50. package/dist/cjs/Logger.js.map +1 -1
  51. package/dist/cjs/Mailbox.js +2 -0
  52. package/dist/cjs/Mailbox.js.map +1 -1
  53. package/dist/cjs/ManagedRuntime.js +2 -0
  54. package/dist/cjs/ManagedRuntime.js.map +1 -1
  55. package/dist/cjs/Metric.js +10 -0
  56. package/dist/cjs/Metric.js.map +1 -1
  57. package/dist/cjs/Micro.js +1104 -1069
  58. package/dist/cjs/Micro.js.map +1 -1
  59. package/dist/cjs/Number.js +44 -0
  60. package/dist/cjs/Number.js.map +1 -1
  61. package/dist/cjs/Option.js +70 -0
  62. package/dist/cjs/Option.js.map +1 -1
  63. package/dist/cjs/Order.js +2 -0
  64. package/dist/cjs/Order.js.map +1 -1
  65. package/dist/cjs/Ordering.js +4 -0
  66. package/dist/cjs/Ordering.js.map +1 -1
  67. package/dist/cjs/Predicate.js +68 -0
  68. package/dist/cjs/Predicate.js.map +1 -1
  69. package/dist/cjs/Random.js +4 -0
  70. package/dist/cjs/Random.js.map +1 -1
  71. package/dist/cjs/RateLimiter.js +4 -0
  72. package/dist/cjs/RateLimiter.js.map +1 -1
  73. package/dist/cjs/RcMap.js +2 -0
  74. package/dist/cjs/RcMap.js.map +1 -1
  75. package/dist/cjs/RcRef.js +2 -0
  76. package/dist/cjs/RcRef.js.map +1 -1
  77. package/dist/cjs/Record.js +56 -0
  78. package/dist/cjs/Record.js.map +1 -1
  79. package/dist/cjs/Redacted.js +8 -0
  80. package/dist/cjs/Redacted.js.map +1 -1
  81. package/dist/cjs/RegExp.js +4 -0
  82. package/dist/cjs/RegExp.js.map +1 -1
  83. package/dist/cjs/Request.js +4 -0
  84. package/dist/cjs/Request.js.map +1 -1
  85. package/dist/cjs/RequestResolver.js +2 -0
  86. package/dist/cjs/RequestResolver.js.map +1 -1
  87. package/dist/cjs/Runtime.js +6 -0
  88. package/dist/cjs/Runtime.js.map +1 -1
  89. package/dist/cjs/STM.js.map +1 -1
  90. package/dist/cjs/Schema.js +91 -8
  91. package/dist/cjs/Schema.js.map +1 -1
  92. package/dist/cjs/Sink.js +9 -1
  93. package/dist/cjs/Sink.js.map +1 -1
  94. package/dist/cjs/Stream.js +179 -7
  95. package/dist/cjs/Stream.js.map +1 -1
  96. package/dist/cjs/String.js +62 -0
  97. package/dist/cjs/String.js.map +1 -1
  98. package/dist/cjs/Struct.js +12 -0
  99. package/dist/cjs/Struct.js.map +1 -1
  100. package/dist/cjs/Symbol.js +2 -0
  101. package/dist/cjs/Symbol.js.map +1 -1
  102. package/dist/cjs/Trie.js +56 -0
  103. package/dist/cjs/Trie.js.map +1 -1
  104. package/dist/cjs/Tuple.js +18 -0
  105. package/dist/cjs/Tuple.js.map +1 -1
  106. package/dist/cjs/Utils.js +7 -1
  107. package/dist/cjs/Utils.js.map +1 -1
  108. package/dist/cjs/internal/channel/channelExecutor.js +5 -9
  109. package/dist/cjs/internal/channel/channelExecutor.js.map +1 -1
  110. package/dist/cjs/internal/channel.js +156 -130
  111. package/dist/cjs/internal/channel.js.map +1 -1
  112. package/dist/cjs/internal/config.js +13 -4
  113. package/dist/cjs/internal/config.js.map +1 -1
  114. package/dist/cjs/internal/context.js +46 -3
  115. package/dist/cjs/internal/context.js.map +1 -1
  116. package/dist/cjs/internal/dateTime.js +747 -0
  117. package/dist/cjs/internal/dateTime.js.map +1 -0
  118. package/dist/cjs/internal/fiberRuntime.js +34 -11
  119. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  120. package/dist/cjs/internal/groupBy.js +9 -3
  121. package/dist/cjs/internal/groupBy.js.map +1 -1
  122. package/dist/cjs/internal/layer.js +1 -1
  123. package/dist/cjs/internal/layer.js.map +1 -1
  124. package/dist/cjs/internal/mailbox.js +1 -1
  125. package/dist/cjs/internal/mailbox.js.map +1 -1
  126. package/dist/cjs/internal/sink.js +25 -21
  127. package/dist/cjs/internal/sink.js.map +1 -1
  128. package/dist/cjs/internal/stream.js +70 -71
  129. package/dist/cjs/internal/stream.js.map +1 -1
  130. package/dist/cjs/internal/version.js +1 -1
  131. package/dist/cjs/internal/version.js.map +1 -1
  132. package/dist/dts/Array.d.ts +534 -0
  133. package/dist/dts/Array.d.ts.map +1 -1
  134. package/dist/dts/BigDecimal.d.ts +172 -1
  135. package/dist/dts/BigDecimal.d.ts.map +1 -1
  136. package/dist/dts/BigInt.d.ts +114 -0
  137. package/dist/dts/BigInt.d.ts.map +1 -1
  138. package/dist/dts/Boolean.d.ts +56 -0
  139. package/dist/dts/Boolean.d.ts.map +1 -1
  140. package/dist/dts/Brand.d.ts +6 -0
  141. package/dist/dts/Brand.d.ts.map +1 -1
  142. package/dist/dts/Channel.d.ts +66 -5
  143. package/dist/dts/Channel.d.ts.map +1 -1
  144. package/dist/dts/Chunk.d.ts +30 -0
  145. package/dist/dts/Chunk.d.ts.map +1 -1
  146. package/dist/dts/Config.d.ts +25 -1
  147. package/dist/dts/Config.d.ts.map +1 -1
  148. package/dist/dts/Context.d.ts +155 -0
  149. package/dist/dts/Context.d.ts.map +1 -1
  150. package/dist/dts/Cron.d.ts +21 -6
  151. package/dist/dts/Cron.d.ts.map +1 -1
  152. package/dist/dts/Data.d.ts +26 -0
  153. package/dist/dts/Data.d.ts.map +1 -1
  154. package/dist/dts/DateTime.d.ts +192 -49
  155. package/dist/dts/DateTime.d.ts.map +1 -1
  156. package/dist/dts/Duration.d.ts +2 -0
  157. package/dist/dts/Duration.d.ts.map +1 -1
  158. package/dist/dts/Effect.d.ts +658 -1
  159. package/dist/dts/Effect.d.ts.map +1 -1
  160. package/dist/dts/Either.d.ts +84 -2
  161. package/dist/dts/Either.d.ts.map +1 -1
  162. package/dist/dts/FiberHandle.d.ts +6 -0
  163. package/dist/dts/FiberHandle.d.ts.map +1 -1
  164. package/dist/dts/FiberMap.d.ts +6 -0
  165. package/dist/dts/FiberMap.d.ts.map +1 -1
  166. package/dist/dts/FiberSet.d.ts +6 -0
  167. package/dist/dts/FiberSet.d.ts.map +1 -1
  168. package/dist/dts/Function.d.ts +50 -0
  169. package/dist/dts/Function.d.ts.map +1 -1
  170. package/dist/dts/GlobalValue.d.ts +2 -0
  171. package/dist/dts/GlobalValue.d.ts.map +1 -1
  172. package/dist/dts/HashMap.d.ts +6 -0
  173. package/dist/dts/HashMap.d.ts.map +1 -1
  174. package/dist/dts/Inspectable.d.ts.map +1 -1
  175. package/dist/dts/Iterable.d.ts +26 -0
  176. package/dist/dts/Iterable.d.ts.map +1 -1
  177. package/dist/dts/JSONSchema.d.ts +1 -0
  178. package/dist/dts/JSONSchema.d.ts.map +1 -1
  179. package/dist/dts/List.d.ts +20 -0
  180. package/dist/dts/List.d.ts.map +1 -1
  181. package/dist/dts/Logger.d.ts +34 -0
  182. package/dist/dts/Logger.d.ts.map +1 -1
  183. package/dist/dts/Mailbox.d.ts +2 -0
  184. package/dist/dts/Mailbox.d.ts.map +1 -1
  185. package/dist/dts/ManagedRuntime.d.ts +2 -0
  186. package/dist/dts/ManagedRuntime.d.ts.map +1 -1
  187. package/dist/dts/Metric.d.ts +18 -0
  188. package/dist/dts/Metric.d.ts.map +1 -1
  189. package/dist/dts/Micro.d.ts +880 -863
  190. package/dist/dts/Micro.d.ts.map +1 -1
  191. package/dist/dts/Number.d.ts +104 -0
  192. package/dist/dts/Number.d.ts.map +1 -1
  193. package/dist/dts/Option.d.ts +142 -0
  194. package/dist/dts/Option.d.ts.map +1 -1
  195. package/dist/dts/Order.d.ts +2 -0
  196. package/dist/dts/Order.d.ts.map +1 -1
  197. package/dist/dts/Ordering.d.ts +8 -0
  198. package/dist/dts/Ordering.d.ts.map +1 -1
  199. package/dist/dts/Predicate.d.ts +104 -0
  200. package/dist/dts/Predicate.d.ts.map +1 -1
  201. package/dist/dts/Random.d.ts +4 -0
  202. package/dist/dts/Random.d.ts.map +1 -1
  203. package/dist/dts/RateLimiter.d.ts +4 -0
  204. package/dist/dts/RateLimiter.d.ts.map +1 -1
  205. package/dist/dts/RcMap.d.ts +6 -0
  206. package/dist/dts/RcMap.d.ts.map +1 -1
  207. package/dist/dts/RcRef.d.ts +2 -0
  208. package/dist/dts/RcRef.d.ts.map +1 -1
  209. package/dist/dts/Record.d.ts +136 -0
  210. package/dist/dts/Record.d.ts.map +1 -1
  211. package/dist/dts/Redacted.d.ts +8 -0
  212. package/dist/dts/Redacted.d.ts.map +1 -1
  213. package/dist/dts/RegExp.d.ts +4 -0
  214. package/dist/dts/RegExp.d.ts.map +1 -1
  215. package/dist/dts/Request.d.ts +4 -0
  216. package/dist/dts/Request.d.ts.map +1 -1
  217. package/dist/dts/RequestResolver.d.ts +6 -0
  218. package/dist/dts/RequestResolver.d.ts.map +1 -1
  219. package/dist/dts/Runtime.d.ts +18 -0
  220. package/dist/dts/Runtime.d.ts.map +1 -1
  221. package/dist/dts/STM.d.ts +2 -0
  222. package/dist/dts/STM.d.ts.map +1 -1
  223. package/dist/dts/Schema.d.ts +90 -0
  224. package/dist/dts/Schema.d.ts.map +1 -1
  225. package/dist/dts/Sink.d.ts +8 -0
  226. package/dist/dts/Sink.d.ts.map +1 -1
  227. package/dist/dts/Stream.d.ts +394 -32
  228. package/dist/dts/Stream.d.ts.map +1 -1
  229. package/dist/dts/String.d.ts +94 -0
  230. package/dist/dts/String.d.ts.map +1 -1
  231. package/dist/dts/Struct.d.ts +24 -0
  232. package/dist/dts/Struct.d.ts.map +1 -1
  233. package/dist/dts/Symbol.d.ts +2 -0
  234. package/dist/dts/Symbol.d.ts.map +1 -1
  235. package/dist/dts/Trie.d.ts +132 -0
  236. package/dist/dts/Trie.d.ts.map +1 -1
  237. package/dist/dts/Tuple.d.ts +42 -0
  238. package/dist/dts/Tuple.d.ts.map +1 -1
  239. package/dist/dts/Types.d.ts +24 -0
  240. package/dist/dts/Types.d.ts.map +1 -1
  241. package/dist/dts/Utils.d.ts +4 -0
  242. package/dist/dts/Utils.d.ts.map +1 -1
  243. package/dist/dts/internal/context.d.ts +1 -1
  244. package/dist/dts/internal/context.d.ts.map +1 -1
  245. package/dist/dts/internal/dateTime.d.ts +2 -0
  246. package/dist/dts/internal/dateTime.d.ts.map +1 -0
  247. package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
  248. package/dist/dts/internal/stream.d.ts.map +1 -1
  249. package/dist/esm/Array.js +208 -0
  250. package/dist/esm/Array.js.map +1 -1
  251. package/dist/esm/BigDecimal.js +175 -20
  252. package/dist/esm/BigDecimal.js.map +1 -1
  253. package/dist/esm/BigInt.js +54 -0
  254. package/dist/esm/BigInt.js.map +1 -1
  255. package/dist/esm/Boolean.js +24 -0
  256. package/dist/esm/Boolean.js.map +1 -1
  257. package/dist/esm/Brand.js +4 -0
  258. package/dist/esm/Brand.js.map +1 -1
  259. package/dist/esm/Channel.js +42 -2
  260. package/dist/esm/Channel.js.map +1 -1
  261. package/dist/esm/Chunk.js +8 -0
  262. package/dist/esm/Chunk.js.map +1 -1
  263. package/dist/esm/Config.js +9 -0
  264. package/dist/esm/Config.js.map +1 -1
  265. package/dist/esm/Context.js +49 -0
  266. package/dist/esm/Context.js.map +1 -1
  267. package/dist/esm/Cron.js +81 -67
  268. package/dist/esm/Cron.js.map +1 -1
  269. package/dist/esm/Data.js +16 -0
  270. package/dist/esm/Data.js.map +1 -1
  271. package/dist/esm/DateTime.js +176 -627
  272. package/dist/esm/DateTime.js.map +1 -1
  273. package/dist/esm/Duration.js +2 -0
  274. package/dist/esm/Duration.js.map +1 -1
  275. package/dist/esm/Effect.js +297 -0
  276. package/dist/esm/Effect.js.map +1 -1
  277. package/dist/esm/Either.js +40 -2
  278. package/dist/esm/Either.js.map +1 -1
  279. package/dist/esm/FiberHandle.js +6 -0
  280. package/dist/esm/FiberHandle.js.map +1 -1
  281. package/dist/esm/FiberMap.js +6 -0
  282. package/dist/esm/FiberMap.js.map +1 -1
  283. package/dist/esm/FiberSet.js +6 -0
  284. package/dist/esm/FiberSet.js.map +1 -1
  285. package/dist/esm/Function.js +34 -0
  286. package/dist/esm/Function.js.map +1 -1
  287. package/dist/esm/GlobalValue.js +2 -0
  288. package/dist/esm/GlobalValue.js.map +1 -1
  289. package/dist/esm/HashMap.js.map +1 -1
  290. package/dist/esm/Inspectable.js +8 -4
  291. package/dist/esm/Inspectable.js.map +1 -1
  292. package/dist/esm/Iterable.js +18 -0
  293. package/dist/esm/Iterable.js.map +1 -1
  294. package/dist/esm/JSONSchema.js.map +1 -1
  295. package/dist/esm/List.js +4 -0
  296. package/dist/esm/List.js.map +1 -1
  297. package/dist/esm/Logger.js +26 -0
  298. package/dist/esm/Logger.js.map +1 -1
  299. package/dist/esm/Mailbox.js +2 -0
  300. package/dist/esm/Mailbox.js.map +1 -1
  301. package/dist/esm/ManagedRuntime.js +2 -0
  302. package/dist/esm/ManagedRuntime.js.map +1 -1
  303. package/dist/esm/Metric.js +10 -0
  304. package/dist/esm/Metric.js.map +1 -1
  305. package/dist/esm/Micro.js +1077 -1037
  306. package/dist/esm/Micro.js.map +1 -1
  307. package/dist/esm/Number.js +44 -0
  308. package/dist/esm/Number.js.map +1 -1
  309. package/dist/esm/Option.js +72 -0
  310. package/dist/esm/Option.js.map +1 -1
  311. package/dist/esm/Order.js +2 -0
  312. package/dist/esm/Order.js.map +1 -1
  313. package/dist/esm/Ordering.js +4 -0
  314. package/dist/esm/Ordering.js.map +1 -1
  315. package/dist/esm/Predicate.js +68 -0
  316. package/dist/esm/Predicate.js.map +1 -1
  317. package/dist/esm/Random.js +4 -0
  318. package/dist/esm/Random.js.map +1 -1
  319. package/dist/esm/RateLimiter.js +4 -0
  320. package/dist/esm/RateLimiter.js.map +1 -1
  321. package/dist/esm/RcMap.js +2 -0
  322. package/dist/esm/RcMap.js.map +1 -1
  323. package/dist/esm/RcRef.js +2 -0
  324. package/dist/esm/RcRef.js.map +1 -1
  325. package/dist/esm/Record.js +56 -0
  326. package/dist/esm/Record.js.map +1 -1
  327. package/dist/esm/Redacted.js +8 -0
  328. package/dist/esm/Redacted.js.map +1 -1
  329. package/dist/esm/RegExp.js +4 -0
  330. package/dist/esm/RegExp.js.map +1 -1
  331. package/dist/esm/Request.js +4 -0
  332. package/dist/esm/Request.js.map +1 -1
  333. package/dist/esm/RequestResolver.js +2 -0
  334. package/dist/esm/RequestResolver.js.map +1 -1
  335. package/dist/esm/Runtime.js +6 -0
  336. package/dist/esm/Runtime.js.map +1 -1
  337. package/dist/esm/STM.js.map +1 -1
  338. package/dist/esm/Schema.js +88 -0
  339. package/dist/esm/Schema.js.map +1 -1
  340. package/dist/esm/Sink.js +8 -0
  341. package/dist/esm/Sink.js.map +1 -1
  342. package/dist/esm/Stream.js +183 -5
  343. package/dist/esm/Stream.js.map +1 -1
  344. package/dist/esm/String.js +62 -0
  345. package/dist/esm/String.js.map +1 -1
  346. package/dist/esm/Struct.js +12 -0
  347. package/dist/esm/Struct.js.map +1 -1
  348. package/dist/esm/Symbol.js +2 -0
  349. package/dist/esm/Symbol.js.map +1 -1
  350. package/dist/esm/Trie.js +56 -0
  351. package/dist/esm/Trie.js.map +1 -1
  352. package/dist/esm/Tuple.js +22 -0
  353. package/dist/esm/Tuple.js.map +1 -1
  354. package/dist/esm/Utils.js +5 -0
  355. package/dist/esm/Utils.js.map +1 -1
  356. package/dist/esm/internal/channel/channelExecutor.js +5 -7
  357. package/dist/esm/internal/channel/channelExecutor.js.map +1 -1
  358. package/dist/esm/internal/channel.js +152 -129
  359. package/dist/esm/internal/channel.js.map +1 -1
  360. package/dist/esm/internal/config.js +11 -3
  361. package/dist/esm/internal/config.js.map +1 -1
  362. package/dist/esm/internal/context.js +42 -2
  363. package/dist/esm/internal/context.js.map +1 -1
  364. package/dist/esm/internal/dateTime.js +704 -0
  365. package/dist/esm/internal/dateTime.js.map +1 -0
  366. package/dist/esm/internal/fiberRuntime.js +31 -9
  367. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  368. package/dist/esm/internal/groupBy.js +9 -3
  369. package/dist/esm/internal/groupBy.js.map +1 -1
  370. package/dist/esm/internal/layer.js +1 -1
  371. package/dist/esm/internal/layer.js.map +1 -1
  372. package/dist/esm/internal/mailbox.js +1 -1
  373. package/dist/esm/internal/mailbox.js.map +1 -1
  374. package/dist/esm/internal/sink.js +23 -20
  375. package/dist/esm/internal/sink.js.map +1 -1
  376. package/dist/esm/internal/stream.js +66 -69
  377. package/dist/esm/internal/stream.js.map +1 -1
  378. package/dist/esm/internal/version.js +1 -1
  379. package/dist/esm/internal/version.js.map +1 -1
  380. package/package.json +1 -1
  381. package/src/Array.ts +534 -0
  382. package/src/BigDecimal.ts +247 -21
  383. package/src/BigInt.ts +114 -0
  384. package/src/Boolean.ts +56 -0
  385. package/src/Brand.ts +6 -0
  386. package/src/Channel.ts +81 -5
  387. package/src/Chunk.ts +32 -0
  388. package/src/Config.ts +26 -1
  389. package/src/Context.ts +163 -0
  390. package/src/Cron.ts +91 -68
  391. package/src/Data.ts +26 -0
  392. package/src/DateTime.ts +307 -757
  393. package/src/Duration.ts +2 -0
  394. package/src/Effect.ts +910 -1
  395. package/src/Either.ts +84 -2
  396. package/src/FiberHandle.ts +6 -0
  397. package/src/FiberMap.ts +6 -0
  398. package/src/FiberSet.ts +6 -0
  399. package/src/Function.ts +50 -0
  400. package/src/GlobalValue.ts +2 -0
  401. package/src/HashMap.ts +6 -0
  402. package/src/Inspectable.ts +11 -7
  403. package/src/Iterable.ts +26 -0
  404. package/src/JSONSchema.ts +1 -0
  405. package/src/List.ts +24 -0
  406. package/src/Logger.ts +34 -0
  407. package/src/Mailbox.ts +2 -0
  408. package/src/ManagedRuntime.ts +2 -0
  409. package/src/Metric.ts +18 -0
  410. package/src/Micro.ts +2007 -1745
  411. package/src/Number.ts +104 -0
  412. package/src/Option.ts +142 -0
  413. package/src/Order.ts +2 -0
  414. package/src/Ordering.ts +8 -0
  415. package/src/Predicate.ts +104 -0
  416. package/src/Random.ts +4 -0
  417. package/src/RateLimiter.ts +4 -0
  418. package/src/RcMap.ts +6 -0
  419. package/src/RcRef.ts +2 -0
  420. package/src/Record.ts +136 -0
  421. package/src/Redacted.ts +8 -0
  422. package/src/RegExp.ts +4 -0
  423. package/src/Request.ts +4 -0
  424. package/src/RequestResolver.ts +6 -0
  425. package/src/Runtime.ts +18 -0
  426. package/src/STM.ts +2 -0
  427. package/src/Schema.ts +124 -0
  428. package/src/Sink.ts +11 -0
  429. package/src/Stream.ts +399 -44
  430. package/src/String.ts +94 -0
  431. package/src/Struct.ts +24 -0
  432. package/src/Symbol.ts +2 -0
  433. package/src/Trie.ts +132 -0
  434. package/src/Tuple.ts +42 -0
  435. package/src/Types.ts +24 -0
  436. package/src/Utils.ts +8 -0
  437. package/src/internal/channel/channelExecutor.ts +37 -33
  438. package/src/internal/channel.ts +504 -467
  439. package/src/internal/config.ts +18 -6
  440. package/src/internal/context.ts +56 -4
  441. package/src/internal/dateTime.ts +1126 -0
  442. package/src/internal/fiberRuntime.ts +35 -16
  443. package/src/internal/groupBy.ts +13 -22
  444. package/src/internal/layer.ts +5 -8
  445. package/src/internal/mailbox.ts +6 -4
  446. package/src/internal/sink.ts +55 -35
  447. package/src/internal/stream.ts +299 -299
  448. package/src/internal/version.ts +1 -1
package/src/Micro.ts CHANGED
@@ -4,28 +4,33 @@
4
4
  * @since 3.4.0
5
5
  * @experimental
6
6
  */
7
- import type { Channel, ChannelTypeId } from "./Channel.js"
7
+ import * as Arr from "effect/Array"
8
+ import type { Channel } from "./Channel.js"
8
9
  import * as Context from "./Context.js"
9
- import type { Effect, EffectTypeId, EffectUnify, EffectUnifyIgnore } from "./Effect.js"
10
+ import type { Effect, EffectUnify, EffectUnifyIgnore } from "./Effect.js"
10
11
  import * as Effectable from "./Effectable.js"
11
12
  import * as Either from "./Either.js"
12
- import { constTrue, constVoid, dual, identity, type LazyArg } from "./Function.js"
13
+ import * as Equal from "./Equal.js"
14
+ import type { LazyArg } from "./Function.js"
15
+ import { constTrue, constVoid, dual, identity } from "./Function.js"
13
16
  import { globalValue } from "./GlobalValue.js"
17
+ import * as Hash from "./Hash.js"
14
18
  import type { TypeLambda } from "./HKT.js"
15
19
  import type { Inspectable } from "./Inspectable.js"
16
- import { NodeInspectSymbol, toStringUnknown } from "./Inspectable.js"
20
+ import { format, NodeInspectSymbol, toStringUnknown } from "./Inspectable.js"
21
+ import * as InternalContext from "./internal/context.js"
17
22
  import * as doNotation from "./internal/doNotation.js"
18
23
  import { StructuralPrototype } from "./internal/effectable.js"
19
- import { SingleShotGen } from "./internal/singleShotGen.js"
20
24
  import * as Option from "./Option.js"
21
- import { type Pipeable, pipeArguments } from "./Pipeable.js"
22
- import { hasProperty, isIterable, isTagged, type Predicate, type Refinement } from "./Predicate.js"
23
- import type { ReadonlyRecord } from "./Record.js"
24
- import type { Sink, SinkTypeId } from "./Sink.js"
25
- import type { Stream, StreamTypeId } from "./Stream.js"
26
- import type { Concurrency, Covariant, Equals, NoInfer, NotFunction, Simplify } from "./Types.js"
25
+ import type { Pipeable } from "./Pipeable.js"
26
+ import { pipeArguments } from "./Pipeable.js"
27
+ import type { Predicate, Refinement } from "./Predicate.js"
28
+ import { hasProperty, isIterable, isTagged } from "./Predicate.js"
29
+ import type { Sink } from "./Sink.js"
30
+ import type { Stream } from "./Stream.js"
31
+ import type { Concurrency, Covariant, Equals, NotFunction, Simplify } from "./Types.js"
27
32
  import type * as Unify from "./Unify.js"
28
- import { YieldWrap, yieldWrapGet } from "./Utils.js"
33
+ import { SingleShotGen, YieldWrap, yieldWrapGet } from "./Utils.js"
29
34
 
30
35
  /**
31
36
  * @since 3.4.0
@@ -44,16 +49,18 @@ export type TypeId = typeof TypeId
44
49
  /**
45
50
  * @since 3.4.0
46
51
  * @experimental
47
- * @category symbols
52
+ * @category MicroExit
48
53
  */
49
- export const runSymbol: unique symbol = Symbol.for("effect/Micro/runSymbol")
54
+ export const MicroExitTypeId: unique symbol = Symbol.for(
55
+ "effect/Micro/MicroExit"
56
+ )
50
57
 
51
58
  /**
52
59
  * @since 3.4.0
53
60
  * @experimental
54
- * @category symbols
61
+ * @category MicroExit
55
62
  */
56
- export type runSymbol = typeof runSymbol
63
+ export type MicroExitTypeId = typeof TypeId
57
64
 
58
65
  /**
59
66
  * A lightweight alternative to the `Effect` data type, with a subset of the functionality.
@@ -64,7 +71,6 @@ export type runSymbol = typeof runSymbol
64
71
  */
65
72
  export interface Micro<out A, out E = never, out R = never> extends Effect<A, E, R> {
66
73
  readonly [TypeId]: Micro.Variance<A, E, R>
67
- [runSymbol](env: Env<any>, onExit: (exit: MicroExit<A, E>) => void): void
68
74
  [Symbol.iterator](): MicroIterator<Micro<A, E, R>>
69
75
  [Unify.typeSymbol]?: unknown
70
76
  [Unify.unifySymbol]?: MicroUnify<this>
@@ -144,58 +150,6 @@ export interface MicroIterator<T extends Micro<any, any, any>> {
144
150
  next(...args: ReadonlyArray<any>): IteratorResult<YieldWrap<T>, Micro.Success<T>>
145
151
  }
146
152
 
147
- /**
148
- * @since 3.8.4
149
- * @experimental
150
- * @category models
151
- */
152
- export interface MicroClass {
153
- new<A, E = never, R = never>(): Micro<A, E, R>
154
- }
155
-
156
- // ----------------------------------------------------------------------------
157
- // Microable
158
- // ----------------------------------------------------------------------------
159
-
160
- const MicroProto = {
161
- ...Effectable.EffectPrototype,
162
- _op: "Micro",
163
- [TypeId]: {
164
- _A: identity,
165
- _E: identity,
166
- _R: identity
167
- },
168
- [Symbol.iterator]() {
169
- return new SingleShotGen(new YieldWrap(this)) as any
170
- }
171
- }
172
-
173
- const MicroBase: MicroClass = (function() {
174
- function Base() {}
175
- Base.prototype = MicroProto
176
- return Base as any
177
- })()
178
-
179
- /**
180
- * @since 3.8.4
181
- * @experimental
182
- * @category constructors
183
- */
184
- export abstract class Class<out A, out E = never, out R = never> extends MicroBase<A, E, R> {
185
- /**
186
- * @since 3.8.4
187
- * @experimental
188
- */
189
- abstract asMicro(): Micro<A, E, R>
190
- /**
191
- * @since 3.8.4
192
- * @experimental
193
- */
194
- [runSymbol](env: Env<any>, onExit: (exit: MicroExit<A, E>) => void): void {
195
- this.asMicro()[runSymbol](env, onExit)
196
- }
197
- }
198
-
199
153
  // ----------------------------------------------------------------------------
200
154
  // MicroCause
201
155
  // ----------------------------------------------------------------------------
@@ -221,7 +175,10 @@ export type MicroCauseTypeId = typeof MicroCauseTypeId
221
175
  * @experimental
222
176
  * @category MicroCause
223
177
  */
224
- export type MicroCause<E> = MicroCause.Die | MicroCause.Fail<E> | MicroCause.Interrupt
178
+ export type MicroCause<E> =
179
+ | MicroCause.Die
180
+ | MicroCause.Fail<E>
181
+ | MicroCause.Interrupt
225
182
 
226
183
  /**
227
184
  * @since 3.6.6
@@ -302,7 +259,12 @@ abstract class MicroCauseImpl<Tag extends string, E> extends globalThis.Error im
302
259
  message = originalError.message as string
303
260
  const messageLines = message.split("\n").length
304
261
  stack = originalError.stack
305
- ? `(${causeName}) ${originalError.stack.split("\n").slice(0, messageLines + 3).join("\n")}`
262
+ ? `(${causeName}) ${
263
+ originalError.stack
264
+ .split("\n")
265
+ .slice(0, messageLines + 3)
266
+ .join("\n")
267
+ }`
306
268
  : `${name}: ${message}`
307
269
  } else {
308
270
  name = causeName
@@ -329,7 +291,10 @@ abstract class MicroCauseImpl<Tag extends string, E> extends globalThis.Error im
329
291
  }
330
292
 
331
293
  class FailImpl<E> extends MicroCauseImpl<"Fail", E> implements MicroCause.Fail<E> {
332
- constructor(readonly error: E, traces: ReadonlyArray<string> = []) {
294
+ constructor(
295
+ readonly error: E,
296
+ traces: ReadonlyArray<string> = []
297
+ ) {
333
298
  super("Fail", error, traces)
334
299
  }
335
300
  }
@@ -339,10 +304,16 @@ class FailImpl<E> extends MicroCauseImpl<"Fail", E> implements MicroCause.Fail<E
339
304
  * @experimental
340
305
  * @category MicroCause
341
306
  */
342
- export const causeFail = <E>(error: E, traces: ReadonlyArray<string> = []): MicroCause<E> => new FailImpl(error, traces)
307
+ export const causeFail = <E>(
308
+ error: E,
309
+ traces: ReadonlyArray<string> = []
310
+ ): MicroCause<E> => new FailImpl(error, traces)
343
311
 
344
312
  class DieImpl extends MicroCauseImpl<"Die", never> implements MicroCause.Die {
345
- constructor(readonly defect: unknown, traces: ReadonlyArray<string> = []) {
313
+ constructor(
314
+ readonly defect: unknown,
315
+ traces: ReadonlyArray<string> = []
316
+ ) {
346
317
  super("Die", defect, traces)
347
318
  }
348
319
  }
@@ -352,8 +323,10 @@ class DieImpl extends MicroCauseImpl<"Die", never> implements MicroCause.Die {
352
323
  * @experimental
353
324
  * @category MicroCause
354
325
  */
355
- export const causeDie = (defect: unknown, traces: ReadonlyArray<string> = []): MicroCause<never> =>
356
- new DieImpl(defect, traces)
326
+ export const causeDie = (
327
+ defect: unknown,
328
+ traces: ReadonlyArray<string> = []
329
+ ): MicroCause<never> => new DieImpl(defect, traces)
357
330
 
358
331
  class InterruptImpl extends MicroCauseImpl<"Interrupt", never> implements MicroCause.Interrupt {
359
332
  constructor(traces: ReadonlyArray<string> = []) {
@@ -366,14 +339,18 @@ class InterruptImpl extends MicroCauseImpl<"Interrupt", never> implements MicroC
366
339
  * @experimental
367
340
  * @category MicroCause
368
341
  */
369
- export const causeInterrupt = (traces: ReadonlyArray<string> = []): MicroCause<never> => new InterruptImpl(traces)
342
+ export const causeInterrupt = (
343
+ traces: ReadonlyArray<string> = []
344
+ ): MicroCause<never> => new InterruptImpl(traces)
370
345
 
371
346
  /**
372
347
  * @since 3.4.6
373
348
  * @experimental
374
349
  * @category MicroCause
375
350
  */
376
- export const causeIsFail = <E>(self: MicroCause<E>): self is MicroCause.Fail<E> => self._tag === "Fail"
351
+ export const causeIsFail = <E>(
352
+ self: MicroCause<E>
353
+ ): self is MicroCause.Fail<E> => self._tag === "Fail"
377
354
 
378
355
  /**
379
356
  * @since 3.4.6
@@ -387,7 +364,9 @@ export const causeIsDie = <E>(self: MicroCause<E>): self is MicroCause.Die => se
387
364
  * @experimental
388
365
  * @category MicroCause
389
366
  */
390
- export const causeIsInterrupt = <E>(self: MicroCause<E>): self is MicroCause.Interrupt => self._tag === "Interrupt"
367
+ export const causeIsInterrupt = <E>(
368
+ self: MicroCause<E>
369
+ ): self is MicroCause.Interrupt => self._tag === "Interrupt"
391
370
 
392
371
  /**
393
372
  * @since 3.4.6
@@ -428,1680 +407,1963 @@ export const causeWithTrace: {
428
407
  })
429
408
 
430
409
  // ----------------------------------------------------------------------------
431
- // MicroExit
410
+ // Fiber
432
411
  // ----------------------------------------------------------------------------
433
412
 
434
413
  /**
435
- * @since 3.4.6
414
+ * @since 3.11.0
436
415
  * @experimental
437
- * @category MicroExit
416
+ * @category Fiber
438
417
  */
439
- export declare namespace MicroExit {
440
- /**
441
- * @since 3.4.6
442
- * @experimental
443
- * @category MicroExit
444
- */
445
- export type Success<A, E = never> = Either.Right<MicroCause<E>, A>
446
-
447
- /**
448
- * @since 3.4.6
449
- * @experimental
450
- * @category MicroExit
451
- */
452
- export type Failure<A, E = never> = Either.Left<MicroCause<E>, A>
453
- }
418
+ export const FiberTypeId = Symbol.for("effect/Micro/Fiber")
454
419
 
455
420
  /**
456
- * The MicroExit type is a data type that represents the result of a Micro
457
- * computation.
458
- *
459
- * It uses the `Either` data type to represent the success and failure cases.
460
- *
461
- * @since 3.4.6
421
+ * @since 3.11.0
462
422
  * @experimental
463
- * @category MicroExit
423
+ * @category Fiber
464
424
  */
465
- export type MicroExit<A, E = never> = MicroExit.Success<A, E> | MicroExit.Failure<A, E>
425
+ export type FiberTypeId = typeof FiberTypeId
466
426
 
467
427
  /**
468
- * @since 3.4.6
428
+ * @since 3.11.0
469
429
  * @experimental
470
- * @category MicroExit
430
+ * @category Fiber
471
431
  */
472
- export const exitInterrupt: MicroExit<never> = Either.left(causeInterrupt())
432
+ export interface Fiber<out A, out E = never> {
433
+ readonly [FiberTypeId]: Fiber.Variance<A, E>
473
434
 
474
- /**
475
- * @since 3.4.6
476
- * @experimental
477
- * @category MicroExit
478
- */
479
- export const exitSucceed: <A>(a: A) => MicroExit<A, never> = Either.right
435
+ readonly currentOpCount: number
436
+ readonly getRef: <I, A>(ref: Context.Reference<I, A>) => A
437
+ readonly context: Context.Context<never>
438
+ readonly addObserver: (cb: (exit: MicroExit<A, E>) => void) => () => void
439
+ readonly unsafeInterrupt: () => void
440
+ readonly unsafePoll: () => MicroExit<A, E> | undefined
441
+ }
480
442
 
481
443
  /**
482
- * @since 3.4.6
444
+ * @since 3.11.0
483
445
  * @experimental
484
- * @category MicroExit
446
+ * @category Fiber
485
447
  */
486
- export const exitFail = <E>(e: E): MicroExit<never, E> => Either.left(causeFail(e))
448
+ export declare namespace Fiber {
449
+ /**
450
+ * @since 3.11.0
451
+ * @experimental
452
+ * @category Fiber
453
+ */
454
+ export interface Variance<out A, out E = never> {
455
+ readonly _A: Covariant<A>
456
+ readonly _E: Covariant<E>
457
+ }
458
+ }
459
+
460
+ const fiberVariance = {
461
+ _A: identity,
462
+ _E: identity
463
+ }
464
+
465
+ class FiberImpl<in out A = any, in out E = any> implements Fiber<A, E> {
466
+ readonly [FiberTypeId]: Fiber.Variance<A, E>
467
+
468
+ readonly _stack: Array<Primitive> = []
469
+ readonly _observers: Array<(exit: MicroExit<A, E>) => void> = []
470
+ _exit: MicroExit<A, E> | undefined
471
+ public _children: Set<FiberImpl<any, any>> | undefined
472
+
473
+ public currentOpCount = 0
474
+
475
+ constructor(
476
+ public context: Context.Context<never>,
477
+ public interruptible = true
478
+ ) {
479
+ this[FiberTypeId] = fiberVariance
480
+ }
481
+
482
+ getRef<I, A>(ref: Context.Reference<I, A>): A {
483
+ return InternalContext.unsafeGetReference(this.context, ref)
484
+ }
485
+
486
+ addObserver(cb: (exit: MicroExit<A, E>) => void): () => void {
487
+ if (this._exit) {
488
+ cb(this._exit)
489
+ return constVoid
490
+ }
491
+ this._observers.push(cb)
492
+ return () => {
493
+ const index = this._observers.indexOf(cb)
494
+ if (index >= 0) {
495
+ this._observers.splice(index, 1)
496
+ }
497
+ }
498
+ }
499
+
500
+ _interrupted = false
501
+ unsafeInterrupt(): void {
502
+ if (this._exit) {
503
+ return
504
+ }
505
+ this._interrupted = true
506
+ if (this.interruptible) {
507
+ this.evaluate(exitInterrupt as any)
508
+ }
509
+ }
510
+
511
+ unsafePoll(): MicroExit<A, E> | undefined {
512
+ return this._exit
513
+ }
514
+
515
+ evaluate(effect: Primitive): void {
516
+ if (this._exit) {
517
+ return
518
+ } else if (this._yielded !== undefined) {
519
+ const yielded = this._yielded as () => void
520
+ this._yielded = undefined
521
+ yielded()
522
+ }
523
+ const exit = this.runLoop(effect)
524
+ if (exit === Yield) {
525
+ return
526
+ }
527
+
528
+ // the interruptChildren middlware is added in Micro.fork, so it can be
529
+ // tree-shaken if not used
530
+ const interruptChildren = fiberMiddleware.interruptChildren && fiberMiddleware.interruptChildren(this)
531
+ if (interruptChildren !== undefined) {
532
+ return this.evaluate(flatMap(interruptChildren, () => exit) as any)
533
+ }
534
+
535
+ this._exit = exit
536
+ for (let i = 0; i < this._observers.length; i++) {
537
+ this._observers[i](exit)
538
+ }
539
+ this._observers.length = 0
540
+ }
541
+
542
+ runLoop(effect: Primitive): MicroExit<A, E> | Yield {
543
+ let yielding = false
544
+ let current: Primitive | Yield = effect
545
+ this.currentOpCount = 0
546
+ try {
547
+ while (true) {
548
+ this.currentOpCount++
549
+ if (!yielding && this.getRef(CurrentScheduler).shouldYield(this as any)) {
550
+ yielding = true
551
+ const prev = current
552
+ current = flatMap(yieldNow, () => prev as any) as any
553
+ }
554
+ current = (current as any)[evaluate](this)
555
+ if (current === Yield) {
556
+ const yielded = this._yielded!
557
+ if (MicroExitTypeId in yielded) {
558
+ this._yielded = undefined
559
+ return yielded
560
+ }
561
+ return Yield
562
+ }
563
+ }
564
+ } catch (error) {
565
+ if (!hasProperty(current, evaluate)) {
566
+ return exitDie(`Micro/Fiber.runLoop: Not a valid effect: ${String(current)}`)
567
+ }
568
+ return exitDie(error)
569
+ }
570
+ }
571
+
572
+ getCont<S extends successCont | failureCont>(
573
+ symbol: S
574
+ ): Primitive & Record<S, (value: any, fiber: FiberImpl) => Primitive> | undefined {
575
+ while (true) {
576
+ const op = this._stack.pop()
577
+ if (!op) return undefined
578
+ const cont = op[ensureCont] && op[ensureCont](this)
579
+ if (cont) return { [symbol]: cont } as any
580
+ if (op[symbol]) return op as any
581
+ }
582
+ }
583
+
584
+ // cancel the yielded operation, or for the yielded exit value
585
+ _yielded: MicroExit<any, any> | (() => void) | undefined = undefined
586
+ yieldWith(value: MicroExit<any, any> | (() => void)): Yield {
587
+ this._yielded = value
588
+ return Yield
589
+ }
590
+
591
+ children(): Set<Fiber<any, any>> {
592
+ return this._children ??= new Set()
593
+ }
594
+ }
595
+
596
+ const fiberMiddleware = globalValue("effect/Micro/fiberMiddleware", () => ({
597
+ interruptChildren: undefined as ((fiber: FiberImpl) => Micro<void> | undefined) | undefined
598
+ }))
599
+
600
+ const fiberInterruptChildren = (fiber: FiberImpl) => {
601
+ if (fiber._children === undefined || fiber._children.size === 0) {
602
+ return undefined
603
+ }
604
+ return fiberInterruptAll(fiber._children)
605
+ }
487
606
 
488
607
  /**
489
- * @since 3.4.6
608
+ * @since 3.11.0
490
609
  * @experimental
491
- * @category MicroExit
610
+ * @category Fiber
492
611
  */
493
- export const exitDie = (defect: unknown): MicroExit<never> => Either.left(causeDie(defect))
612
+ export const fiberAwait = <A, E>(self: Fiber<A, E>): Micro<MicroExit<A, E>> =>
613
+ async((resume) => sync(self.addObserver((exit) => resume(succeed(exit)))))
494
614
 
495
615
  /**
496
- * @since 3.4.6
616
+ * @since 3.11.0
497
617
  * @experimental
498
- * @category MicroExit
618
+ * @category Fiber
499
619
  */
500
- export const exitFailCause: <E>(cause: MicroCause<E>) => MicroExit<never, E> = Either.left
620
+ export const fiberInterrupt = <A, E>(self: Fiber<A, E>): Micro<void> =>
621
+ suspend(() => {
622
+ self.unsafeInterrupt()
623
+ return asVoid(fiberAwait(self))
624
+ })
501
625
 
502
626
  /**
503
- * @since 3.4.6
627
+ * @since 3.11.0
504
628
  * @experimental
505
- * @category MicroExit
629
+ * @category Fiber
506
630
  */
507
- export const exitIsSuccess: <A, E>(self: MicroExit<A, E>) => self is MicroExit.Success<A, E> = Either.isRight
631
+ export const fiberInterruptAll = <A extends Iterable<Fiber<any, any>>>(fibers: A): Micro<void> =>
632
+ suspend(() => {
633
+ for (const fiber of fibers) fiber.unsafeInterrupt()
634
+ const iter = fibers[Symbol.iterator]()
635
+ const wait: Micro<void> = suspend(() => {
636
+ let result = iter.next()
637
+ while (!result.done) {
638
+ if (result.value.unsafePoll()) {
639
+ result = iter.next()
640
+ continue
641
+ }
642
+ const fiber = result.value
643
+ return async((resume) => {
644
+ fiber.addObserver((_) => {
645
+ resume(wait)
646
+ })
647
+ })
648
+ }
649
+ return exitVoid
650
+ })
651
+ return wait
652
+ })
653
+
654
+ const identifier = Symbol.for("effect/Micro/identifier")
655
+ type identifier = typeof identifier
656
+
657
+ const args = Symbol.for("effect/Micro/args")
658
+ type args = typeof args
659
+
660
+ const evaluate = Symbol.for("effect/Micro/evaluate")
661
+ type evaluate = typeof evaluate
662
+
663
+ const successCont = Symbol.for("effect/Micro/successCont")
664
+ type successCont = typeof successCont
665
+
666
+ const failureCont = Symbol.for("effect/Micro/failureCont")
667
+ type failureCont = typeof failureCont
668
+
669
+ const ensureCont = Symbol.for("effect/Micro/ensureCont")
670
+ type ensureCont = typeof ensureCont
671
+
672
+ const Yield = Symbol.for("effect/Micro/Yield")
673
+ type Yield = typeof Yield
674
+
675
+ interface Primitive {
676
+ readonly [identifier]: string
677
+ readonly [successCont]: ((value: unknown, fiber: FiberImpl) => Primitive | Yield) | undefined
678
+ readonly [failureCont]:
679
+ | ((cause: MicroCause<unknown>, fiber: FiberImpl) => Primitive | Yield)
680
+ | undefined
681
+ readonly [ensureCont]:
682
+ | ((fiber: FiberImpl) =>
683
+ | ((value: unknown, fiber: FiberImpl) => Primitive | Yield)
684
+ | undefined)
685
+ | undefined
686
+ [evaluate](fiber: FiberImpl): Primitive | Yield
687
+ }
688
+
689
+ const microVariance = {
690
+ _A: identity,
691
+ _E: identity,
692
+ _R: identity
693
+ }
694
+
695
+ const MicroProto = {
696
+ ...Effectable.EffectPrototype,
697
+ _op: "Micro",
698
+ [TypeId]: microVariance,
699
+ pipe() {
700
+ return pipeArguments(this, arguments)
701
+ },
702
+ [Symbol.iterator]() {
703
+ return new SingleShotGen(new YieldWrap(this)) as any
704
+ },
705
+ toJSON(this: Primitive) {
706
+ return {
707
+ _id: "effect/Micro",
708
+ op: this[identifier],
709
+ ...(args in this ? { args: this[args] } : undefined)
710
+ }
711
+ },
712
+ toString() {
713
+ return format(this)
714
+ },
715
+ [NodeInspectSymbol]() {
716
+ return format(this)
717
+ }
718
+ }
719
+
720
+ function defaultEvaluate(_fiber: FiberImpl): Primitive | Yield {
721
+ return exitDie(`Micro.evaluate: Not implemented`) as any
722
+ }
723
+
724
+ const makePrimitiveProto = <Op extends string>(options: {
725
+ readonly op: Op
726
+ readonly eval?: (fiber: FiberImpl) => Primitive | Micro<any, any, any> | Yield
727
+ readonly contA?: (this: Primitive, value: any, fiber: FiberImpl) => Primitive | Micro<any, any, any> | Yield
728
+ readonly contE?: (
729
+ this: Primitive,
730
+ cause: MicroCause<any>,
731
+ fiber: FiberImpl
732
+ ) => Primitive | Micro<any, any, any> | Yield
733
+ readonly ensure?: (this: Primitive, fiber: FiberImpl) => void | ((value: any, fiber: FiberImpl) => void)
734
+ }): Primitive => ({
735
+ ...MicroProto,
736
+ [identifier]: options.op,
737
+ [evaluate]: options.eval ?? defaultEvaluate,
738
+ [successCont]: options.contA,
739
+ [failureCont]: options.contE,
740
+ [ensureCont]: options.ensure
741
+ } as any)
742
+
743
+ const makePrimitive = <Fn extends (...args: Array<any>) => any, Single extends boolean = true>(options: {
744
+ readonly op: string
745
+ readonly single?: Single
746
+ readonly eval?: (
747
+ this: Primitive & { readonly [args]: Single extends true ? Parameters<Fn>[0] : Parameters<Fn> },
748
+ fiber: FiberImpl
749
+ ) => Primitive | Micro<any, any, any> | Yield
750
+ readonly contA?: (
751
+ this: Primitive & { readonly [args]: Single extends true ? Parameters<Fn>[0] : Parameters<Fn> },
752
+ value: any,
753
+ fiber: FiberImpl
754
+ ) => Primitive | Micro<any, any, any> | Yield
755
+ readonly contE?: (
756
+ this: Primitive & { readonly [args]: Single extends true ? Parameters<Fn>[0] : Parameters<Fn> },
757
+ cause: MicroCause<any>,
758
+ fiber: FiberImpl
759
+ ) => Primitive | Micro<any, any, any> | Yield
760
+ readonly ensure?: (
761
+ this: Primitive & { readonly [args]: Single extends true ? Parameters<Fn>[0] : Parameters<Fn> },
762
+ fiber: FiberImpl
763
+ ) => void | ((value: any, fiber: FiberImpl) => void)
764
+ }): Fn => {
765
+ const Proto = makePrimitiveProto(options as any)
766
+ return function() {
767
+ const self = Object.create(Proto)
768
+ self[args] = options.single === false ? arguments : arguments[0]
769
+ return self
770
+ } as Fn
771
+ }
772
+
773
+ const makeExit = <Fn extends (...args: Array<any>) => any, Prop extends string>(options: {
774
+ readonly op: "Success" | "Failure"
775
+ readonly prop: Prop
776
+ readonly eval: (
777
+ this:
778
+ & MicroExit<unknown, unknown>
779
+ & { [args]: Parameters<Fn>[0] },
780
+ fiber: FiberImpl<unknown, unknown>
781
+ ) => Primitive | Yield
782
+ }): Fn => {
783
+ const Proto = {
784
+ ...makePrimitiveProto(options),
785
+ [MicroExitTypeId]: MicroExitTypeId,
786
+ _tag: options.op,
787
+ get [options.prop](): any {
788
+ return (this as any)[args]
789
+ },
790
+ toJSON(this: any) {
791
+ return {
792
+ _id: "effect/Micro/Exit",
793
+ _tag: options.op,
794
+ [options.prop]: this[args]
795
+ }
796
+ },
797
+ [Equal.symbol](this: any, that: any): boolean {
798
+ return isMicroExit(that) && that._tag === options.op &&
799
+ Equal.equals(this[args], (that as any)[args])
800
+ },
801
+ [Hash.symbol](this: any): number {
802
+ return Hash.cached(this, Hash.combine(Hash.string(options.op))(Hash.hash(this[args])))
803
+ }
804
+ }
805
+ return function(value: unknown) {
806
+ const self = Object.create(Proto)
807
+ self[args] = value
808
+ self[successCont] = undefined
809
+ self[failureCont] = undefined
810
+ self[ensureCont] = undefined
811
+ return self
812
+ } as Fn
813
+ }
508
814
 
509
815
  /**
510
- * @since 3.4.6
816
+ * Creates a `Micro` effect that will succeed with the specified constant value.
817
+ *
818
+ * @since 3.4.0
511
819
  * @experimental
512
- * @category MicroExit
820
+ * @category constructors
513
821
  */
514
- export const exitIsFailure: <A, E>(self: MicroExit<A, E>) => self is MicroExit.Failure<A, E> = Either.isLeft
822
+ export const succeed: <A>(value: A) => Micro<A> = makeExit({
823
+ op: "Success",
824
+ prop: "value",
825
+ eval(fiber) {
826
+ const cont = fiber.getCont(successCont)
827
+ return cont ? cont[successCont](this[args], fiber) : fiber.yieldWith(this)
828
+ }
829
+ })
515
830
 
516
831
  /**
832
+ * Creates a `Micro` effect that will fail with the specified `MicroCause`.
833
+ *
517
834
  * @since 3.4.6
518
835
  * @experimental
519
- * @category MicroExit
836
+ * @category constructors
520
837
  */
521
- export const exitIsInterrupt = <A, E>(self: MicroExit<A, E>): self is Either.Left<MicroCause.Interrupt, A> =>
522
- exitIsFailure(self) && self.left._tag === "Interrupt"
838
+ export const failCause: <E>(cause: MicroCause<E>) => Micro<never, E> = makeExit({
839
+ op: "Failure",
840
+ prop: "cause",
841
+ eval(fiber) {
842
+ let cont = fiber.getCont(failureCont)
843
+ while (causeIsInterrupt(this[args]) && cont && fiber.interruptible) {
844
+ cont = fiber.getCont(failureCont)
845
+ }
846
+ return cont ? cont[failureCont](this[args], fiber) : fiber.yieldWith(this)
847
+ }
848
+ })
523
849
 
524
850
  /**
525
- * @since 3.4.6
851
+ * Creates a `Micro` effect that will fail with the specified error.
852
+ *
853
+ * This will result in a `CauseFail`, where the error is tracked at the
854
+ * type level.
855
+ *
856
+ * @since 3.4.0
526
857
  * @experimental
527
- * @category MicroExit
858
+ * @category constructors
528
859
  */
529
- export const exitIsFail = <A, E>(self: MicroExit<A, E>): self is Either.Left<MicroCause.Fail<E>, A> =>
530
- exitIsFailure(self) && self.left._tag === "Fail"
860
+ export const fail = <E>(error: E): Micro<never, E> => failCause(causeFail(error))
531
861
 
532
862
  /**
533
- * @since 3.4.6
863
+ * Creates a `Micro` effect that will succeed with the lazily evaluated value.
864
+ *
865
+ * If the evaluation of the value throws an error, the effect will fail with
866
+ * `CauseDie`.
867
+ *
868
+ * @since 3.4.0
534
869
  * @experimental
535
- * @category MicroExit
870
+ * @category constructors
536
871
  */
537
- export const exitIsDie = <A, E>(self: MicroExit<A, E>): self is Either.Left<MicroCause.Die, A> =>
538
- exitIsFailure(self) && self.left._tag === "Die"
872
+ export const sync: <A>(evaluate: LazyArg<A>) => Micro<A> = makePrimitive({
873
+ op: "Sync",
874
+ eval(fiber): Primitive | Yield {
875
+ const value = this[args]()
876
+ const cont = fiber.getCont(successCont)
877
+ return cont ? cont[successCont](value, fiber) : fiber.yieldWith(exitSucceed(value))
878
+ }
879
+ })
539
880
 
540
881
  /**
541
- * @since 3.4.6
882
+ * Lazily creates a `Micro` effect from the given side-effect.
883
+ *
884
+ * @since 3.4.0
542
885
  * @experimental
543
- * @category MicroExit
886
+ * @category constructors
544
887
  */
545
- export const exitVoid: MicroExit<void> = exitSucceed(void 0)
546
-
547
- // ----------------------------------------------------------------------------
548
- // env
549
- // ----------------------------------------------------------------------------
888
+ export const suspend: <A, E, R>(evaluate: LazyArg<Micro<A, E, R>>) => Micro<A, E, R> = makePrimitive({
889
+ op: "Suspend",
890
+ eval(_fiber) {
891
+ return this[args]()
892
+ }
893
+ })
550
894
 
551
895
  /**
896
+ * Pause the execution of the current `Micro` effect, and resume it on the next
897
+ * scheduler tick.
898
+ *
552
899
  * @since 3.4.0
553
900
  * @experimental
554
- * @category environment
901
+ * @category constructors
555
902
  */
556
- export const EnvTypeId = Symbol.for("effect/Micro/Env")
903
+ export const yieldNowWith: (priority?: number) => Micro<void> = makePrimitive({
904
+ op: "Yield",
905
+ eval(fiber) {
906
+ let resumed = false
907
+ fiber.getRef(CurrentScheduler).scheduleTask(() => {
908
+ if (resumed) return
909
+ fiber.evaluate(exitVoid as any)
910
+ }, this[args] ?? 0)
911
+ return fiber.yieldWith(() => {
912
+ resumed = true
913
+ })
914
+ }
915
+ })
557
916
 
558
917
  /**
918
+ * Pause the execution of the current `Micro` effect, and resume it on the next
919
+ * scheduler tick.
920
+ *
559
921
  * @since 3.4.0
560
922
  * @experimental
561
- * @category environment
923
+ * @category constructors
562
924
  */
563
- export type EnvTypeId = typeof EnvTypeId
925
+ export const yieldNow: Micro<void> = yieldNowWith(0)
564
926
 
565
927
  /**
566
- * @since 3.4.0
928
+ * Creates a `Micro` effect that will succeed with `Option.Some` of the value.
929
+ *
930
+ * @since 3.4.0
567
931
  * @experimental
568
- * @category environment
932
+ * @category constructors
569
933
  */
570
- export interface Env<R> extends Pipeable {
571
- readonly [EnvTypeId]: {
572
- _R: Covariant<R>
573
- }
574
- readonly refs: ReadonlyRecord<string, unknown>
575
- }
576
-
577
- const EnvProto = {
578
- [EnvTypeId]: {
579
- _R: identity
580
- },
581
- pipe() {
582
- return pipeArguments(this, arguments)
583
- }
584
- }
934
+ export const succeedSome = <A>(a: A): Micro<Option.Option<A>> => succeed(Option.some(a))
585
935
 
586
936
  /**
937
+ * Creates a `Micro` effect that will succeed with `Option.None`.
938
+ *
587
939
  * @since 3.4.0
588
940
  * @experimental
589
- * @category environment
941
+ * @category constructors
590
942
  */
591
- export const envMake = <R = never>(
592
- refs: Record<string, unknown>
593
- ): Env<R> => {
594
- const self = Object.create(EnvProto)
595
- self.refs = refs
596
- return self
597
- }
943
+ export const succeedNone: Micro<Option.Option<never>> = succeed(Option.none())
598
944
 
599
945
  /**
946
+ * Creates a `Micro` effect that will fail with the lazily evaluated `MicroCause`.
947
+ *
600
948
  * @since 3.4.0
601
949
  * @experimental
602
- * @category environment
950
+ * @category constructors
603
951
  */
604
- export const envUnsafeMakeEmpty = (): Env<never> => {
605
- const controller = new AbortController()
606
- const refs = Object.create(null)
607
- refs[currentAbortController.key] = controller
608
- refs[currentAbortSignal.key] = controller.signal
609
- refs[currentScheduler.key] = new MicroSchedulerDefault()
610
- return envMake(refs)
611
- }
952
+ export const failCauseSync = <E>(evaluate: LazyArg<MicroCause<E>>): Micro<never, E> =>
953
+ suspend(() => failCause(evaluate()))
612
954
 
613
955
  /**
956
+ * Creates a `Micro` effect that will die with the specified error.
957
+ *
958
+ * This will result in a `CauseDie`, where the error is not tracked at
959
+ * the type level.
960
+ *
614
961
  * @since 3.4.0
615
962
  * @experimental
616
- * @category environment
963
+ * @category constructors
617
964
  */
618
- export const envGet: {
619
- /**
620
- * @since 3.4.0
621
- * @experimental
622
- * @category environment
623
- */
624
- <A>(ref: EnvRef<A>): <R>(self: Env<R>) => A
625
- /**
626
- * @since 3.4.0
627
- * @experimental
628
- * @category environment
629
- */
630
- <A, R>(self: Env<R>, ref: EnvRef<A>): A
631
- } = dual(2, <R, A>(self: Env<R>, ref: EnvRef<A>): A => ref.key in self.refs ? (self.refs[ref.key] as A) : ref.initial)
965
+ export const die = (defect: unknown): Micro<never> => exitDie(defect)
966
+
967
+ /**
968
+ * Creates a `Micro` effect that will fail with the lazily evaluated error.
969
+ *
970
+ * This will result in a `CauseFail`, where the error is tracked at the
971
+ * type level.
972
+ *
973
+ * @since 3.4.6
974
+ * @experimental
975
+ * @category constructors
976
+ */
977
+ export const failSync = <E>(error: LazyArg<E>): Micro<never, E> => suspend(() => fail(error()))
632
978
 
633
979
  /**
980
+ * Converts an `Option` into a `Micro` effect, that will fail with
981
+ * `NoSuchElementException` if the option is `None`. Otherwise, it will succeed with the
982
+ * value of the option.
983
+ *
634
984
  * @since 3.4.0
635
985
  * @experimental
636
- * @category environment
986
+ * @category constructors
637
987
  */
638
- export const envSet: {
639
- /**
640
- * @since 3.4.0
641
- * @experimental
642
- * @category environment
643
- */
644
- <A>(ref: EnvRef<A>, value: A): <R>(self: Env<R>) => Env<R>
645
- /**
646
- * @since 3.4.0
647
- * @experimental
648
- * @category environment
649
- */
650
- <A, R>(self: Env<R>, ref: EnvRef<A>, value: A): Env<R>
651
- } = dual(3, <R, A>(self: Env<R>, ref: EnvRef<A>, value: A): Env<R> => {
652
- const refs = Object.assign(Object.create(null), self.refs)
653
- refs[ref.key] = value
654
- return envMake(refs)
655
- })
988
+ export const fromOption = <A>(option: Option.Option<A>): Micro<A, NoSuchElementException> =>
989
+ option._tag === "Some" ? succeed(option.value) : fail(new NoSuchElementException({}))
656
990
 
657
991
  /**
992
+ * Converts an `Either` into a `Micro` effect, that will fail with the left side
993
+ * of the either if it is a `Left`. Otherwise, it will succeed with the right
994
+ * side of the either.
995
+ *
658
996
  * @since 3.4.0
659
997
  * @experimental
660
- * @category environment
998
+ * @category constructors
661
999
  */
662
- export const envMutate: {
1000
+ export const fromEither = <R, L>(either: Either.Either<R, L>): Micro<R, L> =>
1001
+ either._tag === "Right" ? succeed(either.right) : fail(either.left)
1002
+
1003
+ const void_: Micro<void> = succeed(void 0)
1004
+ export {
663
1005
  /**
1006
+ * A `Micro` effect that will succeed with `void` (`undefined`).
1007
+ *
664
1008
  * @since 3.4.0
665
1009
  * @experimental
666
- * @category environment
1010
+ * @category constructors
667
1011
  */
668
- (f: (map: Record<string, unknown>) => void): <R>(self: Env<R>) => Env<R>
1012
+ void_ as void
1013
+ }
1014
+
1015
+ const try_ = <A, E>(options: {
1016
+ try: LazyArg<A>
1017
+ catch: (error: unknown) => E
1018
+ }): Micro<A, E> =>
1019
+ suspend(() => {
1020
+ try {
1021
+ return succeed(options.try())
1022
+ } catch (err) {
1023
+ return fail(options.catch(err))
1024
+ }
1025
+ })
1026
+ export {
669
1027
  /**
1028
+ * The `Micro` equivalent of a try / catch block, which allows you to map
1029
+ * thrown errors to a specific error type.
1030
+ *
670
1031
  * @since 3.4.0
671
1032
  * @experimental
672
- * @category environment
1033
+ * @category constructors
1034
+ * @example
1035
+ * ```ts
1036
+ * import { Micro } from "effect"
1037
+ *
1038
+ * Micro.try({
1039
+ * try: () => throw new Error("boom"),
1040
+ * catch: (cause) => new Error("caught", { cause })
1041
+ * })
1042
+ * ```
673
1043
  */
674
- <R>(self: Env<R>, f: (map: Record<string, unknown>) => void): Env<R>
675
- } = dual(
676
- 2,
677
- <R>(self: Env<R>, f: (map: Record<string, unknown>) => ReadonlyRecord<string, unknown>): Env<R> =>
678
- envMake(f(Object.assign(Object.create(null), self.refs)))
679
- )
1044
+ try_ as try
1045
+ }
680
1046
 
681
1047
  /**
682
- * Access the given `Context.Tag` from the environment.
1048
+ * Wrap a `Promise` into a `Micro` effect. Any errors will result in a
1049
+ * `CauseDie`.
683
1050
  *
684
1051
  * @since 3.4.0
685
1052
  * @experimental
686
- * @category environment
1053
+ * @category constructors
687
1054
  */
688
- export const service = <I, S>(tag: Context.Tag<I, S>): Micro<S, never, I> =>
689
- make(function(env, onExit) {
690
- onExit(exitSucceed(Context.get(envGet(env, currentContext) as Context.Context<I>, tag as any) as S))
691
- })
1055
+ export const promise = <A>(evaluate: (signal: AbortSignal) => PromiseLike<A>): Micro<A> =>
1056
+ asyncOptions<A>(function(resume, signal) {
1057
+ evaluate(signal!).then(
1058
+ (a) => resume(succeed(a)),
1059
+ (e) => resume(die(e))
1060
+ )
1061
+ }, evaluate.length !== 0)
692
1062
 
693
1063
  /**
694
- * Access the given `Context.Tag` from the environment, without tracking the
695
- * dependency at the type level.
1064
+ * Wrap a `Promise` into a `Micro` effect. Any errors will be caught and
1065
+ * converted into a specific error type.
696
1066
  *
697
- * It will return an `Option` of the service, depending on whether it is
698
- * available in the environment or not.
1067
+ * @since 3.4.0
1068
+ * @experimental
1069
+ * @category constructors
1070
+ * @example
1071
+ * ```ts
1072
+ * import { Micro } from "effect"
1073
+ *
1074
+ * Micro.tryPromise({
1075
+ * try: () => Promise.resolve("success"),
1076
+ * catch: (cause) => new Error("caught", { cause })
1077
+ * })
1078
+ * ```
1079
+ */
1080
+ export const tryPromise = <A, E>(options: {
1081
+ readonly try: (signal: AbortSignal) => PromiseLike<A>
1082
+ readonly catch: (error: unknown) => E
1083
+ }): Micro<A, E> =>
1084
+ asyncOptions<A, E>(function(resume, signal) {
1085
+ try {
1086
+ options.try(signal!).then(
1087
+ (a) => resume(succeed(a)),
1088
+ (e) => resume(fail(options.catch(e)))
1089
+ )
1090
+ } catch (err) {
1091
+ resume(fail(options.catch(err)))
1092
+ }
1093
+ }, options.try.length !== 0)
1094
+
1095
+ /**
1096
+ * Create a `Micro` effect using the current `Fiber`.
699
1097
  *
700
1098
  * @since 3.4.0
701
1099
  * @experimental
702
- * @category environment
1100
+ * @category constructors
703
1101
  */
704
- export const serviceOption = <I, S>(tag: Context.Tag<I, S>): Micro<Option.Option<S>> =>
705
- make(function(env, onExit) {
706
- onExit(exitSucceed(Context.getOption(envGet(env, currentContext) as Context.Context<I>, tag)))
707
- })
1102
+ export const withFiber: <A, E = never, R = never>(
1103
+ evaluate: (fiber: FiberImpl<A, E>) => Micro<A, E, R>
1104
+ ) => Micro<A, E, R> = makePrimitive({
1105
+ op: "WithFiber",
1106
+ eval(fiber) {
1107
+ return this[args](fiber)
1108
+ }
1109
+ })
708
1110
 
709
1111
  /**
710
- * Retrieve the current value of the given `EnvRef`.
1112
+ * Flush any yielded effects that are waiting to be executed.
711
1113
  *
712
1114
  * @since 3.4.0
713
1115
  * @experimental
714
- * @category environment
1116
+ * @category constructors
715
1117
  */
716
- export const getEnvRef = <A>(envRef: EnvRef<A>): Micro<A> =>
717
- make((env, onExit) => onExit(Either.right(envGet(env, envRef))))
1118
+ export const yieldFlush: Micro<void> = withFiber((fiber) => {
1119
+ fiber.getRef(CurrentScheduler).flush()
1120
+ return exitVoid
1121
+ })
1122
+
1123
+ const asyncOptions: <A, E = never, R = never>(
1124
+ register: (
1125
+ resume: (effect: Micro<A, E, R>) => void,
1126
+ signal?: AbortSignal
1127
+ ) => void | Micro<void, never, R>,
1128
+ withSignal: boolean
1129
+ ) => Micro<A, E, R> = makePrimitive({
1130
+ op: "Async",
1131
+ single: false,
1132
+ eval(fiber) {
1133
+ const register = this[args][0]
1134
+ let resumed = false
1135
+ let yielded: boolean | Primitive = false
1136
+ const controller = this[args][1] ? new AbortController() : undefined
1137
+ const onCancel = register((effect) => {
1138
+ if (resumed) return
1139
+ resumed = true
1140
+ if (yielded) {
1141
+ fiber.evaluate(effect as any)
1142
+ } else {
1143
+ yielded = effect as any
1144
+ }
1145
+ }, controller?.signal)
1146
+ if (yielded !== false) return yielded
1147
+ yielded = true
1148
+ fiber._yielded = () => {
1149
+ resumed = true
1150
+ }
1151
+ if (controller === undefined && onCancel === undefined) {
1152
+ return Yield
1153
+ }
1154
+ fiber._stack.push(asyncFinalizer(() => {
1155
+ resumed = true
1156
+ controller?.abort()
1157
+ return onCancel ?? exitVoid
1158
+ }))
1159
+ return Yield
1160
+ }
1161
+ })
1162
+ const asyncFinalizer: (onInterrupt: () => Micro<void, any, any>) => Primitive = makePrimitive({
1163
+ op: "AsyncFinalizer",
1164
+ ensure(fiber) {
1165
+ if (fiber.interruptible) {
1166
+ fiber.interruptible = false
1167
+ fiber._stack.push(setInterruptible(true))
1168
+ }
1169
+ },
1170
+ contE(cause, _fiber) {
1171
+ return causeIsInterrupt(cause)
1172
+ ? flatMap(this[args](), () => failCause(cause))
1173
+ : failCause(cause)
1174
+ }
1175
+ })
718
1176
 
719
1177
  /**
720
- * Set the value of the given `EnvRef` for the duration of the effect.
1178
+ * Create a `Micro` effect from an asynchronous computation.
1179
+ *
1180
+ * You can return a cleanup effect that will be run when the effect is aborted.
1181
+ * It is also passed an `AbortSignal` that is triggered when the effect is
1182
+ * aborted.
721
1183
  *
722
1184
  * @since 3.4.0
723
1185
  * @experimental
724
- * @category environment
1186
+ * @category constructors
725
1187
  */
726
- export const locally: {
727
- /**
728
- * Set the value of the given `EnvRef` for the duration of the effect.
729
- *
730
- * @since 3.4.0
731
- * @experimental
732
- * @category environment
733
- */
734
- <A>(fiberRef: EnvRef<A>, value: A): <XA, E, R>(self: Micro<XA, E, R>) => Micro<XA, E, R>
735
- /**
736
- * Set the value of the given `EnvRef` for the duration of the effect.
737
- *
738
- * @since 3.4.0
739
- * @experimental
740
- * @category environment
741
- */
742
- <XA, E, R, A>(self: Micro<XA, E, R>, fiberRef: EnvRef<A>, value: A): Micro<XA, E, R>
743
- } = dual(
744
- 3,
745
- <XA, E, R, A>(self: Micro<XA, E, R>, fiberRef: EnvRef<A>, value: A): Micro<XA, E, R> =>
746
- make((env, onExit) => self[runSymbol](envSet(env, fiberRef, value), onExit))
747
- )
1188
+ export const async = <A, E = never, R = never>(
1189
+ register: (
1190
+ resume: (effect: Micro<A, E, R>) => void,
1191
+ signal: AbortSignal
1192
+ ) => void | Micro<void, never, R>
1193
+ ): Micro<A, E, R> => asyncOptions(register as any, register.length >= 2)
748
1194
 
749
1195
  /**
750
- * Access the current `Context` from the environment.
1196
+ * A `Micro` that will never succeed or fail. It wraps `setInterval` to prevent
1197
+ * the Javascript runtime from exiting.
751
1198
  *
752
1199
  * @since 3.4.0
753
1200
  * @experimental
754
- * @category environment
1201
+ * @category constructors
755
1202
  */
756
- export const context = <R>(): Micro<Context.Context<R>> => getEnvRef(currentContext) as any
1203
+ export const never: Micro<never> = async<never>(function() {
1204
+ const interval = setInterval(constVoid, 2147483646)
1205
+ return sync(() => clearInterval(interval))
1206
+ })
757
1207
 
758
1208
  /**
759
- * Merge the given `Context` with the current context.
1209
+ * @since 3.4.0
1210
+ * @experimental
1211
+ * @category constructors
1212
+ */
1213
+ export const gen = <Self, Eff extends YieldWrap<Micro<any, any, any>>, AEff>(
1214
+ ...args:
1215
+ | [self: Self, body: (this: Self) => Generator<Eff, AEff, never>]
1216
+ | [body: () => Generator<Eff, AEff, never>]
1217
+ ): Micro<
1218
+ AEff,
1219
+ [Eff] extends [never] ? never : [Eff] extends [YieldWrap<Micro<infer _A, infer E, infer _R>>] ? E : never,
1220
+ [Eff] extends [never] ? never : [Eff] extends [YieldWrap<Micro<infer _A, infer _E, infer R>>] ? R : never
1221
+ > => suspend(() => fromIterator(args.length === 1 ? args[0]() : args[1].call(args[0]) as any))
1222
+
1223
+ const fromIterator: (
1224
+ iterator: Iterator<any, YieldWrap<Micro<any, any, any>>>
1225
+ ) => Micro<any, any, any> = makePrimitive({
1226
+ op: "Iterator",
1227
+ contA(value, fiber) {
1228
+ const state = this[args].next(value)
1229
+ if (state.done) return succeed(state.value)
1230
+ fiber._stack.push(this)
1231
+ return yieldWrapGet(state.value)
1232
+ },
1233
+ eval(this: any, fiber: FiberImpl) {
1234
+ return this[successCont](undefined, fiber)
1235
+ }
1236
+ })
1237
+
1238
+ // ----------------------------------------------------------------------------
1239
+ // mapping & sequencing
1240
+ // ----------------------------------------------------------------------------
1241
+
1242
+ /**
1243
+ * Create a `Micro` effect that will replace the success value of the given
1244
+ * effect.
760
1245
  *
761
1246
  * @since 3.4.0
762
1247
  * @experimental
763
- * @category environment
1248
+ * @category mapping & sequencing
764
1249
  */
765
- export const provideContext: {
1250
+ export const as: {
1251
+ // ----------------------------------------------------------------------------
1252
+ // mapping & sequencing
1253
+ // ----------------------------------------------------------------------------
1254
+
766
1255
  /**
767
- * Merge the given `Context` with the current context.
1256
+ * Create a `Micro` effect that will replace the success value of the given
1257
+ * effect.
768
1258
  *
769
1259
  * @since 3.4.0
770
1260
  * @experimental
771
- * @category environment
1261
+ * @category mapping & sequencing
772
1262
  */
773
- <XR>(context: Context.Context<XR>): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E, Exclude<R, XR>>
1263
+ <A, B>(value: B): <E, R>(self: Micro<A, E, R>) => Micro<B, E, R>
1264
+ // ----------------------------------------------------------------------------
1265
+ // mapping & sequencing
1266
+ // ----------------------------------------------------------------------------
1267
+
774
1268
  /**
775
- * Merge the given `Context` with the current context.
1269
+ * Create a `Micro` effect that will replace the success value of the given
1270
+ * effect.
776
1271
  *
777
1272
  * @since 3.4.0
778
1273
  * @experimental
779
- * @category environment
1274
+ * @category mapping & sequencing
780
1275
  */
781
- <A, E, R, XR>(self: Micro<A, E, R>, context: Context.Context<XR>): Micro<A, E, Exclude<R, XR>>
782
- } = dual(
783
- 2,
784
- <A, E, R, XR>(self: Micro<A, E, R>, provided: Context.Context<XR>): Micro<A, E, Exclude<R, XR>> =>
785
- make(function(env, onExit) {
786
- const context = envGet(env, currentContext)
787
- const nextEnv = envSet(env, currentContext, Context.merge(context, provided))
788
- self[runSymbol](nextEnv, onExit)
789
- })
790
- )
1276
+ <A, E, R, B>(self: Micro<A, E, R>, value: B): Micro<B, E, R>
1277
+ } = dual(2, <A, E, R, B>(self: Micro<A, E, R>, value: B): Micro<B, E, R> => map(self, (_) => value))
791
1278
 
792
1279
  /**
793
- * Add the provided service to the current context.
1280
+ * Wrap the success value of this `Micro` effect in an `Option.Some`.
794
1281
  *
795
1282
  * @since 3.4.0
796
1283
  * @experimental
797
- * @category environment
1284
+ * @category mapping & sequencing
798
1285
  */
799
- export const provideService: {
1286
+ export const asSome = <A, E, R>(self: Micro<A, E, R>): Micro<Option.Option<A>, E, R> => map(self, Option.some)
1287
+
1288
+ /**
1289
+ * Swap the error and success types of the `Micro` effect.
1290
+ *
1291
+ * @since 3.4.0
1292
+ * @experimental
1293
+ * @category mapping & sequencing
1294
+ */
1295
+ export const flip = <A, E, R>(self: Micro<A, E, R>): Micro<E, A, R> =>
1296
+ matchEffect(self, {
1297
+ onFailure: succeed,
1298
+ onSuccess: fail
1299
+ })
1300
+
1301
+ /**
1302
+ * A more flexible version of `flatMap`, that combines `map` and `flatMap` into
1303
+ * a single api.
1304
+ *
1305
+ * It also allows you to pass in a `Micro` effect directly, which will be
1306
+ * executed after the current effect.
1307
+ *
1308
+ * @since 3.4.0
1309
+ * @experimental
1310
+ * @category mapping & sequencing
1311
+ */
1312
+ export const andThen: {
800
1313
  /**
801
- * Add the provided service to the current context.
1314
+ * A more flexible version of `flatMap`, that combines `map` and `flatMap` into
1315
+ * a single api.
1316
+ *
1317
+ * It also allows you to pass in a `Micro` effect directly, which will be
1318
+ * executed after the current effect.
802
1319
  *
803
1320
  * @since 3.4.0
804
1321
  * @experimental
805
- * @category environment
1322
+ * @category mapping & sequencing
806
1323
  */
807
- <I, S>(tag: Context.Tag<I, S>, service: S): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E, Exclude<R, I>>
1324
+ <A, X>(f: (a: A) => X): <E, R>(
1325
+ self: Micro<A, E, R>
1326
+ ) => [X] extends [Micro<infer A1, infer E1, infer R1>] ? Micro<A1, E | E1, R | R1>
1327
+ : Micro<X, E, R>
808
1328
  /**
809
- * Add the provided service to the current context.
1329
+ * A more flexible version of `flatMap`, that combines `map` and `flatMap` into
1330
+ * a single api.
1331
+ *
1332
+ * It also allows you to pass in a `Micro` effect directly, which will be
1333
+ * executed after the current effect.
810
1334
  *
811
1335
  * @since 3.4.0
812
1336
  * @experimental
813
- * @category environment
1337
+ * @category mapping & sequencing
814
1338
  */
815
- <A, E, R, I, S>(self: Micro<A, E, R>, tag: Context.Tag<I, S>, service: S): Micro<A, E, Exclude<R, I>>
816
- } = dual(
817
- 3,
818
- <A, E, R, I, S>(self: Micro<A, E, R>, tag: Context.Tag<I, S>, service: S): Micro<A, E, Exclude<R, I>> =>
819
- make(function(env, onExit) {
820
- const context = envGet(env, currentContext)
821
- const nextEnv = envSet(env, currentContext, Context.add(context, tag, service))
822
- self[runSymbol](nextEnv, onExit)
823
- })
824
- )
825
-
826
- /**
827
- * Create a service using the provided `Micro` effect, and add it to the
828
- * current context.
829
- *
830
- * @since 3.4.6
831
- * @experimental
832
- * @category environment
833
- */
834
- export const provideServiceEffect: {
1339
+ <X>(f: NotFunction<X>): <A, E, R>(
1340
+ self: Micro<A, E, R>
1341
+ ) => [X] extends [Micro<infer A1, infer E1, infer R1>] ? Micro<A1, E | E1, R | R1>
1342
+ : Micro<X, E, R>
835
1343
  /**
836
- * Create a service using the provided `Micro` effect, and add it to the
837
- * current context.
1344
+ * A more flexible version of `flatMap`, that combines `map` and `flatMap` into
1345
+ * a single api.
838
1346
  *
839
- * @since 3.4.6
1347
+ * It also allows you to pass in a `Micro` effect directly, which will be
1348
+ * executed after the current effect.
1349
+ *
1350
+ * @since 3.4.0
840
1351
  * @experimental
841
- * @category environment
1352
+ * @category mapping & sequencing
842
1353
  */
843
- <I, S, E2, R2>(
844
- tag: Context.Tag<I, S>,
845
- acquire: Micro<S, E2, R2>
846
- ): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E | E2, Exclude<R, I> | R2>
1354
+ <A, E, R, X>(
1355
+ self: Micro<A, E, R>,
1356
+ f: (a: A) => X
1357
+ ): [X] extends [Micro<infer A1, infer E1, infer R1>] ? Micro<A1, E | E1, R | R1>
1358
+ : Micro<X, E, R>
847
1359
  /**
848
- * Create a service using the provided `Micro` effect, and add it to the
849
- * current context.
1360
+ * A more flexible version of `flatMap`, that combines `map` and `flatMap` into
1361
+ * a single api.
850
1362
  *
851
- * @since 3.4.6
1363
+ * It also allows you to pass in a `Micro` effect directly, which will be
1364
+ * executed after the current effect.
1365
+ *
1366
+ * @since 3.4.0
852
1367
  * @experimental
853
- * @category environment
1368
+ * @category mapping & sequencing
854
1369
  */
855
- <A, E, R, I, S, E2, R2>(
1370
+ <A, E, R, X>(
856
1371
  self: Micro<A, E, R>,
857
- tag: Context.Tag<I, S>,
858
- acquire: Micro<S, E2, R2>
859
- ): Micro<A, E | E2, Exclude<R, I> | R2>
1372
+ f: NotFunction<X>
1373
+ ): [X] extends [Micro<infer A1, infer E1, infer R1>] ? Micro<A1, E | E1, R | R1>
1374
+ : Micro<X, E, R>
860
1375
  } = dual(
861
- 3,
862
- <A, E, R, I, S, E2, R2>(
863
- self: Micro<A, E, R>,
864
- tag: Context.Tag<I, S>,
865
- acquire: Micro<S, E2, R2>
866
- ): Micro<A, E | E2, Exclude<R, I> | R2> => flatMap(acquire, (service) => provideService(self, tag, service))
1376
+ 2,
1377
+ <A, E, R, B, E2, R2>(self: Micro<A, E, R>, f: any): Micro<B, E | E2, R | R2> =>
1378
+ flatMap(self, (a) => {
1379
+ const value = isMicro(f) ? f : typeof f === "function" ? f(a) : f
1380
+ return isMicro(value) ? value : succeed(value)
1381
+ })
867
1382
  )
868
1383
 
869
- // ----------------------------------------------------------------------------
870
- // scheduler
871
- // ----------------------------------------------------------------------------
872
-
873
- /**
874
- * @since 3.5.9
875
- * @experimental
876
- * @category scheduler
877
- */
878
- export interface MicroScheduler {
879
- readonly scheduleTask: (task: () => void, priority: number) => void
880
- readonly shouldYield: (env: Env<unknown>) => boolean
881
- readonly flush: () => void
882
- }
883
-
884
- const setImmediate = "setImmediate" in globalThis ? globalThis.setImmediate : (f: () => void) => setTimeout(f, 0)
885
-
886
1384
  /**
887
- * @since 3.5.9
1385
+ * Execute a side effect from the success value of the `Micro` effect.
1386
+ *
1387
+ * It is similar to the `andThen` api, but the success value is ignored.
1388
+ *
1389
+ * @since 3.4.0
888
1390
  * @experimental
889
- * @category scheduler
1391
+ * @category mapping & sequencing
890
1392
  */
891
- export class MicroSchedulerDefault implements MicroScheduler {
892
- private tasks: Array<() => void> = []
893
- private running = false
894
-
895
- /**
896
- * @since 3.5.9
897
- */
898
- scheduleTask(task: () => void, _priority: number) {
899
- this.tasks.push(task)
900
- if (!this.running) {
901
- this.running = true
902
- setImmediate(this.afterScheduled)
903
- }
904
- }
905
-
906
- /**
907
- * @since 3.5.9
908
- */
909
- afterScheduled = () => {
910
- this.running = false
911
- this.runTasks()
912
- }
913
-
914
- /**
915
- * @since 3.5.9
916
- */
917
- runTasks() {
918
- const tasks = this.tasks
919
- this.tasks = []
920
- for (let i = 0, len = tasks.length; i < len; i++) {
921
- tasks[i]()
922
- }
923
- }
924
-
1393
+ export const tap: {
925
1394
  /**
926
- * @since 3.5.9
1395
+ * Execute a side effect from the success value of the `Micro` effect.
1396
+ *
1397
+ * It is similar to the `andThen` api, but the success value is ignored.
1398
+ *
1399
+ * @since 3.4.0
1400
+ * @experimental
1401
+ * @category mapping & sequencing
927
1402
  */
928
- shouldYield(_env: Env<unknown>) {
929
- return false
930
- }
931
-
1403
+ <A, X>(f: (a: NoInfer<A>) => X): <E, R>(
1404
+ self: Micro<A, E, R>
1405
+ ) => [X] extends [Micro<infer _A1, infer E1, infer R1>] ? Micro<A, E | E1, R | R1>
1406
+ : Micro<A, E, R>
932
1407
  /**
933
- * @since 3.5.9
1408
+ * Execute a side effect from the success value of the `Micro` effect.
1409
+ *
1410
+ * It is similar to the `andThen` api, but the success value is ignored.
1411
+ *
1412
+ * @since 3.4.0
1413
+ * @experimental
1414
+ * @category mapping & sequencing
934
1415
  */
935
- flush() {
936
- while (this.tasks.length > 0) {
937
- this.runTasks()
938
- }
939
- }
940
- }
941
-
942
- // ========================================================================
943
- // Env refs
944
- // ========================================================================
945
-
946
- /**
947
- * @since 3.4.0
948
- * @experimental
949
- * @category environment
950
- */
951
- export const EnvRefTypeId: unique symbol = Symbol.for("effect/Micro/EnvRef")
952
-
953
- /**
954
- * @since 3.4.0
955
- * @experimental
956
- * @category environment
957
- */
958
- export type EnvRefTypeId = typeof EnvRefTypeId
959
-
960
- /**
961
- * @since 3.4.0
962
- * @experimental
963
- * @category environment
964
- */
965
- export interface EnvRef<A> extends Micro<A> {
966
- readonly [EnvRefTypeId]: EnvRefTypeId
967
- readonly key: string
968
- readonly initial: A
969
-
970
- [Unify.typeSymbol]?: unknown
971
- [Unify.unifySymbol]?: EnvRefUnify<this>
972
- [Unify.ignoreSymbol]?: EnvRefUnifyIgnore
973
- }
974
-
975
- /**
976
- * @category models
977
- * @since 3.8.4
978
- * @experimental
979
- */
980
- export interface EnvRefUnify<A extends { [Unify.typeSymbol]?: any }> extends MicroUnify<A> {
981
- EnvRef?: () => A[Unify.typeSymbol] extends EnvRef<infer A0> | infer _ ? EnvRef<A0> : never
982
- }
983
-
984
- /**
985
- * @category models
986
- * @since 3.8.4
987
- * @experimental
988
- */
989
- export interface EnvRefUnifyIgnore extends MicroUnifyIgnore {
990
- Micro?: true
991
- }
992
-
993
- const EnvRefProto: ThisType<EnvRef<any>> = {
994
- ...MicroProto,
995
- [EnvRefTypeId]: EnvRefTypeId,
996
- [runSymbol](env: Env<any>, onExit: (exit: MicroExit<any, any>) => void) {
997
- getEnvRef(this)[runSymbol](env, onExit)
998
- }
999
- }
1000
-
1001
- /**
1002
- * @since 3.4.0
1003
- * @experimental
1004
- * @category environment refs
1005
- */
1006
- export const envRefMake = <A>(key: string, initial: LazyArg<A>): EnvRef<A> =>
1007
- globalValue(key, () => {
1008
- const self = Object.create(EnvRefProto)
1009
- self.key = key
1010
- self.initial = initial()
1011
- return self
1012
- })
1013
-
1014
- /**
1015
- * @since 3.4.0
1016
- * @experimental
1017
- * @category environment refs
1018
- */
1019
- export const currentAbortController: EnvRef<AbortController> = envRefMake(
1020
- "effect/Micro/currentAbortController",
1021
- () => undefined as any
1022
- )
1023
-
1024
- /**
1025
- * @since 3.4.0
1026
- * @experimental
1027
- * @category environment refs
1028
- */
1029
- export const currentAbortSignal: EnvRef<AbortSignal> = envRefMake(
1030
- "effect/Micro/currentAbortSignal",
1031
- () => undefined as any
1032
- )
1033
-
1034
- /**
1035
- * @since 3.4.0
1036
- * @experimental
1037
- * @category environment refs
1038
- */
1039
- export const currentContext: EnvRef<Context.Context<never>> = envRefMake(
1040
- "effect/Micro/currentContext",
1041
- () => Context.empty()
1042
- )
1043
-
1044
- /**
1045
- * @since 3.4.0
1046
- * @experimental
1047
- * @category environment refs
1048
- */
1049
- export const currentConcurrency: EnvRef<"unbounded" | number> = envRefMake(
1050
- "effect/Micro/currentConcurrency",
1051
- () => "unbounded"
1052
- )
1053
-
1054
- /**
1055
- * @since 3.4.0
1056
- * @experimental
1057
- * @category environment refs
1058
- */
1059
- export const currentMaxDepthBeforeYield: EnvRef<number> = envRefMake(
1060
- "effect/Micro/currentMaxDepthBeforeYield",
1061
- () => 2048
1062
- )
1063
-
1064
- const currentInterruptible: EnvRef<boolean> = envRefMake(
1065
- "effect/Micro/currentInterruptible",
1066
- () => true
1067
- )
1068
-
1069
- /**
1070
- * @since 3.4.0
1071
- * @experimental
1072
- * @category environment refs
1073
- */
1074
- export const currentScheduler: EnvRef<MicroScheduler> = envRefMake(
1075
- "effect/Micro/currentScheduler",
1076
- () => new MicroSchedulerDefault()
1077
- )
1078
-
1079
- /**
1080
- * If you have a `Micro` that uses `concurrency: "inherit"`, you can use this
1081
- * api to control the concurrency of that `Micro` when it is run.
1082
- *
1083
- * @since 3.4.0
1084
- * @experimental
1085
- * @category environment refs
1086
- * @example
1087
- * import * as Micro from "effect/Micro"
1088
- *
1089
- * Micro.forEach([1, 2, 3], (n) => Micro.succeed(n), {
1090
- * concurrency: "inherit"
1091
- * }).pipe(
1092
- * Micro.withConcurrency(2) // use a concurrency of 2
1093
- * )
1094
- */
1095
- export const withConcurrency: {
1416
+ <X>(f: NotFunction<X>): <A, E, R>(
1417
+ self: Micro<A, E, R>
1418
+ ) => [X] extends [Micro<infer _A1, infer E1, infer R1>] ? Micro<A, E | E1, R | R1>
1419
+ : Micro<A, E, R>
1096
1420
  /**
1097
- * If you have a `Micro` that uses `concurrency: "inherit"`, you can use this
1098
- * api to control the concurrency of that `Micro` when it is run.
1421
+ * Execute a side effect from the success value of the `Micro` effect.
1422
+ *
1423
+ * It is similar to the `andThen` api, but the success value is ignored.
1099
1424
  *
1100
1425
  * @since 3.4.0
1101
1426
  * @experimental
1102
- * @category environment refs
1103
- * @example
1104
- * import * as Micro from "effect/Micro"
1105
- *
1106
- * Micro.forEach([1, 2, 3], (n) => Micro.succeed(n), {
1107
- * concurrency: "inherit"
1108
- * }).pipe(
1109
- * Micro.withConcurrency(2) // use a concurrency of 2
1110
- * )
1427
+ * @category mapping & sequencing
1111
1428
  */
1112
- (concurrency: "unbounded" | number): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E, R>
1429
+ <A, E, R, X>(
1430
+ self: Micro<A, E, R>,
1431
+ f: (a: NoInfer<A>) => X
1432
+ ): [X] extends [Micro<infer _A1, infer E1, infer R1>] ? Micro<A, E | E1, R | R1>
1433
+ : Micro<A, E, R>
1113
1434
  /**
1114
- * If you have a `Micro` that uses `concurrency: "inherit"`, you can use this
1115
- * api to control the concurrency of that `Micro` when it is run.
1435
+ * Execute a side effect from the success value of the `Micro` effect.
1436
+ *
1437
+ * It is similar to the `andThen` api, but the success value is ignored.
1116
1438
  *
1117
1439
  * @since 3.4.0
1118
1440
  * @experimental
1119
- * @category environment refs
1120
- * @example
1121
- * import * as Micro from "effect/Micro"
1122
- *
1123
- * Micro.forEach([1, 2, 3], (n) => Micro.succeed(n), {
1124
- * concurrency: "inherit"
1125
- * }).pipe(
1126
- * Micro.withConcurrency(2) // use a concurrency of 2
1127
- * )
1441
+ * @category mapping & sequencing
1128
1442
  */
1129
- <A, E, R>(self: Micro<A, E, R>, concurrency: "unbounded" | number): Micro<A, E, R>
1443
+ <A, E, R, X>(
1444
+ self: Micro<A, E, R>,
1445
+ f: NotFunction<X>
1446
+ ): [X] extends [Micro<infer _A1, infer E1, infer R1>] ? Micro<A, E | E1, R | R1>
1447
+ : Micro<A, E, R>
1130
1448
  } = dual(
1131
1449
  2,
1132
- <A, E, R>(self: Micro<A, E, R>, concurrency: "unbounded" | number): Micro<A, E, R> =>
1133
- locally(self, currentConcurrency, concurrency)
1450
+ <A, E, R, B, E2, R2>(self: Micro<A, E, R>, f: (a: A) => Micro<B, E2, R2>): Micro<A, E | E2, R | R2> =>
1451
+ flatMap(self, (a) => {
1452
+ const value = isMicro(f) ? f : typeof f === "function" ? f(a) : f
1453
+ return isMicro(value) ? as(value, a) : succeed(a)
1454
+ })
1134
1455
  )
1135
1456
 
1136
- // ----------------------------------------------------------------------------
1137
- // constructors
1138
- // ----------------------------------------------------------------------------
1139
-
1140
- const microDepthState = globalValue("effect/Micro/microDepthState", () => ({
1141
- depth: 0,
1142
- maxDepthBeforeYield: currentMaxDepthBeforeYield.initial
1143
- }))
1144
-
1145
- const unsafeMake = <R, A, E>(
1146
- run: (env: Env<R>, onExit: (exit: MicroExit<A, E>) => void) => void
1147
- ): Micro<A, E, R> => {
1148
- const self = Object.create(MicroProto)
1149
- self[runSymbol] = run
1150
- return self
1151
- }
1152
-
1153
- const unsafeMakeOptions = <R, A, E>(
1154
- run: (env: Env<R>, onExit: (exit: MicroExit<A, E>) => void) => void,
1155
- checkAbort: boolean
1156
- ): Micro<A, E, R> =>
1157
- unsafeMake(function execute(env, onExit) {
1158
- if (
1159
- checkAbort && env.refs[currentInterruptible.key] !== false &&
1160
- (env.refs[currentAbortSignal.key] as AbortSignal).aborted
1161
- ) {
1162
- return onExit(exitInterrupt)
1163
- }
1164
- microDepthState.depth++
1165
- if (microDepthState.depth === 1) {
1166
- microDepthState.maxDepthBeforeYield = envGet(env, currentMaxDepthBeforeYield)
1167
- }
1168
- const scheduler = env.refs[currentScheduler.key] as MicroScheduler
1169
- if (microDepthState.depth >= microDepthState.maxDepthBeforeYield || scheduler.shouldYield(env)) {
1170
- scheduler.scheduleTask(() => execute(env, onExit), 0)
1171
- } else {
1172
- try {
1173
- run(env, onExit)
1174
- } catch (err) {
1175
- onExit(exitDie(err))
1176
- }
1177
- }
1178
- microDepthState.depth--
1179
- })
1180
-
1181
1457
  /**
1182
- * A low-level constructor for creating a `Micro` effect. It takes a function
1183
- * that receives an environment and a callback which should be called with the
1184
- * result of the effect.
1458
+ * Replace the success value of the `Micro` effect with `void`.
1185
1459
  *
1186
1460
  * @since 3.4.0
1187
1461
  * @experimental
1188
- * @category constructors
1462
+ * @category mapping & sequencing
1189
1463
  */
1190
- export const make = <R, A, E>(
1191
- run: (env: Env<R>, onExit: (exit: MicroExit<A, E>) => void) => void
1192
- ): Micro<A, E, R> => unsafeMakeOptions(run, true)
1464
+ export const asVoid = <A, E, R>(self: Micro<A, E, R>): Micro<void, E, R> => flatMap(self, (_) => exitVoid)
1193
1465
 
1194
1466
  /**
1195
- * Converts a `MicroExit` into a `Micro` effect.
1467
+ * Access the `MicroExit` of the given `Micro` effect.
1196
1468
  *
1197
1469
  * @since 3.4.6
1198
1470
  * @experimental
1199
- * @category constructors
1471
+ * @category mapping & sequencing
1200
1472
  */
1201
- export const fromExit = <A, E>(self: MicroExit<A, E>): Micro<A, E> =>
1202
- make(function(_env, onExit) {
1203
- onExit(self)
1473
+ export const exit = <A, E, R>(self: Micro<A, E, R>): Micro<MicroExit<A, E>, never, R> =>
1474
+ matchCause(self, {
1475
+ onFailure: exitFailCause,
1476
+ onSuccess: exitSucceed
1204
1477
  })
1205
1478
 
1206
1479
  /**
1207
- * Converts a lazy `MicroExit` into a `Micro` effect.
1480
+ * Replace the error type of the given `Micro` with the full `MicroCause` object.
1208
1481
  *
1209
- * @since 3.4.6
1482
+ * @since 3.4.0
1210
1483
  * @experimental
1211
- * @category constructors
1484
+ * @category mapping & sequencing
1212
1485
  */
1213
- export const fromExitSync = <A, E>(self: LazyArg<MicroExit<A, E>>): Micro<A, E> =>
1214
- make(function(_env, onExit) {
1215
- onExit(self())
1216
- })
1486
+ export const sandbox = <A, E, R>(self: Micro<A, E, R>): Micro<A, MicroCause<E>, R> => catchAllCause(self, fail)
1217
1487
 
1218
1488
  /**
1219
- * Creates a `Micro` effect that will succeed with the specified constant value.
1489
+ * Returns an effect that races all the specified effects,
1490
+ * yielding the value of the first effect to succeed with a value. Losers of
1491
+ * the race will be interrupted immediately
1220
1492
  *
1221
1493
  * @since 3.4.0
1222
1494
  * @experimental
1223
- * @category constructors
1495
+ * @category sequencing
1224
1496
  */
1225
- export const succeed = <A>(a: A): Micro<A> => fromExit(exitSucceed(a))
1497
+ export const raceAll = <Eff extends Micro<any, any, any>>(
1498
+ all: Iterable<Eff>
1499
+ ): Micro<Micro.Success<Eff>, Micro.Error<Eff>, Micro.Context<Eff>> =>
1500
+ withFiber((parent) =>
1501
+ async((resume) => {
1502
+ const effects = Arr.fromIterable(all)
1503
+ const len = effects.length
1504
+ let doneCount = 0
1505
+ let done = false
1506
+ const fibers = new Set<Fiber<any, any>>()
1507
+ const causes: Array<MicroCause<any>> = []
1508
+ const onExit = (exit: MicroExit<any, any>) => {
1509
+ doneCount++
1510
+ if (exit._tag === "Failure") {
1511
+ causes.push(exit.cause)
1512
+ if (doneCount >= len) {
1513
+ resume(failCause(causes[0]))
1514
+ }
1515
+ return
1516
+ }
1517
+ done = true
1518
+ resume(fibers.size === 0 ? exit : flatMap(uninterruptible(fiberInterruptAll(fibers)), () => exit))
1519
+ }
1520
+
1521
+ for (let i = 0; i < len; i++) {
1522
+ if (done) break
1523
+ const fiber = unsafeFork(parent, interruptible(effects[i]), true, true)
1524
+ fibers.add(fiber)
1525
+ fiber.addObserver((exit) => {
1526
+ fibers.delete(fiber)
1527
+ onExit(exit)
1528
+ })
1529
+ }
1530
+
1531
+ return fiberInterruptAll(fibers)
1532
+ })
1533
+ )
1226
1534
 
1227
1535
  /**
1228
- * Creates a `Micro` effect that will succeed with `Option.Some` of the value.
1536
+ * Returns an effect that races all the specified effects,
1537
+ * yielding the value of the first effect to succeed or fail. Losers of
1538
+ * the race will be interrupted immediately
1229
1539
  *
1230
1540
  * @since 3.4.0
1231
1541
  * @experimental
1232
- * @category constructors
1542
+ * @category sequencing
1233
1543
  */
1234
- export const succeedSome = <A>(a: A): Micro<Option.Option<A>> => succeed(Option.some(a))
1544
+ export const raceAllFirst = <Eff extends Micro<any, any, any>>(
1545
+ all: Iterable<Eff>
1546
+ ): Micro<Micro.Success<Eff>, Micro.Error<Eff>, Micro.Context<Eff>> =>
1547
+ withFiber((parent) =>
1548
+ async((resume) => {
1549
+ let done = false
1550
+ const fibers = new Set<Fiber<any, any>>()
1551
+ const onExit = (exit: MicroExit<any, any>) => {
1552
+ done = true
1553
+ resume(fibers.size === 0 ? exit : flatMap(fiberInterruptAll(fibers), () => exit))
1554
+ }
1555
+
1556
+ for (const effect of all) {
1557
+ if (done) break
1558
+ const fiber = unsafeFork(parent, interruptible(effect), true, true)
1559
+ fibers.add(fiber)
1560
+ fiber.addObserver((exit) => {
1561
+ fibers.delete(fiber)
1562
+ onExit(exit)
1563
+ })
1564
+ }
1565
+
1566
+ return fiberInterruptAll(fibers)
1567
+ })
1568
+ )
1235
1569
 
1236
1570
  /**
1237
- * Creates a `Micro` effect that will succeed with `Option.None`.
1571
+ * Returns an effect that races two effects, yielding the value of the first
1572
+ * effect to succeed. Losers of the race will be interrupted immediately
1238
1573
  *
1239
1574
  * @since 3.4.0
1240
1575
  * @experimental
1241
- * @category constructors
1576
+ * @category sequencing
1242
1577
  */
1243
- export const succeedNone: Micro<Option.Option<never>> = succeed(Option.none())
1578
+ export const race: {
1579
+ /**
1580
+ * Returns an effect that races two effects, yielding the value of the first
1581
+ * effect to succeed. Losers of the race will be interrupted immediately
1582
+ *
1583
+ * @since 3.4.0
1584
+ * @experimental
1585
+ * @category sequencing
1586
+ */
1587
+ <A2, E2, R2>(that: Micro<A2, E2, R2>): <A, E, R>(self: Micro<A, E, R>) => Micro<A | A2, E | E2, R | R2>
1588
+ /**
1589
+ * Returns an effect that races two effects, yielding the value of the first
1590
+ * effect to succeed. Losers of the race will be interrupted immediately
1591
+ *
1592
+ * @since 3.4.0
1593
+ * @experimental
1594
+ * @category sequencing
1595
+ */
1596
+ <A, E, R, A2, E2, R2>(self: Micro<A, E, R>, that: Micro<A2, E2, R2>): Micro<A | A2, E | E2, R | R2>
1597
+ } = dual(
1598
+ 2,
1599
+ <A, E, R, A2, E2, R2>(self: Micro<A, E, R>, that: Micro<A2, E2, R2>): Micro<A | A2, E | E2, R | R2> =>
1600
+ raceAll([self, that])
1601
+ )
1244
1602
 
1245
1603
  /**
1246
- * Creates a `Micro` effect that will fail with the specified error.
1604
+ * Returns an effect that races two effects, yielding the value of the first
1605
+ * effect to succeed *or* fail. Losers of the race will be interrupted immediately
1247
1606
  *
1248
- * This will result in a `CauseFail`, where the error is tracked at the
1249
- * type level.
1607
+ * @since 3.4.0
1608
+ * @experimental
1609
+ * @category sequencing
1610
+ */
1611
+ export const raceFirst: {
1612
+ /**
1613
+ * Returns an effect that races two effects, yielding the value of the first
1614
+ * effect to succeed *or* fail. Losers of the race will be interrupted immediately
1615
+ *
1616
+ * @since 3.4.0
1617
+ * @experimental
1618
+ * @category sequencing
1619
+ */
1620
+ <A2, E2, R2>(that: Micro<A2, E2, R2>): <A, E, R>(self: Micro<A, E, R>) => Micro<A | A2, E | E2, R | R2>
1621
+ /**
1622
+ * Returns an effect that races two effects, yielding the value of the first
1623
+ * effect to succeed *or* fail. Losers of the race will be interrupted immediately
1624
+ *
1625
+ * @since 3.4.0
1626
+ * @experimental
1627
+ * @category sequencing
1628
+ */
1629
+ <A, E, R, A2, E2, R2>(self: Micro<A, E, R>, that: Micro<A2, E2, R2>): Micro<A | A2, E | E2, R | R2>
1630
+ } = dual(
1631
+ 2,
1632
+ <A, E, R, A2, E2, R2>(self: Micro<A, E, R>, that: Micro<A2, E2, R2>): Micro<A | A2, E | E2, R | R2> =>
1633
+ raceAllFirst([self, that])
1634
+ )
1635
+
1636
+ /**
1637
+ * Map the success value of this `Micro` effect to another `Micro` effect, then
1638
+ * flatten the result.
1250
1639
  *
1251
1640
  * @since 3.4.0
1252
1641
  * @experimental
1253
- * @category constructors
1642
+ * @category mapping & sequencing
1254
1643
  */
1255
- export const fail = <E>(e: E): Micro<never, E> => fromExit(exitFail(e))
1644
+ export const flatMap: {
1645
+ /**
1646
+ * Map the success value of this `Micro` effect to another `Micro` effect, then
1647
+ * flatten the result.
1648
+ *
1649
+ * @since 3.4.0
1650
+ * @experimental
1651
+ * @category mapping & sequencing
1652
+ */
1653
+ <A, B, E2, R2>(f: (a: A) => Micro<B, E2, R2>): <E, R>(self: Micro<A, E, R>) => Micro<B, E | E2, R | R2>
1654
+ /**
1655
+ * Map the success value of this `Micro` effect to another `Micro` effect, then
1656
+ * flatten the result.
1657
+ *
1658
+ * @since 3.4.0
1659
+ * @experimental
1660
+ * @category mapping & sequencing
1661
+ */
1662
+ <A, E, R, B, E2, R2>(self: Micro<A, E, R>, f: (a: A) => Micro<B, E2, R2>): Micro<B, E | E2, R | R2>
1663
+ } = dual(
1664
+ 2,
1665
+ <A, E, R, B, E2, R2>(
1666
+ self: Micro<A, E, R>,
1667
+ f: (a: A) => Micro<B, E2, R2>
1668
+ ): Micro<B, E | E2, R | R2> => {
1669
+ const onSuccess = Object.create(OnSuccessProto)
1670
+ onSuccess[args] = self
1671
+ onSuccess[successCont] = f
1672
+ return onSuccess
1673
+ }
1674
+ )
1675
+ const OnSuccessProto = makePrimitiveProto({
1676
+ op: "OnSuccess",
1677
+ eval(this: any, fiber: FiberImpl): Primitive {
1678
+ fiber._stack.push(this)
1679
+ return this[args]
1680
+ }
1681
+ })
1682
+
1683
+ // ----------------------------------------------------------------------------
1684
+ // mapping & sequencing
1685
+ // ----------------------------------------------------------------------------
1256
1686
 
1257
1687
  /**
1258
- * Creates a `Micro` effect that will fail with the lazily evaluated error.
1688
+ * Flattens any nested `Micro` effects, merging the error and requirement types.
1259
1689
  *
1260
- * This will result in a `CauseFail`, where the error is tracked at the
1261
- * type level.
1690
+ * @since 3.4.0
1691
+ * @experimental
1692
+ * @category mapping & sequencing
1693
+ */
1694
+ export const flatten = <A, E, R, E2, R2>(
1695
+ self: Micro<Micro<A, E, R>, E2, R2>
1696
+ ): Micro<A, E | E2, R | R2> => flatMap(self, identity)
1697
+
1698
+ /**
1699
+ * Transforms the success value of the `Micro` effect with the specified
1700
+ * function.
1262
1701
  *
1263
1702
  * @since 3.4.0
1264
1703
  * @experimental
1265
- * @category constructors
1704
+ * @category mapping & sequencing
1266
1705
  */
1267
- export const failSync = <E>(e: LazyArg<E>): Micro<never, E> =>
1268
- make(function(_env, onExit) {
1269
- onExit(exitFail(e()))
1270
- })
1706
+ export const map: {
1707
+ /**
1708
+ * Transforms the success value of the `Micro` effect with the specified
1709
+ * function.
1710
+ *
1711
+ * @since 3.4.0
1712
+ * @experimental
1713
+ * @category mapping & sequencing
1714
+ */
1715
+ <A, B>(f: (a: A) => B): <E, R>(self: Micro<A, E, R>) => Micro<B, E, R>
1716
+ /**
1717
+ * Transforms the success value of the `Micro` effect with the specified
1718
+ * function.
1719
+ *
1720
+ * @since 3.4.0
1721
+ * @experimental
1722
+ * @category mapping & sequencing
1723
+ */
1724
+ <A, E, R, B>(self: Micro<A, E, R>, f: (a: A) => B): Micro<B, E, R>
1725
+ } = dual(
1726
+ 2,
1727
+ <A, E, R, B>(self: Micro<A, E, R>, f: (a: A) => B): Micro<B, E, R> => flatMap(self, (a) => succeed(f(a)))
1728
+ )
1729
+
1730
+ // ----------------------------------------------------------------------------
1731
+ // MicroExit
1732
+ // ----------------------------------------------------------------------------
1271
1733
 
1272
1734
  /**
1273
- * Creates a `Micro` effect that will die with the specified error.
1735
+ * The MicroExit type is a data type that represents the result of a Micro
1736
+ * computation.
1274
1737
  *
1275
- * This will result in a `CauseDie`, where the error is not tracked at
1276
- * the type level.
1738
+ * It uses the `Either` data type to represent the success and failure cases.
1277
1739
  *
1278
- * @since 3.4.0
1740
+ * @since 3.4.6
1279
1741
  * @experimental
1280
- * @category constructors
1742
+ * @category MicroExit
1743
+ */
1744
+ export type MicroExit<A, E = never> =
1745
+ | MicroExit.Success<A, E>
1746
+ | MicroExit.Failure<A, E>
1747
+
1748
+ /**
1749
+ * @since 3.4.6
1750
+ * @experimental
1751
+ * @category MicroExit
1281
1752
  */
1282
- export const die = (defect: unknown): Micro<never> => fromExit(exitDie(defect))
1753
+ export declare namespace MicroExit {
1754
+ /**
1755
+ * @since 3.4.6
1756
+ * @experimental
1757
+ * @category MicroExit
1758
+ */
1759
+ export interface Proto<out A, out E = never> extends Micro<A, E> {
1760
+ readonly [MicroExitTypeId]: MicroExitTypeId
1761
+ }
1762
+
1763
+ /**
1764
+ * @since 3.4.6
1765
+ * @experimental
1766
+ * @category MicroExit
1767
+ */
1768
+ export interface Success<out A, out E> extends Proto<A, E> {
1769
+ readonly _tag: "Success"
1770
+ readonly value: A
1771
+ }
1283
1772
 
1284
- /**
1285
- * Creates a `Micro` effect that will fail with the specified `MicroCause`.
1286
- *
1287
- * @since 3.4.6
1288
- * @experimental
1289
- * @category constructors
1290
- */
1291
- export const failCause = <E>(cause: MicroCause<E>): Micro<never, E> => fromExit(exitFailCause(cause))
1773
+ /**
1774
+ * @since 3.4.6
1775
+ * @experimental
1776
+ * @category MicroExit
1777
+ */
1778
+ export interface Failure<out A, out E> extends Proto<A, E> {
1779
+ readonly _tag: "Failure"
1780
+ readonly cause: MicroCause<E>
1781
+ }
1782
+ }
1292
1783
 
1293
1784
  /**
1294
- * Creates a `Micro` effect that will fail with the lazily evaluated `MicroCause`.
1295
- *
1296
1785
  * @since 3.4.6
1297
1786
  * @experimental
1298
- * @category constructors
1787
+ * @category MicroExit
1299
1788
  */
1300
- export const failCauseSync = <E>(cause: LazyArg<MicroCause<E>>): Micro<never, E> =>
1301
- fromExitSync(() => exitFailCause(cause()))
1789
+ export const isMicroExit = (u: unknown): u is MicroExit<unknown, unknown> => hasProperty(u, MicroExitTypeId)
1302
1790
 
1303
1791
  /**
1304
- * Creates a `Micro` effect that will succeed with the lazily evaluated value.
1305
- *
1306
- * If the evaluation of the value throws an error, the effect will fail with
1307
- * `CauseDie`.
1308
- *
1309
- * @since 3.4.0
1792
+ * @since 3.4.6
1310
1793
  * @experimental
1311
- * @category constructors
1794
+ * @category MicroExit
1312
1795
  */
1313
- export const sync = <A>(evaluate: LazyArg<A>): Micro<A> =>
1314
- make(function(_env, onExit) {
1315
- onExit(exitSucceed(evaluate()))
1316
- })
1796
+ export const exitSucceed: <A>(a: A) => MicroExit<A, never> = succeed as any
1317
1797
 
1318
1798
  /**
1319
- * Converts an `Option` into a `Micro` effect, that will fail with
1320
- * `NoSuchElementException` if the option is `None`. Otherwise, it will succeed with the
1321
- * value of the option.
1322
- *
1323
- * @since 3.4.0
1799
+ * @since 3.4.6
1324
1800
  * @experimental
1325
- * @category constructors
1801
+ * @category MicroExit
1326
1802
  */
1327
- export const fromOption = <A>(option: Option.Option<A>): Micro<A, NoSuchElementException> =>
1328
- make(function(_env, onExit) {
1329
- onExit(option._tag === "Some" ? exitSucceed(option.value) : exitFail(new NoSuchElementException({})))
1330
- })
1803
+ export const exitFailCause: <E>(cause: MicroCause<E>) => MicroExit<never, E> = failCause as any
1331
1804
 
1332
1805
  /**
1333
- * Converts an `Either` into a `Micro` effect, that will fail with the left side
1334
- * of the either if it is a `Left`. Otherwise, it will succeed with the right
1335
- * side of the either.
1336
- *
1337
- * @since 3.4.0
1806
+ * @since 3.4.6
1338
1807
  * @experimental
1339
- * @category constructors
1808
+ * @category MicroExit
1340
1809
  */
1341
- export const fromEither = <R, L>(either: Either.Either<R, L>): Micro<R, L> =>
1342
- make(function(_env, onExit) {
1343
- onExit(either._tag === "Right" ? either as MicroExit<R, never> : exitFail(either.left))
1344
- })
1810
+ export const exitInterrupt: MicroExit<never> = exitFailCause(causeInterrupt())
1345
1811
 
1346
1812
  /**
1347
- * Lazily creates a `Micro` effect from the given side-effect.
1348
- *
1349
- * @since 3.4.0
1813
+ * @since 3.4.6
1350
1814
  * @experimental
1351
- * @category constructors
1815
+ * @category MicroExit
1352
1816
  */
1353
- export const suspend = <A, E, R>(evaluate: LazyArg<Micro<A, E, R>>): Micro<A, E, R> =>
1354
- make(function(env, onExit) {
1355
- evaluate()[runSymbol](env, onExit)
1356
- })
1357
-
1358
- const void_: Micro<void> = succeed(void 0)
1359
- export {
1360
- /**
1361
- * A `Micro` effect that will succeed with `void` (`undefined`).
1362
- *
1363
- * @since 3.4.0
1364
- * @experimental
1365
- * @category constructors
1366
- */
1367
- void_ as void
1368
- }
1817
+ export const exitFail = <E>(e: E): MicroExit<never, E> => exitFailCause(causeFail(e))
1369
1818
 
1370
1819
  /**
1371
- * Create a `Micro` effect from an asynchronous computation.
1372
- *
1373
- * You can return a cleanup effect that will be run when the effect is aborted.
1374
- * It is also passed an `AbortSignal` that is triggered when the effect is
1375
- * aborted.
1376
- *
1377
- * @since 3.4.0
1820
+ * @since 3.4.6
1378
1821
  * @experimental
1379
- * @category constructors
1822
+ * @category MicroExit
1380
1823
  */
1381
- export const async = <A, E = never, R = never>(
1382
- register: (resume: (effect: Micro<A, E, R>) => void, signal: AbortSignal) => void | Micro<void, never, R>
1383
- ): Micro<A, E, R> =>
1384
- make(function(env, onExit) {
1385
- let resumed = false
1386
- const controller = register.length > 1 ? new AbortController() : undefined
1387
- const signal = envGet(env, currentAbortSignal)
1388
- let cleanup: Micro<void, never, R> | void = undefined
1389
- function onAbort() {
1390
- if (cleanup) {
1391
- resume(uninterruptible(andThen(cleanup, fromExit(exitInterrupt))))
1392
- } else {
1393
- resume(fromExit(exitInterrupt))
1394
- }
1395
- if (controller !== undefined) {
1396
- controller.abort()
1397
- }
1398
- }
1399
- function resume(effect: Micro<A, E, R>) {
1400
- if (resumed) {
1401
- return
1402
- }
1403
- resumed = true
1404
- signal.removeEventListener("abort", onAbort)
1405
- effect[runSymbol](env, onExit)
1406
- }
1407
- cleanup = controller === undefined
1408
- ? (register as any)(resume)
1409
- : register(resume, controller.signal)
1410
- if (resumed) return
1411
- signal.addEventListener("abort", onAbort)
1412
- })
1413
-
1414
- const try_ = <A, E>(options: {
1415
- try: LazyArg<A>
1416
- catch: (error: unknown) => E
1417
- }): Micro<A, E> =>
1418
- make(function(_env, onExit) {
1419
- try {
1420
- onExit(exitSucceed(options.try()))
1421
- } catch (err) {
1422
- onExit(exitFail(options.catch(err)))
1423
- }
1424
- })
1425
- export {
1426
- /**
1427
- * The `Micro` equivalent of a try / catch block, which allows you to map
1428
- * thrown errors to a specific error type.
1429
- *
1430
- * @since 3.4.0
1431
- * @experimental
1432
- * @category constructors
1433
- * @example
1434
- * import { Micro } from "effect"
1435
- *
1436
- * Micro.try({
1437
- * try: () => throw new Error("boom"),
1438
- * catch: (cause) => new Error("caught", { cause })
1439
- * })
1440
- */
1441
- try_ as try
1442
- }
1824
+ export const exitDie = (defect: unknown): MicroExit<never> => exitFailCause(causeDie(defect))
1443
1825
 
1444
1826
  /**
1445
- * Wrap a `Promise` into a `Micro` effect. Any errors will result in a
1446
- * `CauseDie`.
1447
- *
1448
- * @since 3.4.0
1827
+ * @since 3.4.6
1449
1828
  * @experimental
1450
- * @category constructors
1829
+ * @category MicroExit
1451
1830
  */
1452
- export const promise = <A>(evaluate: (signal: AbortSignal) => PromiseLike<A>): Micro<A> =>
1453
- async<A>(function(resume, signal) {
1454
- evaluate(signal).then(
1455
- (a) => resume(succeed(a)),
1456
- (e) => resume(die(e))
1457
- )
1458
- })
1831
+ export const exitIsSuccess = <A, E>(
1832
+ self: MicroExit<A, E>
1833
+ ): self is MicroExit.Success<A, E> => self._tag === "Success"
1459
1834
 
1460
1835
  /**
1461
- * Wrap a `Promise` into a `Micro` effect. Any errors will be caught and
1462
- * converted into a specific error type.
1463
- *
1464
- * @since 3.4.0
1836
+ * @since 3.4.6
1465
1837
  * @experimental
1466
- * @category constructors
1467
- * @example
1468
- * import { Micro } from "effect"
1469
- *
1470
- * Micro.tryPromise({
1471
- * try: () => Promise.resolve("success"),
1472
- * catch: (cause) => new Error("caught", { cause })
1473
- * })
1838
+ * @category MicroExit
1474
1839
  */
1475
- export const tryPromise = <A, E>(options: {
1476
- readonly try: (signal: AbortSignal) => PromiseLike<A>
1477
- readonly catch: (error: unknown) => E
1478
- }): Micro<A, E> =>
1479
- async<A, E>(function(resume, signal) {
1480
- try {
1481
- options.try(signal).then(
1482
- (a) => resume(succeed(a)),
1483
- (e) => resume(fail(options.catch(e)))
1484
- )
1485
- } catch (err) {
1486
- resume(fail(options.catch(err)))
1487
- }
1488
- })
1840
+ export const exitIsFailure = <A, E>(
1841
+ self: MicroExit<A, E>
1842
+ ): self is MicroExit.Failure<A, E> => self._tag === "Failure"
1489
1843
 
1490
1844
  /**
1491
- * Pause the execution of the current `Micro` effect, and resume it on the next
1492
- * iteration of the event loop.
1493
- *
1494
- * You can specify a priority for the task, which will determine when it is
1495
- * executed relative to other tasks.
1496
- *
1497
- * @since 3.4.0
1845
+ * @since 3.4.6
1498
1846
  * @experimental
1499
- * @category constructors
1847
+ * @category MicroExit
1500
1848
  */
1501
- export const yieldWithPriority = (priority: number): Micro<void> =>
1502
- make(function(env, onExit) {
1503
- envGet(env, currentScheduler).scheduleTask(() => onExit(exitVoid), priority)
1504
- })
1849
+ export const exitIsInterrupt = <A, E>(
1850
+ self: MicroExit<A, E>
1851
+ ): self is MicroExit.Failure<A, E> & {
1852
+ readonly cause: MicroCause.Interrupt
1853
+ } => exitIsFailure(self) && self.cause._tag === "Interrupt"
1505
1854
 
1506
1855
  /**
1507
- * Pause the execution of the current `Micro` effect, and resume it on the next
1508
- * iteration of the event loop.
1509
- *
1510
- * @since 3.4.0
1856
+ * @since 3.4.6
1511
1857
  * @experimental
1512
- * @category constructors
1858
+ * @category MicroExit
1513
1859
  */
1514
- export const yieldNow: Micro<void> = yieldWithPriority(0)
1860
+ export const exitIsFail = <A, E>(
1861
+ self: MicroExit<A, E>
1862
+ ): self is MicroExit.Failure<A, E> & {
1863
+ readonly cause: MicroCause.Fail<E>
1864
+ } => exitIsFailure(self) && self.cause._tag === "Fail"
1515
1865
 
1516
1866
  /**
1517
- * Flush any yielded effects that are waiting to be executed.
1518
- *
1519
- * @since 3.4.0
1867
+ * @since 3.4.6
1520
1868
  * @experimental
1521
- * @category constructors
1869
+ * @category MicroExit
1522
1870
  */
1523
- export const yieldFlush: Micro<void> = make(function(env, onExit) {
1524
- envGet(env, currentScheduler).flush()
1525
- onExit(exitVoid)
1526
- })
1871
+ export const exitIsDie = <A, E>(
1872
+ self: MicroExit<A, E>
1873
+ ): self is MicroExit.Failure<A, E> & {
1874
+ readonly cause: MicroCause.Die
1875
+ } => exitIsFailure(self) && self.cause._tag === "Die"
1527
1876
 
1528
1877
  /**
1529
- * A `Micro` that will never succeed or fail. It wraps `setInterval` to prevent
1530
- * the Javascript runtime from exiting.
1531
- *
1532
- * @since 3.4.0
1878
+ * @since 3.4.6
1533
1879
  * @experimental
1534
- * @category constructors
1880
+ * @category MicroExit
1535
1881
  */
1536
- export const never: Micro<never> = async<never>(function() {
1537
- const interval = setInterval(constVoid, 2147483646)
1538
- return sync(() => clearInterval(interval))
1539
- })
1882
+ export const exitVoid: MicroExit<void> = exitSucceed(void 0)
1540
1883
 
1541
1884
  /**
1542
- * @since 3.4.0
1885
+ * @since 3.11.0
1543
1886
  * @experimental
1544
- * @category constructors
1887
+ * @category MicroExit
1545
1888
  */
1546
- export const gen = <Self, Eff extends YieldWrap<Micro<any, any, any>>, AEff>(
1547
- ...args:
1548
- | [self: Self, body: (this: Self) => Generator<Eff, AEff, never>]
1549
- | [body: () => Generator<Eff, AEff, never>]
1550
- ): Micro<
1551
- AEff,
1552
- [Eff] extends [never] ? never : [Eff] extends [YieldWrap<Micro<infer _A, infer E, infer _R>>] ? E : never,
1553
- [Eff] extends [never] ? never : [Eff] extends [YieldWrap<Micro<infer _A, infer _E, infer R>>] ? R : never
1554
- > =>
1555
- make(function(env, onExit) {
1556
- const iterator: Generator<Eff, AEff, any> = args.length === 1 ? args[0]() : args[1].call(args[0])
1557
- let running = false
1558
- let value: any = undefined
1559
- function run() {
1560
- running = true
1561
- try {
1562
- let shouldContinue = true
1563
- while (shouldContinue) {
1564
- const result = iterator.next(value)
1565
- if (result.done) {
1566
- return onExit(exitSucceed(result.value))
1567
- }
1568
- shouldContinue = false
1569
- yieldWrapGet(result.value)[runSymbol](env, function(exit) {
1570
- if (exit._tag === "Left") {
1571
- onExit(exit)
1572
- } else {
1573
- shouldContinue = true
1574
- value = exit.right
1575
- if (!running) run()
1576
- }
1577
- })
1578
- }
1579
- } catch (err) {
1580
- onExit(exitDie(err))
1581
- }
1582
- running = false
1889
+ export const exitVoidAll = <I extends Iterable<MicroExit<any, any>>>(
1890
+ exits: I
1891
+ ): MicroExit<void, I extends Iterable<MicroExit<infer _A, infer _E>> ? _E : never> => {
1892
+ for (const exit of exits) {
1893
+ if (exit._tag === "Failure") {
1894
+ return exit
1583
1895
  }
1584
- run()
1585
- })
1896
+ }
1897
+ return exitVoid
1898
+ }
1586
1899
 
1587
1900
  // ----------------------------------------------------------------------------
1588
- // mapping & sequencing
1901
+ // scheduler
1589
1902
  // ----------------------------------------------------------------------------
1590
1903
 
1591
1904
  /**
1592
- * Flattens any nested `Micro` effects, merging the error and requirement types.
1593
- *
1594
- * @since 3.4.0
1905
+ * @since 3.5.9
1595
1906
  * @experimental
1596
- * @category mapping & sequencing
1907
+ * @category scheduler
1597
1908
  */
1598
- export const flatten = <A, E, R, E2, R2>(self: Micro<Micro<A, E, R>, E2, R2>): Micro<A, E | E2, R | R2> =>
1599
- make(function(env, onExit) {
1600
- self[runSymbol](
1601
- env,
1602
- (exit) => exit._tag === "Left" ? onExit(exit as MicroExit<never, E2>) : exit.right[runSymbol](env, onExit)
1603
- )
1604
- })
1909
+ export interface MicroScheduler {
1910
+ readonly scheduleTask: (task: () => void, priority: number) => void
1911
+ readonly shouldYield: (fiber: Fiber<unknown, unknown>) => boolean
1912
+ readonly flush: () => void
1913
+ }
1914
+
1915
+ const setImmediate = "setImmediate" in globalThis
1916
+ ? globalThis.setImmediate
1917
+ : (f: () => void) => setTimeout(f, 0)
1605
1918
 
1606
1919
  /**
1607
- * Transforms the success value of the `Micro` effect with the specified
1608
- * function.
1609
- *
1610
- * @since 3.4.0
1920
+ * @since 3.5.9
1611
1921
  * @experimental
1612
- * @category mapping & sequencing
1922
+ * @category scheduler
1613
1923
  */
1614
- export const map: {
1924
+ export class MicroSchedulerDefault implements MicroScheduler {
1925
+ private tasks: Array<() => void> = []
1926
+ private running = false
1927
+
1615
1928
  /**
1616
- * Transforms the success value of the `Micro` effect with the specified
1617
- * function.
1618
- *
1619
- * @since 3.4.0
1620
- * @experimental
1621
- * @category mapping & sequencing
1929
+ * @since 3.5.9
1622
1930
  */
1623
- <A, B>(f: (a: A) => B): <E, R>(self: Micro<A, E, R>) => Micro<B, E, R>
1931
+ scheduleTask(task: () => void, _priority: number) {
1932
+ this.tasks.push(task)
1933
+ if (!this.running) {
1934
+ this.running = true
1935
+ setImmediate(this.afterScheduled)
1936
+ }
1937
+ }
1938
+
1624
1939
  /**
1625
- * Transforms the success value of the `Micro` effect with the specified
1626
- * function.
1627
- *
1628
- * @since 3.4.0
1629
- * @experimental
1630
- * @category mapping & sequencing
1940
+ * @since 3.5.9
1631
1941
  */
1632
- <A, E, R, B>(self: Micro<A, E, R>, f: (a: A) => B): Micro<B, E, R>
1633
- } = dual(2, <A, E, R, B>(self: Micro<A, E, R>, f: (a: A) => B): Micro<B, E, R> =>
1634
- make(function(env, onExit) {
1635
- self[runSymbol](env, function(exit) {
1636
- onExit(exit._tag === "Left" ? exit as MicroExit<never, E> : exitSucceed(f(exit.right)))
1637
- })
1638
- }))
1942
+ afterScheduled = () => {
1943
+ this.running = false
1944
+ this.runTasks()
1945
+ }
1639
1946
 
1640
- /**
1641
- * Create a `Micro` effect that will replace the success value of the given
1642
- * effect.
1643
- *
1644
- * @since 3.4.0
1645
- * @experimental
1646
- * @category mapping & sequencing
1647
- */
1648
- export const as: {
1649
1947
  /**
1650
- * Create a `Micro` effect that will replace the success value of the given
1651
- * effect.
1652
- *
1653
- * @since 3.4.0
1654
- * @experimental
1655
- * @category mapping & sequencing
1948
+ * @since 3.5.9
1656
1949
  */
1657
- <A, B>(value: B): <E, R>(self: Micro<A, E, R>) => Micro<B, E, R>
1950
+ runTasks() {
1951
+ const tasks = this.tasks
1952
+ this.tasks = []
1953
+ for (let i = 0, len = tasks.length; i < len; i++) {
1954
+ tasks[i]()
1955
+ }
1956
+ }
1957
+
1658
1958
  /**
1659
- * Create a `Micro` effect that will replace the success value of the given
1660
- * effect.
1661
- *
1662
- * @since 3.4.0
1663
- * @experimental
1664
- * @category mapping & sequencing
1959
+ * @since 3.5.9
1665
1960
  */
1666
- <A, E, R, B>(self: Micro<A, E, R>, value: B): Micro<B, E, R>
1667
- } = dual(2, <A, E, R, B>(self: Micro<A, E, R>, value: B): Micro<B, E, R> => map(self, (_) => value))
1961
+ shouldYield(fiber: Fiber<unknown, unknown>) {
1962
+ return fiber.currentOpCount >= fiber.getRef(MaxOpsBeforeYield)
1963
+ }
1668
1964
 
1669
- /**
1670
- * Wrap the success value of this `Micro` effect in an `Option.Some`.
1671
- *
1672
- * @since 3.4.0
1673
- * @experimental
1674
- * @category mapping & sequencing
1675
- */
1676
- export const asSome = <A, E, R>(self: Micro<A, E, R>): Micro<Option.Option<A>, E, R> => map(self, Option.some)
1965
+ /**
1966
+ * @since 3.5.9
1967
+ */
1968
+ flush() {
1969
+ while (this.tasks.length > 0) {
1970
+ this.runTasks()
1971
+ }
1972
+ }
1973
+ }
1677
1974
 
1678
1975
  /**
1679
- * Map the success value of this `Micro` effect to another `Micro` effect, then
1680
- * flatten the result.
1976
+ * Access the given `Context.Tag` from the environment.
1681
1977
  *
1682
1978
  * @since 3.4.0
1683
1979
  * @experimental
1684
- * @category mapping & sequencing
1980
+ * @category environment
1685
1981
  */
1686
- export const flatMap: {
1982
+ export const service: {
1687
1983
  /**
1688
- * Map the success value of this `Micro` effect to another `Micro` effect, then
1689
- * flatten the result.
1984
+ * Access the given `Context.Tag` from the environment.
1690
1985
  *
1691
1986
  * @since 3.4.0
1692
1987
  * @experimental
1693
- * @category mapping & sequencing
1988
+ * @category environment
1694
1989
  */
1695
- <A, B, E2, R2>(f: (a: A) => Micro<B, E2, R2>): <E, R>(self: Micro<A, E, R>) => Micro<B, E | E2, R | R2>
1990
+ <I, S>(tag: Context.Reference<I, S>): Micro<S>
1696
1991
  /**
1697
- * Map the success value of this `Micro` effect to another `Micro` effect, then
1698
- * flatten the result.
1992
+ * Access the given `Context.Tag` from the environment.
1699
1993
  *
1700
1994
  * @since 3.4.0
1701
1995
  * @experimental
1702
- * @category mapping & sequencing
1996
+ * @category environment
1703
1997
  */
1704
- <A, E, R, B, E2, R2>(self: Micro<A, E, R>, f: (a: A) => Micro<B, E2, R2>): Micro<B, E | E2, R | R2>
1705
- } = dual(
1706
- 2,
1707
- <A, E, R, B, E2, R2>(self: Micro<A, E, R>, f: (a: A) => Micro<B, E2, R2>): Micro<B, E | E2, R | R2> =>
1708
- make(function(env, onExit) {
1709
- self[runSymbol](env, function(exit) {
1710
- if (exit._tag === "Left") {
1711
- return onExit(exit as MicroExit<never, E>)
1712
- }
1713
- f(exit.right)[runSymbol](env, onExit)
1714
- })
1715
- })
1716
- )
1998
+ <I, S>(tag: Context.Tag<I, S>): Micro<S, never, I>
1999
+ } =
2000
+ (<I, S>(tag: Context.Tag<I, S>): Micro<S, never, I> =>
2001
+ withFiber((fiber) => succeed(Context.unsafeGet(fiber.context, tag)))) as any
1717
2002
 
1718
2003
  /**
1719
- * Swap the error and success types of the `Micro` effect.
2004
+ * Access the given `Context.Tag` from the environment, without tracking the
2005
+ * dependency at the type level.
2006
+ *
2007
+ * It will return an `Option` of the service, depending on whether it is
2008
+ * available in the environment or not.
1720
2009
  *
1721
2010
  * @since 3.4.0
1722
2011
  * @experimental
1723
- * @category mapping & sequencing
2012
+ * @category environment
1724
2013
  */
1725
- export const flip = <A, E, R>(self: Micro<A, E, R>): Micro<E, A, R> =>
1726
- matchEffect(self, {
1727
- onFailure: succeed,
1728
- onSuccess: fail
1729
- })
2014
+ export const serviceOption = <I, S>(
2015
+ tag: Context.Tag<I, S>
2016
+ ): Micro<Option.Option<S>> => withFiber((fiber) => succeed(Context.getOption(fiber.context, tag)))
1730
2017
 
1731
2018
  /**
1732
- * A more flexible version of `flatMap`, that combines `map` and `flatMap` into
1733
- * a single api.
1734
- *
1735
- * It also allows you to pass in a `Micro` effect directly, which will be
1736
- * executed after the current effect.
2019
+ * Update the Context with the given mapping function.
1737
2020
  *
1738
- * @since 3.4.0
2021
+ * @since 3.11.0
1739
2022
  * @experimental
1740
- * @category mapping & sequencing
2023
+ * @category environment
1741
2024
  */
1742
- export const andThen: {
1743
- /**
1744
- * A more flexible version of `flatMap`, that combines `map` and `flatMap` into
1745
- * a single api.
1746
- *
1747
- * It also allows you to pass in a `Micro` effect directly, which will be
1748
- * executed after the current effect.
1749
- *
1750
- * @since 3.4.0
1751
- * @experimental
1752
- * @category mapping & sequencing
1753
- */
1754
- <A, X>(f: (a: A) => X): <E, R>(
1755
- self: Micro<A, E, R>
1756
- ) => [X] extends [Micro<infer A1, infer E1, infer R1>] ? Micro<A1, E | E1, R | R1>
1757
- : Micro<X, E, R>
1758
- /**
1759
- * A more flexible version of `flatMap`, that combines `map` and `flatMap` into
1760
- * a single api.
1761
- *
1762
- * It also allows you to pass in a `Micro` effect directly, which will be
1763
- * executed after the current effect.
1764
- *
1765
- * @since 3.4.0
1766
- * @experimental
1767
- * @category mapping & sequencing
1768
- */
1769
- <X>(f: NotFunction<X>): <A, E, R>(
1770
- self: Micro<A, E, R>
1771
- ) => [X] extends [Micro<infer A1, infer E1, infer R1>] ? Micro<A1, E | E1, R | R1>
1772
- : Micro<X, E, R>
2025
+ export const updateContext: {
1773
2026
  /**
1774
- * A more flexible version of `flatMap`, that combines `map` and `flatMap` into
1775
- * a single api.
2027
+ * Update the Context with the given mapping function.
1776
2028
  *
1777
- * It also allows you to pass in a `Micro` effect directly, which will be
1778
- * executed after the current effect.
1779
- *
1780
- * @since 3.4.0
2029
+ * @since 3.11.0
1781
2030
  * @experimental
1782
- * @category mapping & sequencing
2031
+ * @category environment
1783
2032
  */
1784
- <A, E, R, X>(
1785
- self: Micro<A, E, R>,
1786
- f: (a: A) => X
1787
- ): [X] extends [Micro<infer A1, infer E1, infer R1>] ? Micro<A1, E | E1, R | R1>
1788
- : Micro<X, E, R>
2033
+ <R2, R>(
2034
+ f: (context: Context.Context<R2>) => Context.Context<NoInfer<R>>
2035
+ ): <A, E>(self: Micro<A, E, R>) => Micro<A, E, R2>
1789
2036
  /**
1790
- * A more flexible version of `flatMap`, that combines `map` and `flatMap` into
1791
- * a single api.
1792
- *
1793
- * It also allows you to pass in a `Micro` effect directly, which will be
1794
- * executed after the current effect.
2037
+ * Update the Context with the given mapping function.
1795
2038
  *
1796
- * @since 3.4.0
2039
+ * @since 3.11.0
1797
2040
  * @experimental
1798
- * @category mapping & sequencing
2041
+ * @category environment
1799
2042
  */
1800
- <A, E, R, X>(
2043
+ <A, E, R, R2>(
1801
2044
  self: Micro<A, E, R>,
1802
- f: NotFunction<X>
1803
- ): [X] extends [Micro<infer A1, infer E1, infer R1>] ? Micro<A1, E | E1, R | R1>
1804
- : Micro<X, E, R>
2045
+ f: (context: Context.Context<R2>) => Context.Context<NoInfer<R>>
2046
+ ): Micro<A, E, R2>
1805
2047
  } = dual(
1806
2048
  2,
1807
- <A, E, R, B, E2, R2>(self: Micro<A, E, R>, f: any): Micro<B, E | E2, R | R2> =>
1808
- make(function(env, onExit) {
1809
- self[runSymbol](env, function(exit) {
1810
- if (exit._tag === "Left") {
1811
- return onExit(exit as MicroExit<never, E>)
1812
- } else if (envGet(env, currentAbortSignal).aborted) {
1813
- return onExit(exitInterrupt)
1814
- }
1815
- const value = isMicro(f) ? f : typeof f === "function" ? f(exit.right) : f
1816
- if (isMicro(value)) {
1817
- value[runSymbol](env, onExit)
1818
- } else {
1819
- onExit(exitSucceed(value))
2049
+ <A, E, R, R2>(
2050
+ self: Micro<A, E, R>,
2051
+ f: (context: Context.Context<R2>) => Context.Context<NoInfer<R>>
2052
+ ): Micro<A, E, R2> =>
2053
+ withFiber<
2054
+ /**
2055
+ * Update the Context with the given mapping function.
2056
+ *
2057
+ * @since 3.11.0
2058
+ * @experimental
2059
+ * @category environment
2060
+ */
2061
+ A, /**
2062
+ * Update the Context with the given mapping function.
2063
+ *
2064
+ * @since 3.11.0
2065
+ * @experimental
2066
+ * @category environment
2067
+ */
2068
+ E, /**
2069
+ * Update the Context with the given mapping function.
2070
+ *
2071
+ * @since 3.11.0
2072
+ * @experimental
2073
+ * @category environment
2074
+ */
2075
+ R2
2076
+ >((fiber) => {
2077
+ const prev = fiber.context as Context.Context<R2>
2078
+ fiber.context = f(prev)
2079
+ return onExit(
2080
+ self as any,
2081
+ () => {
2082
+ fiber.context = prev
2083
+ return void_
1820
2084
  }
1821
- })
2085
+ )
1822
2086
  })
1823
2087
  )
1824
2088
 
1825
2089
  /**
1826
- * Execute a side effect from the success value of the `Micro` effect.
1827
- *
1828
- * It is similar to the `andThen` api, but the success value is ignored.
2090
+ * Update the service for the given `Context.Tag` in the environment.
1829
2091
  *
1830
- * @since 3.4.0
2092
+ * @since 3.11.0
1831
2093
  * @experimental
1832
- * @category mapping & sequencing
2094
+ * @category environment
1833
2095
  */
1834
- export const tap: {
2096
+ export const updateService: {
1835
2097
  /**
1836
- * Execute a side effect from the success value of the `Micro` effect.
2098
+ * Update the service for the given `Context.Tag` in the environment.
1837
2099
  *
1838
- * It is similar to the `andThen` api, but the success value is ignored.
1839
- *
1840
- * @since 3.4.0
2100
+ * @since 3.11.0
1841
2101
  * @experimental
1842
- * @category mapping & sequencing
2102
+ * @category environment
1843
2103
  */
1844
- <A, X>(f: (a: NoInfer<A>) => X): <E, R>(
1845
- self: Micro<A, E, R>
1846
- ) => [X] extends [Micro<infer _A1, infer E1, infer R1>] ? Micro<A, E | E1, R | R1>
1847
- : Micro<A, E, R>
2104
+ <I, A>(tag: Context.Reference<I, A>, f: (value: A) => A): <XA, E, R>(self: Micro<XA, E, R>) => Micro<XA, E, R>
1848
2105
  /**
1849
- * Execute a side effect from the success value of the `Micro` effect.
1850
- *
1851
- * It is similar to the `andThen` api, but the success value is ignored.
2106
+ * Update the service for the given `Context.Tag` in the environment.
1852
2107
  *
1853
- * @since 3.4.0
2108
+ * @since 3.11.0
1854
2109
  * @experimental
1855
- * @category mapping & sequencing
2110
+ * @category environment
1856
2111
  */
1857
- <X>(f: NotFunction<X>): <A, E, R>(
1858
- self: Micro<A, E, R>
1859
- ) => [X] extends [Micro<infer _A1, infer E1, infer R1>] ? Micro<A, E | E1, R | R1>
1860
- : Micro<A, E, R>
2112
+ <I, A>(tag: Context.Tag<I, A>, f: (value: A) => A): <XA, E, R>(self: Micro<XA, E, R>) => Micro<XA, E, R | I>
1861
2113
  /**
1862
- * Execute a side effect from the success value of the `Micro` effect.
2114
+ * Update the service for the given `Context.Tag` in the environment.
1863
2115
  *
1864
- * It is similar to the `andThen` api, but the success value is ignored.
1865
- *
1866
- * @since 3.4.0
2116
+ * @since 3.11.0
1867
2117
  * @experimental
1868
- * @category mapping & sequencing
2118
+ * @category environment
1869
2119
  */
1870
- <A, E, R, X>(
1871
- self: Micro<A, E, R>,
1872
- f: (a: NoInfer<A>) => X
1873
- ): [X] extends [Micro<infer _A1, infer E1, infer R1>] ? Micro<A, E | E1, R | R1>
1874
- : Micro<A, E, R>
2120
+ <XA, E, R, I, A>(self: Micro<XA, E, R>, tag: Context.Reference<I, A>, f: (value: A) => A): Micro<XA, E, R>
1875
2121
  /**
1876
- * Execute a side effect from the success value of the `Micro` effect.
1877
- *
1878
- * It is similar to the `andThen` api, but the success value is ignored.
2122
+ * Update the service for the given `Context.Tag` in the environment.
1879
2123
  *
1880
- * @since 3.4.0
2124
+ * @since 3.11.0
1881
2125
  * @experimental
1882
- * @category mapping & sequencing
2126
+ * @category environment
1883
2127
  */
1884
- <A, E, R, X>(
1885
- self: Micro<A, E, R>,
1886
- f: NotFunction<X>
1887
- ): [X] extends [Micro<infer _A1, infer E1, infer R1>] ? Micro<A, E | E1, R | R1>
1888
- : Micro<A, E, R>
2128
+ <XA, E, R, I, A>(self: Micro<XA, E, R>, tag: Context.Tag<I, A>, f: (value: A) => A): Micro<XA, E, R | I>
1889
2129
  } = dual(
1890
- 2,
1891
- <A, E, R, B, E2, R2>(self: Micro<A, E, R>, f: (a: A) => Micro<B, E2, R2>): Micro<A, E | E2, R | R2> =>
1892
- make(function(env, onExit) {
1893
- self[runSymbol](env, function(selfExit) {
1894
- if (selfExit._tag === "Left") {
1895
- return onExit(selfExit as MicroExit<never, E>)
1896
- } else if (envGet(env, currentAbortSignal).aborted) {
1897
- return onExit(exitInterrupt)
1898
- }
1899
- const value = isMicro(f) ? f : typeof f === "function" ? f(selfExit.right) : f
1900
- if (isMicro(value)) {
1901
- value[runSymbol](env, function(tapExit) {
1902
- if (tapExit._tag === "Left") {
1903
- return onExit(tapExit)
1904
- }
1905
- onExit(selfExit)
1906
- })
1907
- } else {
1908
- onExit(selfExit)
2130
+ 3,
2131
+ <XA, E, R, I, A>(
2132
+ self: Micro<XA, E, R>,
2133
+ tag: Context.Reference<I, A>,
2134
+ f: (value: A) => A
2135
+ ): Micro<XA, E, R> =>
2136
+ withFiber((fiber) => {
2137
+ const prev = Context.unsafeGet(fiber.context, tag)
2138
+ fiber.context = Context.add(fiber.context, tag, f(prev))
2139
+ return onExit(
2140
+ self,
2141
+ () => {
2142
+ fiber.context = Context.add(fiber.context, tag, prev)
2143
+ return void_
1909
2144
  }
1910
- })
2145
+ )
1911
2146
  })
1912
2147
  )
1913
-
1914
- /**
1915
- * Replace the success value of the `Micro` effect with `void`.
1916
- *
1917
- * @since 3.4.0
1918
- * @experimental
1919
- * @category mapping & sequencing
1920
- */
1921
- export const asVoid = <A, E, R>(self: Micro<A, E, R>): Micro<void, E, R> => map(self, (_) => void 0)
1922
-
1923
- /**
1924
- * Access the `MicroExit` of the given `Micro` effect.
1925
- *
1926
- * @since 3.4.6
1927
- * @experimental
1928
- * @category mapping & sequencing
1929
- */
1930
- export const exit = <A, E, R>(self: Micro<A, E, R>): Micro<MicroExit<A, E>, never, R> =>
1931
- make(function(env, onExit) {
1932
- self[runSymbol](env, function(exit) {
1933
- onExit(exitSucceed(exit))
1934
- })
1935
- })
1936
-
1937
- /**
1938
- * Replace the error type of the given `Micro` with the full `MicroCause` object.
1939
- *
1940
- * @since 3.4.0
1941
- * @experimental
1942
- * @category mapping & sequencing
1943
- */
1944
- export const sandbox = <A, E, R>(self: Micro<A, E, R>): Micro<A, MicroCause<E>, R> =>
1945
- catchAllCause(self, (cause) => fail(cause))
1946
-
1947
- function forkSignal(env: Env<any>) {
1948
- const controller = new AbortController()
1949
- const parentSignal = envGet(env, currentAbortSignal)
1950
- function onAbort() {
1951
- controller.abort()
1952
- parentSignal.removeEventListener("abort", onAbort)
1953
- }
1954
- parentSignal.addEventListener("abort", onAbort)
1955
- const envWithSignal = envMutate(env, function(refs) {
1956
- refs[currentAbortController.key] = controller
1957
- refs[currentAbortSignal.key] = controller.signal
1958
- return refs
1959
- })
1960
- return [envWithSignal, onAbort] as const
1961
- }
1962
-
1963
- /**
1964
- * Returns an effect that races all the specified effects,
1965
- * yielding the value of the first effect to succeed with a value. Losers of
1966
- * the race will be interrupted immediately
2148
+
2149
+ /**
2150
+ * Access the current `Context` from the environment.
1967
2151
  *
1968
2152
  * @since 3.4.0
1969
2153
  * @experimental
1970
- * @category sequencing
2154
+ * @category environment
1971
2155
  */
1972
- export const raceAll = <Eff extends Micro<any, any, any>>(
1973
- all: Iterable<Eff>
1974
- ): Micro<Micro.Success<Eff>, Micro.Error<Eff>, Micro.Context<Eff>> =>
1975
- make(function(env, onExit) {
1976
- const [envWithSignal, onAbort] = forkSignal(env)
1977
-
1978
- const effects = Array.from(all)
1979
- let len = effects.length
1980
- let index = 0
1981
- let done = 0
1982
- let exit: MicroExit<any, any> | undefined = undefined
1983
- const causes: Array<MicroCause<any>> = []
1984
- function onDone(exit_: MicroExit<any, any>) {
1985
- done++
1986
- if (exit_._tag === "Right" && exit === undefined) {
1987
- len = index
1988
- exit = exit_
1989
- onAbort()
1990
- } else if (exit_._tag === "Left") {
1991
- causes.push(exit_.left)
1992
- }
1993
- if (done >= len) {
1994
- onExit(exit ?? Either.left(causes[0]))
1995
- }
1996
- }
1997
-
1998
- for (; index < len; index++) {
1999
- effects[index][runSymbol](envWithSignal, onDone)
2000
- }
2001
- })
2156
+ export const context = <R>(): Micro<Context.Context<R>> => getContext as any
2157
+ const getContext = withFiber((fiber) => succeed(fiber.context))
2002
2158
 
2003
2159
  /**
2004
- * Returns an effect that races all the specified effects,
2005
- * yielding the value of the first effect to succeed or fail. Losers of
2006
- * the race will be interrupted immediately
2160
+ * Merge the given `Context` with the current context.
2007
2161
  *
2008
2162
  * @since 3.4.0
2009
2163
  * @experimental
2010
- * @category sequencing
2164
+ * @category environment
2011
2165
  */
2012
- export const raceAllFirst = <Eff extends Micro<any, any, any>>(
2013
- all: Iterable<Eff>
2014
- ): Micro<Micro.Success<Eff>, Micro.Error<Eff>, Micro.Context<Eff>> =>
2015
- make(function(env, onExit) {
2016
- const [envWithSignal, onAbort] = forkSignal(env)
2017
-
2018
- const effects = Array.from(all)
2019
- let len = effects.length
2020
- let index = 0
2021
- let done = 0
2022
- let exit: MicroExit<any, any> | undefined = undefined
2023
- const causes: Array<MicroCause<any>> = []
2024
- function onDone(exit_: MicroExit<any, any>) {
2025
- done++
2026
- if (exit === undefined) {
2027
- len = index
2028
- exit = exit_
2029
- onAbort()
2030
- }
2031
- if (done >= len) {
2032
- onExit(exit ?? Either.left(causes[0]))
2033
- }
2034
- }
2035
-
2036
- for (; index < len; index++) {
2037
- effects[index][runSymbol](envWithSignal, onDone)
2038
- }
2039
- })
2166
+ export const provideContext: {
2167
+ /**
2168
+ * Merge the given `Context` with the current context.
2169
+ *
2170
+ * @since 3.4.0
2171
+ * @experimental
2172
+ * @category environment
2173
+ */
2174
+ <XR>(context: Context.Context<XR>): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E, Exclude<R, XR>>
2175
+ /**
2176
+ * Merge the given `Context` with the current context.
2177
+ *
2178
+ * @since 3.4.0
2179
+ * @experimental
2180
+ * @category environment
2181
+ */
2182
+ <A, E, R, XR>(self: Micro<A, E, R>, context: Context.Context<XR>): Micro<A, E, Exclude<R, XR>>
2183
+ } = dual(
2184
+ 2,
2185
+ <A, E, R, XR>(
2186
+ self: Micro<A, E, R>,
2187
+ provided: Context.Context<XR>
2188
+ ): Micro<A, E, Exclude<R, XR>> => updateContext(self, Context.merge(provided)) as any
2189
+ )
2040
2190
 
2041
2191
  /**
2042
- * Returns an effect that races two effects, yielding the value of the first
2043
- * effect to succeed. Losers of the race will be interrupted immediately
2192
+ * Add the provided service to the current context.
2044
2193
  *
2045
2194
  * @since 3.4.0
2046
2195
  * @experimental
2047
- * @category sequencing
2196
+ * @category environment
2048
2197
  */
2049
- export const race: {
2198
+ export const provideService: {
2050
2199
  /**
2051
- * Returns an effect that races two effects, yielding the value of the first
2052
- * effect to succeed. Losers of the race will be interrupted immediately
2200
+ * Add the provided service to the current context.
2053
2201
  *
2054
2202
  * @since 3.4.0
2055
2203
  * @experimental
2056
- * @category sequencing
2204
+ * @category environment
2057
2205
  */
2058
- <A2, E2, R2>(that: Micro<A2, E2, R2>): <A, E, R>(self: Micro<A, E, R>) => Micro<A | A2, E | E2, R | R2>
2206
+ <I, S>(tag: Context.Tag<I, S>, service: S): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E, Exclude<R, I>>
2059
2207
  /**
2060
- * Returns an effect that races two effects, yielding the value of the first
2061
- * effect to succeed. Losers of the race will be interrupted immediately
2208
+ * Add the provided service to the current context.
2062
2209
  *
2063
2210
  * @since 3.4.0
2064
2211
  * @experimental
2065
- * @category sequencing
2212
+ * @category environment
2066
2213
  */
2067
- <A, E, R, A2, E2, R2>(self: Micro<A, E, R>, that: Micro<A2, E2, R2>): Micro<A | A2, E | E2, R | R2>
2214
+ <A, E, R, I, S>(self: Micro<A, E, R>, tag: Context.Tag<I, S>, service: S): Micro<A, E, Exclude<R, I>>
2068
2215
  } = dual(
2069
- 2,
2070
- <A, E, R, A2, E2, R2>(self: Micro<A, E, R>, that: Micro<A2, E2, R2>): Micro<A | A2, E | E2, R | R2> =>
2071
- raceAll([self, that])
2216
+ 3,
2217
+ <A, E, R, I, S>(
2218
+ self: Micro<A, E, R>,
2219
+ tag: Context.Tag<I, S>,
2220
+ service: S
2221
+ ): Micro<A, E, Exclude<R, I>> => updateContext(self, Context.add(tag, service)) as any
2072
2222
  )
2073
2223
 
2074
2224
  /**
2075
- * Returns an effect that races two effects, yielding the value of the first
2076
- * effect to succeed *or* fail. Losers of the race will be interrupted immediately
2225
+ * Create a service using the provided `Micro` effect, and add it to the
2226
+ * current context.
2227
+ *
2228
+ * @since 3.4.6
2229
+ * @experimental
2230
+ * @category environment
2231
+ */
2232
+ export const provideServiceEffect: {
2233
+ /**
2234
+ * Create a service using the provided `Micro` effect, and add it to the
2235
+ * current context.
2236
+ *
2237
+ * @since 3.4.6
2238
+ * @experimental
2239
+ * @category environment
2240
+ */
2241
+ <I, S, E2, R2>(
2242
+ tag: Context.Tag<I, S>,
2243
+ acquire: Micro<S, E2, R2>
2244
+ ): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E | E2, Exclude<R, I> | R2>
2245
+ /**
2246
+ * Create a service using the provided `Micro` effect, and add it to the
2247
+ * current context.
2248
+ *
2249
+ * @since 3.4.6
2250
+ * @experimental
2251
+ * @category environment
2252
+ */
2253
+ <A, E, R, I, S, E2, R2>(
2254
+ self: Micro<A, E, R>,
2255
+ tag: Context.Tag<I, S>,
2256
+ acquire: Micro<S, E2, R2>
2257
+ ): Micro<A, E | E2, Exclude<R, I> | R2>
2258
+ } = dual(
2259
+ 3,
2260
+ <A, E, R, I, S, E2, R2>(
2261
+ self: Micro<A, E, R>,
2262
+ tag: Context.Tag<I, S>,
2263
+ acquire: Micro<S, E2, R2>
2264
+ ): Micro<A, E | E2, Exclude<R, I> | R2> => flatMap(acquire, (service) => provideService(self, tag, service))
2265
+ )
2266
+
2267
+ // ========================================================================
2268
+ // References
2269
+ // ========================================================================
2270
+
2271
+ /**
2272
+ * @since 3.11.0
2273
+ * @experimental
2274
+ * @category references
2275
+ */
2276
+ export class MaxOpsBeforeYield extends Context.Reference<MaxOpsBeforeYield>()<
2277
+ "effect/Micro/currentMaxOpsBeforeYield",
2278
+ number
2279
+ >(
2280
+ "effect/Micro/currentMaxOpsBeforeYield",
2281
+ { defaultValue: () => 2048 }
2282
+ ) {}
2283
+
2284
+ /**
2285
+ * @since 3.11.0
2286
+ * @experimental
2287
+ * @category environment refs
2288
+ */
2289
+ export class CurrentConcurrency extends Context.Reference<CurrentConcurrency>()<
2290
+ "effect/Micro/currentConcurrency",
2291
+ "unbounded" | number
2292
+ >(
2293
+ "effect/Micro/currentConcurrency",
2294
+ { defaultValue: () => "unbounded" }
2295
+ ) {}
2296
+
2297
+ /**
2298
+ * @since 3.11.0
2299
+ * @experimental
2300
+ * @category environment refs
2301
+ */
2302
+ export class CurrentScheduler extends Context.Reference<CurrentScheduler>()<
2303
+ "effect/Micro/currentScheduler",
2304
+ MicroScheduler
2305
+ >(
2306
+ "effect/Micro/currentScheduler",
2307
+ { defaultValue: () => new MicroSchedulerDefault() }
2308
+ ) {}
2309
+
2310
+ /**
2311
+ * If you have a `Micro` that uses `concurrency: "inherit"`, you can use this
2312
+ * api to control the concurrency of that `Micro` when it is run.
2077
2313
  *
2078
2314
  * @since 3.4.0
2079
2315
  * @experimental
2080
- * @category sequencing
2316
+ * @category environment refs
2317
+ * @example
2318
+ * import * as Micro from "effect/Micro"
2319
+ *
2320
+ * Micro.forEach([1, 2, 3], (n) => Micro.succeed(n), {
2321
+ * concurrency: "inherit"
2322
+ * }).pipe(
2323
+ * Micro.withConcurrency(2) // use a concurrency of 2
2324
+ * )
2081
2325
  */
2082
- export const raceFirst: {
2326
+ export const withConcurrency: {
2083
2327
  /**
2084
- * Returns an effect that races two effects, yielding the value of the first
2085
- * effect to succeed *or* fail. Losers of the race will be interrupted immediately
2328
+ * If you have a `Micro` that uses `concurrency: "inherit"`, you can use this
2329
+ * api to control the concurrency of that `Micro` when it is run.
2086
2330
  *
2087
2331
  * @since 3.4.0
2088
2332
  * @experimental
2089
- * @category sequencing
2333
+ * @category environment refs
2334
+ * @example
2335
+ * import * as Micro from "effect/Micro"
2336
+ *
2337
+ * Micro.forEach([1, 2, 3], (n) => Micro.succeed(n), {
2338
+ * concurrency: "inherit"
2339
+ * }).pipe(
2340
+ * Micro.withConcurrency(2) // use a concurrency of 2
2341
+ * )
2090
2342
  */
2091
- <A2, E2, R2>(that: Micro<A2, E2, R2>): <A, E, R>(self: Micro<A, E, R>) => Micro<A | A2, E | E2, R | R2>
2343
+ (concurrency: "unbounded" | number): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E, R>
2092
2344
  /**
2093
- * Returns an effect that races two effects, yielding the value of the first
2094
- * effect to succeed *or* fail. Losers of the race will be interrupted immediately
2345
+ * If you have a `Micro` that uses `concurrency: "inherit"`, you can use this
2346
+ * api to control the concurrency of that `Micro` when it is run.
2095
2347
  *
2096
2348
  * @since 3.4.0
2097
2349
  * @experimental
2098
- * @category sequencing
2350
+ * @category environment refs
2351
+ * @example
2352
+ * import * as Micro from "effect/Micro"
2353
+ *
2354
+ * Micro.forEach([1, 2, 3], (n) => Micro.succeed(n), {
2355
+ * concurrency: "inherit"
2356
+ * }).pipe(
2357
+ * Micro.withConcurrency(2) // use a concurrency of 2
2358
+ * )
2099
2359
  */
2100
- <A, E, R, A2, E2, R2>(self: Micro<A, E, R>, that: Micro<A2, E2, R2>): Micro<A | A2, E | E2, R | R2>
2360
+ <A, E, R>(self: Micro<A, E, R>, concurrency: "unbounded" | number): Micro<A, E, R>
2101
2361
  } = dual(
2102
2362
  2,
2103
- <A, E, R, A2, E2, R2>(self: Micro<A, E, R>, that: Micro<A2, E2, R2>): Micro<A | A2, E | E2, R | R2> =>
2104
- raceAllFirst([self, that])
2363
+ <A, E, R>(
2364
+ self: Micro<A, E, R>,
2365
+ concurrency: "unbounded" | number
2366
+ ): Micro<A, E, R> => provideService(self, CurrentConcurrency, concurrency)
2105
2367
  )
2106
2368
 
2107
2369
  // ----------------------------------------------------------------------------
@@ -2202,13 +2464,11 @@ export const zipWith: {
2202
2464
  that: Micro<A2, E2, R2>,
2203
2465
  f: (a: A, b: A2) => B,
2204
2466
  options?: { readonly concurrent?: boolean | undefined }
2205
- ): Micro<B, E2 | E, R2 | R> => {
2206
- if (options?.concurrent) {
2467
+ ): Micro<B, E2 | E, R2 | R> =>
2468
+ options?.concurrent
2207
2469
  // Use `all` exclusively for concurrent cases, as it introduces additional overhead due to the management of concurrency
2208
- return map(all([self, that], { concurrency: "unbounded" }), ([a, a2]) => f(a, a2))
2209
- }
2210
- return flatMap(self, (a) => map(that, (a2) => f(a, a2)))
2211
- })
2470
+ ? map(all([self, that], { concurrency: 2 }), ([a, a2]) => f(a, a2))
2471
+ : flatMap(self, (a) => map(that, (a2) => f(a, a2))))
2212
2472
 
2213
2473
  // ----------------------------------------------------------------------------
2214
2474
  // filtering & conditionals
@@ -2421,7 +2681,7 @@ export const when: {
2421
2681
  self: Micro<A, E, R>,
2422
2682
  condition: LazyArg<boolean> | Micro<boolean, E2, R2>
2423
2683
  ): Micro<Option.Option<A>, E | E2, R | R2> =>
2424
- flatMap(isMicro(condition) ? condition : sync(condition), (pass) => pass ? asSome(self) : succeed(Option.none()))
2684
+ flatMap(isMicro(condition) ? condition : sync(condition), (pass) => pass ? asSome(self) : succeedNone)
2425
2685
  )
2426
2686
 
2427
2687
  // ----------------------------------------------------------------------------
@@ -2487,14 +2747,15 @@ export const repeatExit: {
2487
2747
  times?: number | undefined
2488
2748
  schedule?: MicroSchedule | undefined
2489
2749
  }): Micro<A, E, R> =>
2490
- make(function(env, onExit) {
2750
+ suspend(() => {
2491
2751
  const startedAt = options.schedule ? Date.now() : 0
2492
2752
  let attempt = 0
2493
- self[runSymbol](env, function loop(exit) {
2753
+
2754
+ const loop: Micro<A, E, R> = flatMap(exit(self), (exit) => {
2494
2755
  if (options.while !== undefined && !options.while(exit)) {
2495
- return onExit(exit)
2756
+ return exit
2496
2757
  } else if (options.times !== undefined && attempt >= options.times) {
2497
- return onExit(exit)
2758
+ return exit
2498
2759
  }
2499
2760
  attempt++
2500
2761
  let delayEffect = yieldNow
@@ -2502,17 +2763,14 @@ export const repeatExit: {
2502
2763
  const elapsed = Date.now() - startedAt
2503
2764
  const duration = options.schedule(attempt, elapsed)
2504
2765
  if (Option.isNone(duration)) {
2505
- return onExit(exit)
2766
+ return exit
2506
2767
  }
2507
2768
  delayEffect = sleep(duration.value)
2508
2769
  }
2509
- delayEffect[runSymbol](env, function(exit) {
2510
- if (exit._tag === "Left") {
2511
- return onExit(exit as MicroExit<never, never>)
2512
- }
2513
- self[runSymbol](env, loop)
2514
- })
2770
+ return flatMap(delayEffect, () => loop)
2515
2771
  })
2772
+
2773
+ return loop
2516
2774
  }))
2517
2775
 
2518
2776
  /**
@@ -2565,9 +2823,116 @@ export const repeat: {
2565
2823
  ): Micro<A, E, R> =>
2566
2824
  repeatExit(self, {
2567
2825
  ...options,
2568
- while: (exit) => exit._tag === "Right" && (options?.while === undefined || options.while(exit.right))
2826
+ while: (exit) => exit._tag === "Success" && (options?.while === undefined || options.while(exit.value))
2569
2827
  }))
2570
2828
 
2829
+ /**
2830
+ * Replicates the given effect `n` times.
2831
+ *
2832
+ * @since 3.11.0
2833
+ * @experimental
2834
+ * @category repetition
2835
+ */
2836
+ export const replicate: {
2837
+ /**
2838
+ * Replicates the given effect `n` times.
2839
+ *
2840
+ * @since 3.11.0
2841
+ * @experimental
2842
+ * @category repetition
2843
+ */
2844
+ (n: number): <A, E, R>(self: Micro<A, E, R>) => Array<Micro<A, E, R>>
2845
+ /**
2846
+ * Replicates the given effect `n` times.
2847
+ *
2848
+ * @since 3.11.0
2849
+ * @experimental
2850
+ * @category repetition
2851
+ */
2852
+ <A, E, R>(self: Micro<A, E, R>, n: number): Array<Micro<A, E, R>>
2853
+ } = dual(
2854
+ 2,
2855
+ <A, E, R>(self: Micro<A, E, R>, n: number): Array<Micro<A, E, R>> => Array.from({ length: n }, () => self)
2856
+ )
2857
+
2858
+ /**
2859
+ * Performs this effect the specified number of times and collects the
2860
+ * results.
2861
+ *
2862
+ * @since 3.11.0
2863
+ * @category repetition
2864
+ */
2865
+ export const replicateEffect: {
2866
+ /**
2867
+ * Performs this effect the specified number of times and collects the
2868
+ * results.
2869
+ *
2870
+ * @since 3.11.0
2871
+ * @category repetition
2872
+ */
2873
+ (
2874
+ n: number,
2875
+ options?: {
2876
+ readonly concurrency?: Concurrency | undefined
2877
+ readonly discard?: false | undefined
2878
+ }
2879
+ ): <A, E, R>(self: Micro<A, E, R>) => Micro<Array<A>, E, R>
2880
+ /**
2881
+ * Performs this effect the specified number of times and collects the
2882
+ * results.
2883
+ *
2884
+ * @since 3.11.0
2885
+ * @category repetition
2886
+ */
2887
+ (
2888
+ n: number,
2889
+ options: {
2890
+ readonly concurrency?: Concurrency | undefined
2891
+ readonly discard: true
2892
+ }
2893
+ ): <A, E, R>(self: Micro<A, E, R>) => Micro<void, E, R>
2894
+ /**
2895
+ * Performs this effect the specified number of times and collects the
2896
+ * results.
2897
+ *
2898
+ * @since 3.11.0
2899
+ * @category repetition
2900
+ */
2901
+ <A, E, R>(
2902
+ self: Micro<A, E, R>,
2903
+ n: number,
2904
+ options?: {
2905
+ readonly concurrency?: Concurrency | undefined
2906
+ readonly discard?: false | undefined
2907
+ }
2908
+ ): Micro<Array<A>, E, R>
2909
+ /**
2910
+ * Performs this effect the specified number of times and collects the
2911
+ * results.
2912
+ *
2913
+ * @since 3.11.0
2914
+ * @category repetition
2915
+ */
2916
+ <A, E, R>(
2917
+ self: Micro<A, E, R>,
2918
+ n: number,
2919
+ options: {
2920
+ readonly concurrency?: Concurrency | undefined
2921
+ readonly discard: true
2922
+ }
2923
+ ): Micro<void, E, R>
2924
+ } = dual(
2925
+ (args) => isMicro(args[0]),
2926
+ <A, E, R>(
2927
+ self: Micro<A, E, R>,
2928
+ n: number,
2929
+ options: {
2930
+ readonly concurrency?: Concurrency | undefined
2931
+ readonly discard: true
2932
+ }
2933
+ ): Micro<void, E, R> => all(replicate(self, n), options)
2934
+ )
2935
+
2571
2936
  /**
2572
2937
  * Repeat the given `Micro` effect forever, only stopping if the effect fails.
2573
2938
  *
@@ -2838,8 +3203,20 @@ export const catchAllCause: {
2838
3203
  <A, E, R, B, E2, R2>(
2839
3204
  self: Micro<A, E, R>,
2840
3205
  f: (cause: NoInfer<MicroCause<E>>) => Micro<B, E2, R2>
2841
- ): Micro<A | B, E2, R | R2> => catchCauseIf(self, constTrue, f) as Micro<A | B, E2, R | R2>
3206
+ ): Micro<A | B, E2, R | R2> => {
3207
+ const onFailure = Object.create(OnFailureProto)
3208
+ onFailure[args] = self
3209
+ onFailure[failureCont] = f
3210
+ return onFailure
3211
+ }
2842
3212
  )
3213
+ const OnFailureProto = makePrimitiveProto({
3214
+ op: "OnFailure",
3215
+ eval(this: any, fiber: FiberImpl): Primitive {
3216
+ fiber._stack.push(this as any)
3217
+ return this[args]
3218
+ }
3219
+ })
2843
3220
 
2844
3221
  /**
2845
3222
  * Selectively catch a `MicroCause` object of the given `Micro` effect,
@@ -2861,7 +3238,9 @@ export const catchCauseIf: {
2861
3238
  <E, B, E2, R2, EB extends MicroCause<E>>(
2862
3239
  refinement: Refinement<MicroCause<E>, EB>,
2863
3240
  f: (cause: EB) => Micro<B, E2, R2>
2864
- ): <A, R>(self: Micro<A, E, R>) => Micro<A | B, Exclude<E, MicroCause.Error<EB>> | E2, R | R2>
3241
+ ): <A, R>(
3242
+ self: Micro<A, E, R>
3243
+ ) => Micro<A | B, Exclude<E, MicroCause.Error<EB>> | E2, R | R2>
2865
3244
  /**
2866
3245
  * Selectively catch a `MicroCause` object of the given `Micro` effect,
2867
3246
  * using the provided predicate to determine if the failure should be caught.
@@ -2900,20 +3279,15 @@ export const catchCauseIf: {
2900
3279
  predicate: Predicate<MicroCause<NoInfer<E>>>,
2901
3280
  f: (cause: NoInfer<MicroCause<E>>) => Micro<B, E2, R2>
2902
3281
  ): Micro<A | B, E | E2, R | R2>
2903
- } = dual(3, <A, E, R, B, E2, R2>(
2904
- self: Micro<A, E, R>,
2905
- predicate: Predicate<MicroCause<E>>,
2906
- f: (cause: MicroCause<E>) => Micro<B, E2, R2>
2907
- ): Micro<A | B, E | E2, R | R2> =>
2908
- make(function(env, onExit) {
2909
- self[runSymbol](env, function(exit) {
2910
- if (exit._tag === "Right" || !predicate(exit.left)) {
2911
- onExit(exit)
2912
- } else {
2913
- f(exit.left)[runSymbol](env, onExit)
2914
- }
2915
- })
2916
- }))
3282
+ } = dual(
3283
+ 3,
3284
+ <A, E, R, B, E2, R2>(
3285
+ self: Micro<A, E, R>,
3286
+ predicate: Predicate<MicroCause<E>>,
3287
+ f: (cause: MicroCause<E>) => Micro<B, E2, R2>
3288
+ ): Micro<A | B, E | E2, R | R2> =>
3289
+ catchAllCause(self, (cause) => predicate(cause) ? f(cause) : failCause(cause) as any)
3290
+ )
2917
3291
 
2918
3292
  /**
2919
3293
  * Catch the error of the given `Micro` effect, allowing you to recover from it.
@@ -2950,7 +3324,7 @@ export const catchAll: {
2950
3324
  <A, E, R, B, E2, R2>(
2951
3325
  self: Micro<A, E, R>,
2952
3326
  f: (a: NoInfer<E>) => Micro<B, E2, R2>
2953
- ): Micro<A | B, E2, R | R2> => catchAllCause(self, (cause) => causeIsFail(cause) ? f(cause.error) : failCause(cause))
3327
+ ): Micro<A | B, E2, R | R2> => catchCauseIf(self, causeIsFail, (cause) => f(cause.error))
2954
3328
  )
2955
3329
 
2956
3330
  /**
@@ -3386,7 +3760,7 @@ export const ignoreLogged = <A, E, R>(self: Micro<A, E, R>): Micro<void, never,
3386
3760
  * @category error handling
3387
3761
  */
3388
3762
  export const option = <A, E, R>(self: Micro<A, E, R>): Micro<Option.Option<A>, never, R> =>
3389
- match(self, { onFailure: (_) => Option.none(), onSuccess: Option.some })
3763
+ match(self, { onFailure: Option.none, onSuccess: Option.some })
3390
3764
 
3391
3765
  /**
3392
3766
  * Replace the success value of the given `Micro` effect with an `Either`,
@@ -3448,8 +3822,8 @@ export const retry: {
3448
3822
  repeatExit(self, {
3449
3823
  ...options,
3450
3824
  while: (exit) =>
3451
- exit._tag === "Left" && exit.left._tag === "Fail" &&
3452
- (options?.while === undefined || options.while(exit.left.error))
3825
+ exit._tag === "Failure" && exit.cause._tag === "Fail" &&
3826
+ (options?.while === undefined || options.while(exit.cause.error))
3453
3827
  }))
3454
3828
 
3455
3829
  /**
@@ -3496,12 +3870,7 @@ export const withTrace: {
3496
3870
  const lineMatch = line.match(/\((.*)\)$/)
3497
3871
  return causeWithTrace(cause, `at ${name} (${lineMatch ? lineMatch[1] : line})`)
3498
3872
  }
3499
- const f = (name: string) => (self: Micro<any, any, any>) =>
3500
- unsafeMakeOptions(function(env, onExit) {
3501
- self[runSymbol](env, function(exit) {
3502
- onExit(exit._tag === "Left" ? Either.left(generate(name, exit.left)) : exit)
3503
- })
3504
- }, false)
3873
+ const f = (name: string) => (self: Micro<any, any, any>) => onError(self, (cause) => failCause(generate(name, cause)))
3505
3874
  if (arguments.length === 2) {
3506
3875
  return f(arguments[1])(arguments[0])
3507
3876
  }
@@ -3557,18 +3926,21 @@ export const matchCauseEffect: {
3557
3926
  readonly onFailure: (cause: MicroCause<E>) => Micro<A2, E2, R2>
3558
3927
  readonly onSuccess: (a: A) => Micro<A3, E3, R3>
3559
3928
  }
3560
- ): Micro<A2 | A3, E2 | E3, R2 | R3 | R> =>
3561
- make(function(env, onExit) {
3562
- self[runSymbol](env, function(exit) {
3563
- try {
3564
- const next = exit._tag === "Left" ? options.onFailure(exit.left) : options.onSuccess(exit.right)
3565
- next[runSymbol](env, onExit)
3566
- } catch (err) {
3567
- onExit(exitDie(err))
3568
- }
3569
- })
3570
- })
3929
+ ): Micro<A2 | A3, E2 | E3, R2 | R3 | R> => {
3930
+ const primitive = Object.create(OnSuccessAndFailureProto)
3931
+ primitive[args] = self
3932
+ primitive[successCont] = options.onSuccess
3933
+ primitive[failureCont] = options.onFailure
3934
+ return primitive
3935
+ }
3571
3936
  )
3937
+ const OnSuccessAndFailureProto = makePrimitiveProto({
3938
+ op: "OnSuccessAndFailure",
3939
+ eval(this: any, fiber: FiberImpl): Primitive {
3940
+ fiber._stack.push(this)
3941
+ return this[args]
3942
+ }
3943
+ })
3572
3944
 
3573
3945
  /**
3574
3946
  * @since 3.4.6
@@ -3714,12 +4086,12 @@ export const match: {
3714
4086
  * @category delays & timeouts
3715
4087
  */
3716
4088
  export const sleep = (millis: number): Micro<void> =>
3717
- async(function(resume) {
3718
- const timeout = setTimeout(function() {
4089
+ async((resume) => {
4090
+ const timeout = setTimeout(() => {
3719
4091
  resume(void_)
3720
4092
  }, millis)
3721
4093
  return sync(() => {
3722
- return clearTimeout(timeout)
4094
+ clearTimeout(timeout)
3723
4095
  })
3724
4096
  })
3725
4097
 
@@ -3987,7 +4359,7 @@ class MicroScopeImpl implements MicroScope.Closeable {
3987
4359
  this.state = { _tag: "Closed", exit: microExit }
3988
4360
  return flatMap(
3989
4361
  forEach(finalizers, (finalizer) => exit(finalizer(microExit))),
3990
- (exits) => asVoid(fromExit(Either.all(exits)))
4362
+ exitVoidAll
3991
4363
  )
3992
4364
  }
3993
4365
  return void_
@@ -4072,7 +4444,7 @@ export const provideScope: {
4072
4444
  * @category resources & finalization
4073
4445
  */
4074
4446
  export const scoped = <A, E, R>(self: Micro<A, E, R>): Micro<A, E, Exclude<R, MicroScope>> =>
4075
- suspend(function() {
4447
+ suspend(() => {
4076
4448
  const scope = new MicroScopeImpl()
4077
4449
  return onExit(provideService(self, MicroScope, scope), (exit) => scope.close(exit))
4078
4450
  })
@@ -4139,7 +4511,45 @@ export const onExit: {
4139
4511
  <A, E, R, XE, XR>(
4140
4512
  self: Micro<A, E, R>,
4141
4513
  f: (exit: MicroExit<A, E>) => Micro<void, XE, XR>
4142
- ): Micro<A, E | XE, R | XR> => onExitIf(self, constTrue, f)
4514
+ ): Micro<A, E | XE, R | XR> =>
4515
+ uninterruptibleMask((restore) =>
4516
+ matchCauseEffect(restore(self), {
4517
+ onFailure: (cause) => flatMap(f(exitFailCause(cause)), () => failCause(cause)),
4518
+ onSuccess: (a) => flatMap(f(exitSucceed(a)), () => succeed(a))
4519
+ })
4520
+ )
4521
+ )
4522
+
4523
+ /**
4524
+ * Regardless of the result of the this `Micro` effect, run the finalizer effect.
4525
+ *
4526
+ * @since 3.4.0
4527
+ * @experimental
4528
+ * @category resources & finalization
4529
+ */
4530
+ export const ensuring: {
4531
+ /**
4532
+ * Regardless of the result of the this `Micro` effect, run the finalizer effect.
4533
+ *
4534
+ * @since 3.4.0
4535
+ * @experimental
4536
+ * @category resources & finalization
4537
+ */
4538
+ <XE, XR>(finalizer: Micro<void, XE, XR>): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E | XE, R | XR>
4539
+ /**
4540
+ * Regardless of the result of the this `Micro` effect, run the finalizer effect.
4541
+ *
4542
+ * @since 3.4.0
4543
+ * @experimental
4544
+ * @category resources & finalization
4545
+ */
4546
+ <A, E, R, XE, XR>(self: Micro<A, E, R>, finalizer: Micro<void, XE, XR>): Micro<A, E | XE, R | XR>
4547
+ } = dual(
4548
+ 2,
4549
+ <A, E, R, XE, XR>(
4550
+ self: Micro<A, E, R>,
4551
+ finalizer: Micro<void, XE, XR>
4552
+ ): Micro<A, E | XE, R | XR> => onExit(self, (_) => finalizer)
4143
4553
  )
4144
4554
 
4145
4555
  /**
@@ -4207,52 +4617,7 @@ export const onExitIf: {
4207
4617
  self: Micro<A, E, R>,
4208
4618
  refinement: Refinement<MicroExit<A, E>, B>,
4209
4619
  f: (exit: B) => Micro<void, XE, XR>
4210
- ): Micro<A, E | XE, R | XR> =>
4211
- uninterruptibleMask((restore) =>
4212
- make(function(env, onExit) {
4213
- restore(self)[runSymbol](env, function(exit) {
4214
- if (!refinement(exit)) {
4215
- return onExit(exit)
4216
- }
4217
- f(exit)[runSymbol](env, function(finalizerExit) {
4218
- if (finalizerExit._tag === "Left") {
4219
- return onExit(finalizerExit as MicroExit<never, XE>)
4220
- }
4221
- onExit(exit)
4222
- })
4223
- })
4224
- })
4225
- )
4226
- )
4227
-
4228
- /**
4229
- * Regardless of the result of the this `Micro` effect, run the finalizer effect.
4230
- *
4231
- * @since 3.4.0
4232
- * @experimental
4233
- * @category resources & finalization
4234
- */
4235
- export const ensuring: {
4236
- /**
4237
- * Regardless of the result of the this `Micro` effect, run the finalizer effect.
4238
- *
4239
- * @since 3.4.0
4240
- * @experimental
4241
- * @category resources & finalization
4242
- */
4243
- <XE, XR>(finalizer: Micro<void, XE, XR>): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E | XE, R | XR>
4244
- /**
4245
- * Regardless of the result of the this `Micro` effect, run the finalizer effect.
4246
- *
4247
- * @since 3.4.0
4248
- * @experimental
4249
- * @category resources & finalization
4250
- */
4251
- <A, E, R, XE, XR>(self: Micro<A, E, R>, finalizer: Micro<void, XE, XR>): Micro<A, E | XE, R | XR>
4252
- } = dual(
4253
- 2,
4254
- <A, E, R, XE, XR>(self: Micro<A, E, R>, finalizer: Micro<void, XE, XR>): Micro<A, E | XE, R | XR> =>
4255
- onExit(self, (_) => finalizer)
4620
+ ): Micro<A, E | XE, R | XR> => onExit(self, (exit) => (refinement(exit) ? f(exit) : exitVoid))
4256
4621
  )
4257
4622
 
4258
4623
  /**
@@ -4292,7 +4657,7 @@ export const onError: {
4292
4657
  <A, E, R, XE, XR>(
4293
4658
  self: Micro<A, E, R>,
4294
4659
  f: (cause: MicroCause<NoInfer<E>>) => Micro<void, XE, XR>
4295
- ): Micro<A, E | XE, R | XR> => onExitIf(self, exitIsFailure, (exit) => f(exit.left))
4660
+ ): Micro<A, E | XE, R | XR> => onExitIf(self, exitIsFailure, (exit) => f(exit.cause))
4296
4661
  )
4297
4662
 
4298
4663
  /**
@@ -4344,7 +4709,7 @@ export const acquireUseRelease = <Resource, E, R, A, E2, R2, E3, R3>(
4344
4709
  (a) =>
4345
4710
  flatMap(
4346
4711
  exit(restore(use(a))),
4347
- (exit) => andThen(release(a, exit), fromExit(exit))
4712
+ (exit) => andThen(release(a, exit), exit)
4348
4713
  )
4349
4714
  )
4350
4715
  )
@@ -4360,29 +4725,54 @@ export const acquireUseRelease = <Resource, E, R, A, E2, R2, E3, R3>(
4360
4725
  * @experimental
4361
4726
  * @category interruption
4362
4727
  */
4363
- export const interrupt: Micro<never> = make(function(env, onExit) {
4364
- const controller = envGet(env, currentAbortController)
4365
- controller.abort()
4366
- onExit(exitInterrupt)
4728
+ export const interrupt: Micro<never> = failCause(causeInterrupt())
4729
+
4730
+ /**
4731
+ * Flag the effect as uninterruptible, which means that when the effect is
4732
+ * interrupted, it will be allowed to continue running until completion.
4733
+ *
4734
+ * @since 3.4.0
4735
+ * @experimental
4736
+ * @category flags
4737
+ */
4738
+ export const uninterruptible = <A, E, R>(
4739
+ self: Micro<A, E, R>
4740
+ ): Micro<A, E, R> =>
4741
+ withFiber((fiber) => {
4742
+ if (!fiber.interruptible) return self
4743
+ fiber.interruptible = false
4744
+ fiber._stack.push(setInterruptible(true))
4745
+ return self
4746
+ })
4747
+
4748
+ const setInterruptible: (interruptible: boolean) => Primitive = makePrimitive({
4749
+ op: "SetInterruptible",
4750
+ ensure(fiber) {
4751
+ fiber.interruptible = this[args]
4752
+ if (fiber._interrupted && fiber.interruptible) {
4753
+ return () => exitInterrupt
4754
+ }
4755
+ }
4367
4756
  })
4368
4757
 
4369
4758
  /**
4370
- * Wrap the given `Micro` effect in an uninterruptible region, preventing the
4371
- * effect from being aborted.
4759
+ * Flag the effect as interruptible, which means that when the effect is
4760
+ * interrupted, it will be interrupted immediately.
4372
4761
  *
4373
4762
  * @since 3.4.0
4374
4763
  * @experimental
4375
- * @category interruption
4764
+ * @category flags
4376
4765
  */
4377
- export const uninterruptible = <A, E, R>(self: Micro<A, E, R>): Micro<A, E, R> =>
4378
- unsafeMakeOptions(function(env, onExit) {
4379
- const nextEnv = envMutate(env, function(env) {
4380
- env[currentInterruptible.key] = false
4381
- env[currentAbortSignal.key] = new AbortController().signal
4382
- return env
4383
- })
4384
- self[runSymbol](nextEnv, onExit)
4385
- }, false)
4766
+ export const interruptible = <A, E, R>(
4767
+ self: Micro<A, E, R>
4768
+ ): Micro<A, E, R> =>
4769
+ withFiber((fiber) => {
4770
+ if (fiber.interruptible) return self
4771
+ fiber.interruptible = true
4772
+ fiber._stack.push(setInterruptible(false))
4773
+ if (fiber._interrupted) return exitInterrupt
4774
+ return self
4775
+ })
4386
4776
 
4387
4777
  /**
4388
4778
  * Wrap the given `Micro` effect in an uninterruptible region, preventing the
@@ -4395,6 +4785,7 @@ export const uninterruptible = <A, E, R>(self: Micro<A, E, R>): Micro<A, E, R> =
4395
4785
  * @experimental
4396
4786
  * @category interruption
4397
4787
  * @example
4788
+ * ```ts
4398
4789
  * import * as Micro from "effect/Micro"
4399
4790
  *
4400
4791
  * Micro.uninterruptibleMask((restore) =>
@@ -4402,44 +4793,18 @@ export const uninterruptible = <A, E, R>(self: Micro<A, E, R>): Micro<A, E, R> =
4402
4793
  * Micro.andThen(restore(Micro.sleep(1000))) // interruptible
4403
4794
  * )
4404
4795
  * )
4796
+ * ```
4405
4797
  */
4406
4798
  export const uninterruptibleMask = <A, E, R>(
4407
- f: (restore: <A, E, R>(effect: Micro<A, E, R>) => Micro<A, E, R>) => Micro<A, E, R>
4799
+ f: (
4800
+ restore: <A, E, R>(effect: Micro<A, E, R>) => Micro<A, E, R>
4801
+ ) => Micro<A, E, R>
4408
4802
  ): Micro<A, E, R> =>
4409
- unsafeMakeOptions((env, onExit) => {
4410
- const isInterruptible = envGet(env, currentInterruptible)
4411
- const effect = isInterruptible ? f(interruptible) : f(identity)
4412
- const nextEnv = isInterruptible ?
4413
- envMutate(env, function(env) {
4414
- env[currentInterruptible.key] = false
4415
- env[currentAbortSignal.key] = new AbortController().signal
4416
- return env
4417
- }) :
4418
- env
4419
- effect[runSymbol](nextEnv, onExit)
4420
- }, false)
4421
-
4422
- /**
4423
- * Wrap the given `Micro` effect in an interruptible region, allowing the effect
4424
- * to be aborted.
4425
- *
4426
- * @since 3.4.0
4427
- * @experimental
4428
- * @category interruption
4429
- */
4430
- export const interruptible = <A, E, R>(self: Micro<A, E, R>): Micro<A, E, R> =>
4431
- make((env, onExit) => {
4432
- const isInterruptible = envGet(env, currentInterruptible)
4433
- let newEnv = env
4434
- if (!isInterruptible) {
4435
- const controller = envGet(env, currentAbortController)
4436
- newEnv = envMutate(env, function(env) {
4437
- env[currentInterruptible.key] = true
4438
- env[currentAbortSignal.key] = controller.signal
4439
- return env
4440
- })
4441
- }
4442
- self[runSymbol](newEnv, onExit)
4803
+ withFiber((fiber) => {
4804
+ if (!fiber.interruptible) return f(identity)
4805
+ fiber.interruptible = false
4806
+ fiber._stack.push(setInterruptible(true))
4807
+ return f(interruptible)
4443
4808
  })
4444
4809
 
4445
4810
  // ========================================================================
@@ -4559,6 +4924,34 @@ export const all = <
4559
4924
  }) as any
4560
4925
  }
4561
4926
 
4927
+ /**
4928
+ * @since 3.11.0
4929
+ * @experimental
4930
+ * @category collecting & elements
4931
+ */
4932
+ export const whileLoop: <A, E, R>(options: {
4933
+ readonly while: LazyArg<boolean>
4934
+ readonly body: LazyArg<Micro<A, E, R>>
4935
+ readonly step: (a: A) => void
4936
+ }) => Micro<void, E, R> = makePrimitive({
4937
+ op: "While",
4938
+ contA(value, fiber) {
4939
+ this[args].step(value)
4940
+ if (this[args].while()) {
4941
+ fiber._stack.push(this)
4942
+ return this[args].body()
4943
+ }
4944
+ return exitVoid
4945
+ },
4946
+ eval(fiber) {
4947
+ if (this[args].while()) {
4948
+ fiber._stack.push(this)
4949
+ return this[args].body()
4950
+ }
4951
+ return exitVoid
4952
+ }
4953
+ })
4954
+
4562
4955
  /**
4563
4956
  * For each element of the provided iterable, run the effect and collect the results.
4564
4957
  *
@@ -4624,64 +5017,89 @@ export const forEach: {
4624
5017
  readonly concurrency?: Concurrency | undefined
4625
5018
  readonly discard?: boolean | undefined
4626
5019
  }): Micro<any, E, R> =>
4627
- make(function(env, onExit) {
5020
+ withFiber((parent) => {
4628
5021
  const concurrencyOption = options?.concurrency === "inherit"
4629
- ? envGet(env, currentConcurrency)
5022
+ ? parent.getRef(CurrentConcurrency)
4630
5023
  : options?.concurrency ?? 1
4631
5024
  const concurrency = concurrencyOption === "unbounded"
4632
5025
  ? Number.POSITIVE_INFINITY
4633
5026
  : Math.max(1, concurrencyOption)
4634
5027
 
4635
- // abort
4636
- const [envWithSignal, onAbort] = forkSignal(env)
4637
-
4638
- // iterate
4639
- let result: MicroExit<any, any> | undefined = undefined
4640
- const items = Array.from(iterable)
5028
+ const items = Arr.fromIterable(iterable)
4641
5029
  let length = items.length
4642
5030
  if (length === 0) {
4643
- return onExit(Either.right(options?.discard ? undefined : []))
5031
+ return options?.discard ? void_ : succeed([])
4644
5032
  }
5033
+
4645
5034
  const out: Array<B> | undefined = options?.discard ? undefined : new Array(length)
4646
5035
  let index = 0
4647
- let inProgress = 0
4648
- let doneCount = 0
4649
- let pumping = false
4650
- function pump() {
4651
- pumping = true
4652
- while (inProgress < concurrency && index < length) {
4653
- const currentIndex = index
4654
- const item = items[currentIndex]
4655
- index++
4656
- inProgress++
4657
- try {
4658
- f(item, currentIndex)[runSymbol](envWithSignal, function(exit) {
4659
- if (exit._tag === "Left") {
4660
- if (result === undefined) {
4661
- result = exit
4662
- length = index
4663
- onAbort()
5036
+
5037
+ if (concurrency === 1) {
5038
+ return as(
5039
+ whileLoop({
5040
+ while: () => index < items.length,
5041
+ body: () => f(items[index], index),
5042
+ step: out ?
5043
+ (b) => out[index++] = b :
5044
+ (_) => index++
5045
+ }),
5046
+ out as any
5047
+ )
5048
+ }
5049
+ return async((resume) => {
5050
+ const fibers = new Set<Fiber<unknown, unknown>>()
5051
+ let result: MicroExit<any, any> | undefined = undefined
5052
+ let inProgress = 0
5053
+ let doneCount = 0
5054
+ let pumping = false
5055
+ let interrupted = false
5056
+ function pump() {
5057
+ pumping = true
5058
+ while (inProgress < concurrency && index < length) {
5059
+ const currentIndex = index
5060
+ const item = items[currentIndex]
5061
+ index++
5062
+ inProgress++
5063
+ try {
5064
+ const child = unsafeFork(parent, f(item, currentIndex), true, true)
5065
+ fibers.add(child)
5066
+ child.addObserver((exit) => {
5067
+ fibers.delete(child)
5068
+ if (interrupted) {
5069
+ return
5070
+ } else if (exit._tag === "Failure") {
5071
+ if (result === undefined) {
5072
+ result = exit
5073
+ length = index
5074
+ fibers.forEach((fiber) => fiber.unsafeInterrupt())
5075
+ }
5076
+ } else if (out !== undefined) {
5077
+ out[currentIndex] = exit.value
4664
5078
  }
4665
- } else if (out !== undefined) {
4666
- out[currentIndex] = exit.right
4667
- }
4668
- doneCount++
4669
- inProgress--
4670
- if (doneCount === length) {
4671
- onExit(result ?? Either.right(out))
4672
- } else if (!pumping && inProgress < concurrency) {
4673
- pump()
4674
- }
4675
- })
4676
- } catch (err) {
4677
- result = exitDie(err)
4678
- length = index
4679
- onAbort()
5079
+ doneCount++
5080
+ inProgress--
5081
+ if (doneCount === length) {
5082
+ resume(result ?? succeed(out))
5083
+ } else if (!pumping && inProgress < concurrency) {
5084
+ pump()
5085
+ }
5086
+ })
5087
+ } catch (err) {
5088
+ result = exitDie(err)
5089
+ length = index
5090
+ fibers.forEach((fiber) => fiber.unsafeInterrupt())
5091
+ }
4680
5092
  }
5093
+ pumping = false
4681
5094
  }
4682
- pumping = false
4683
- }
4684
- pump()
5095
+ pump()
5096
+
5097
+ return suspend(() => {
5098
+ interrupted = true
5099
+ index = length
5100
+ return fiberInterruptAll(fibers)
5101
+ })
5102
+ })
4685
5103
  })
4686
5104
 
4687
5105
  /**
@@ -4831,151 +5249,9 @@ export {
4831
5249
  }
4832
5250
 
4833
5251
  // ----------------------------------------------------------------------------
4834
- // handle & forking
5252
+ // fibers & forking
4835
5253
  // ----------------------------------------------------------------------------
4836
5254
 
4837
- /**
4838
- * @since 3.4.0
4839
- * @experimental
4840
- * @category handle & forking
4841
- */
4842
- export const HandleTypeId: unique symbol = Symbol.for("effect/Micro/Handle")
4843
-
4844
- /**
4845
- * @since 3.4.0
4846
- * @experimental
4847
- * @category handle & forking
4848
- */
4849
- export type HandleTypeId = typeof HandleTypeId
4850
-
4851
- /**
4852
- * @since 3.4.0
4853
- * @experimental
4854
- * @category handle & forking
4855
- */
4856
- export interface Handle<A, E = never> extends Micro<A, E> {
4857
- readonly [HandleTypeId]: HandleTypeId
4858
- readonly await: Micro<MicroExit<A, E>>
4859
- readonly join: Micro<A, E>
4860
- readonly interrupt: Micro<MicroExit<A, E>>
4861
- readonly unsafeInterrupt: () => void
4862
- readonly addObserver: (observer: (exit: MicroExit<A, E>) => void) => void
4863
- readonly removeObserver: (observer: (exit: MicroExit<A, E>) => void) => void
4864
- readonly unsafePoll: () => MicroExit<A, E> | null
4865
-
4866
- [Unify.typeSymbol]?: unknown
4867
- [Unify.unifySymbol]?: HandleUnify<this>
4868
- [Unify.ignoreSymbol]?: HandleUnifyIgnore
4869
- }
4870
-
4871
- /**
4872
- * @category models
4873
- * @since 3.8.4
4874
- * @experimental
4875
- */
4876
- export interface HandleUnify<A extends { [Unify.typeSymbol]?: any }> extends MicroUnify<A> {
4877
- Handle?: () => A[Unify.typeSymbol] extends Handle<infer A0, infer E0> | infer _ ? Handle<A0, E0> : never
4878
- }
4879
-
4880
- /**
4881
- * @category models
4882
- * @since 3.8.4
4883
- * @experimental
4884
- */
4885
- export interface HandleUnifyIgnore extends MicroUnifyIgnore {
4886
- Micro?: true
4887
- }
4888
-
4889
- /**
4890
- * @since 3.4.0
4891
- * @experimental
4892
- * @category handle & forking
4893
- */
4894
- export const isHandle = (u: unknown): u is Handle<unknown, unknown> =>
4895
- typeof u === "object" && u !== null && HandleTypeId in u
4896
-
4897
- class HandleImpl<A, E> extends Class<A, E> implements Handle<A, E> {
4898
- readonly [HandleTypeId]: HandleTypeId
4899
-
4900
- readonly observers: Set<(exit: MicroExit<A, E>) => void> = new Set()
4901
- private _exit: MicroExit<A, E> | undefined = undefined
4902
- _controller: AbortController
4903
- readonly isRoot: boolean
4904
-
4905
- constructor(readonly parentSignal: AbortSignal, controller?: AbortController) {
4906
- super()
4907
- this[HandleTypeId] = HandleTypeId
4908
- this.isRoot = controller !== undefined
4909
- this._controller = controller ?? new AbortController()
4910
- if (!this.isRoot) {
4911
- parentSignal.addEventListener("abort", this.unsafeInterrupt)
4912
- }
4913
- }
4914
-
4915
- unsafePoll(): MicroExit<A, E> | null {
4916
- return this._exit ?? null
4917
- }
4918
-
4919
- unsafeInterrupt = () => {
4920
- this._controller.abort()
4921
- }
4922
-
4923
- emit(exit: MicroExit<A, E>): void {
4924
- if (this._exit) {
4925
- return
4926
- }
4927
- this._exit = exit
4928
- if (!this.isRoot) {
4929
- this.parentSignal.removeEventListener("abort", this.unsafeInterrupt)
4930
- }
4931
- this.observers.forEach((observer) => observer(exit))
4932
- this.observers.clear()
4933
- }
4934
-
4935
- addObserver(observer: (exit: MicroExit<A, E>) => void): void {
4936
- if (this._exit) {
4937
- return observer(this._exit)
4938
- }
4939
- this.observers.add(observer)
4940
- }
4941
-
4942
- removeObserver(observer: (exit: MicroExit<A, E>) => void): void {
4943
- this.observers.delete(observer)
4944
- }
4945
-
4946
- get await(): Micro<MicroExit<A, E>> {
4947
- return suspend(() => {
4948
- if (this._exit) {
4949
- return succeed(this._exit)
4950
- }
4951
- return async((resume) => {
4952
- function observer(exit: MicroExit<A, E>) {
4953
- resume(succeed(exit))
4954
- }
4955
- this.addObserver(observer)
4956
- return sync(() => {
4957
- this.removeObserver(observer)
4958
- })
4959
- })
4960
- })
4961
- }
4962
-
4963
- get join(): Micro<A, E> {
4964
- return flatMap(this.await, fromExit)
4965
- }
4966
-
4967
- get interrupt(): Micro<MicroExit<A, E>> {
4968
- return suspend(() => {
4969
- this.unsafeInterrupt()
4970
- return this.await
4971
- })
4972
- }
4973
-
4974
- asMicro(): Micro<A, E> {
4975
- return this.join
4976
- }
4977
- }
4978
-
4979
5255
  /**
4980
5256
  * Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
4981
5257
  * aborted.
@@ -4986,23 +5262,33 @@ class HandleImpl<A, E> extends Class<A, E> implements Handle<A, E> {
4986
5262
  * @experimental
4987
5263
  * @category handle & forking
4988
5264
  */
4989
- export const fork = <A, E, R>(self: Micro<A, E, R>): Micro<Handle<A, E>, never, R> =>
4990
- make(function(env, onExit) {
4991
- const signal = envGet(env, currentAbortSignal)
4992
- const handle = new HandleImpl<A, E>(signal)
4993
- const nextEnv = envMutate(env, (map) => {
4994
- map[currentAbortController.key] = handle._controller
4995
- map[currentAbortSignal.key] = handle._controller.signal
4996
- return map
4997
- })
4998
- envGet(env, currentScheduler).scheduleTask(() => {
4999
- self[runSymbol](nextEnv, (exit) => {
5000
- handle.emit(exit)
5001
- })
5002
- }, 0)
5003
- onExit(Either.right(handle))
5265
+ export const fork = <A, E, R>(
5266
+ self: Micro<A, E, R>
5267
+ ): Micro<Fiber<A, E>, never, R> =>
5268
+ withFiber((fiber) => {
5269
+ fiberMiddleware.interruptChildren ??= fiberInterruptChildren
5270
+ return succeed(unsafeFork(fiber, self))
5004
5271
  })
5005
5272
 
5273
+ const unsafeFork = <FA, FE, A, E, R>(
5274
+ parent: FiberImpl<FA, FE>,
5275
+ effect: Micro<A, E, R>,
5276
+ immediate = false,
5277
+ daemon = false
5278
+ ): Fiber<A, E> => {
5279
+ const child = new FiberImpl<A, E>(parent.context, parent.interruptible)
5280
+ if (!daemon) {
5281
+ parent.children().add(child)
5282
+ child.addObserver(() => parent.children().delete(child))
5283
+ }
5284
+ if (immediate) {
5285
+ child.evaluate(effect as any)
5286
+ } else {
5287
+ parent.getRef(CurrentScheduler).scheduleTask(() => child.evaluate(effect as any), 0)
5288
+ }
5289
+ return child
5290
+ }
5291
+
5006
5292
  /**
5007
5293
  * Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
5008
5294
  * aborted.
@@ -5013,22 +5299,9 @@ export const fork = <A, E, R>(self: Micro<A, E, R>): Micro<Handle<A, E>, never,
5013
5299
  * @experimental
5014
5300
  * @category handle & forking
5015
5301
  */
5016
- export const forkDaemon = <A, E, R>(self: Micro<A, E, R>): Micro<Handle<A, E>, never, R> =>
5017
- make(function(env, onExit) {
5018
- const controller = new AbortController()
5019
- const handle = new HandleImpl<A, E>(controller.signal, controller)
5020
- const nextEnv = envMutate(env, (map) => {
5021
- map[currentAbortController.key] = controller
5022
- map[currentAbortSignal.key] = controller.signal
5023
- return map
5024
- })
5025
- envGet(env, currentScheduler).scheduleTask(() => {
5026
- self[runSymbol](nextEnv, (exit) => {
5027
- handle.emit(exit)
5028
- })
5029
- }, 0)
5030
- onExit(Either.right(handle))
5031
- })
5302
+ export const forkDaemon = <A, E, R>(
5303
+ self: Micro<A, E, R>
5304
+ ): Micro<Fiber<A, E>, never, R> => withFiber((fiber) => succeed(unsafeFork(fiber, self, false, true)))
5032
5305
 
5033
5306
  /**
5034
5307
  * Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
@@ -5051,7 +5324,7 @@ export const forkIn: {
5051
5324
  * @experimental
5052
5325
  * @category handle & forking
5053
5326
  */
5054
- (scope: MicroScope): <A, E, R>(self: Micro<A, E, R>) => Micro<Handle<A, E>, never, R>
5327
+ (scope: MicroScope): <A, E, R>(self: Micro<A, E, R>) => Micro<Fiber<A, E>, never, R>
5055
5328
  /**
5056
5329
  * Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
5057
5330
  * aborted.
@@ -5062,15 +5335,15 @@ export const forkIn: {
5062
5335
  * @experimental
5063
5336
  * @category handle & forking
5064
5337
  */
5065
- <A, E, R>(self: Micro<A, E, R>, scope: MicroScope): Micro<Handle<A, E>, never, R>
5338
+ <A, E, R>(self: Micro<A, E, R>, scope: MicroScope): Micro<Fiber<A, E>, never, R>
5066
5339
  } = dual(
5067
5340
  2,
5068
- <A, E, R>(self: Micro<A, E, R>, scope: MicroScope): Micro<Handle<A, E>, never, R> =>
5341
+ <A, E, R>(self: Micro<A, E, R>, scope: MicroScope): Micro<Fiber<A, E>, never, R> =>
5069
5342
  uninterruptibleMask((restore) =>
5070
5343
  flatMap(scope.fork, (scope) =>
5071
5344
  tap(
5072
5345
  restore(forkDaemon(onExit(self, (exit) => scope.close(exit)))),
5073
- (fiber) => scope.addFinalizer((_) => asVoid(fiber.interrupt))
5346
+ (fiber) => scope.addFinalizer((_) => fiberInterrupt(fiber))
5074
5347
  ))
5075
5348
  )
5076
5349
  )
@@ -5085,7 +5358,7 @@ export const forkIn: {
5085
5358
  * @experimental
5086
5359
  * @category handle & forking
5087
5360
  */
5088
- export const forkScoped = <A, E, R>(self: Micro<A, E, R>): Micro<Handle<A, E>, never, R | MicroScope> =>
5361
+ export const forkScoped = <A, E, R>(self: Micro<A, E, R>): Micro<Fiber<A, E>, never, R | MicroScope> =>
5089
5362
  flatMap(scope, (scope) => forkIn(self, scope))
5090
5363
 
5091
5364
  // ----------------------------------------------------------------------------
@@ -5103,6 +5376,7 @@ export const forkScoped = <A, E, R>(self: Micro<A, E, R>): Micro<Handle<A, E>, n
5103
5376
  * @experimental
5104
5377
  * @category execution
5105
5378
  * @example
5379
+ * ```ts
5106
5380
  * import * as Micro from "effect/Micro"
5107
5381
  *
5108
5382
  * const handle = Micro.succeed(42).pipe(
@@ -5113,6 +5387,7 @@ export const forkScoped = <A, E, R>(self: Micro<A, E, R>): Micro<Handle<A, E>, n
5113
5387
  * handle.addObserver((exit) => {
5114
5388
  * console.log(exit)
5115
5389
  * })
5390
+ * ```
5116
5391
  */
5117
5392
  export const runFork = <A, E>(
5118
5393
  effect: Micro<A, E>,
@@ -5120,28 +5395,21 @@ export const runFork = <A, E>(
5120
5395
  readonly signal?: AbortSignal | undefined
5121
5396
  readonly scheduler?: MicroScheduler | undefined
5122
5397
  } | undefined
5123
- ): Handle<A, E> => {
5124
- const controller = new AbortController()
5125
- const refs = Object.create(null)
5126
- refs[currentAbortController.key] = controller
5127
- refs[currentAbortSignal.key] = controller.signal
5128
- refs[currentScheduler.key] = options?.scheduler ?? new MicroSchedulerDefault()
5129
- const env = envMake(refs)
5130
- const handle = new HandleImpl<A, E>(controller.signal, controller)
5131
- effect[runSymbol](envSet(env, currentAbortSignal, handle._controller.signal), (exit) => {
5132
- handle.emit(exit)
5133
- if (options?.signal) {
5134
- options.signal.removeEventListener("abort", handle.unsafeInterrupt)
5135
- }
5136
- })
5398
+ ): FiberImpl<A, E> => {
5399
+ const fiber = new FiberImpl<A, E>(CurrentScheduler.context(
5400
+ options?.scheduler ?? new MicroSchedulerDefault()
5401
+ ))
5402
+ fiber.evaluate(effect as any)
5137
5403
  if (options?.signal) {
5138
5404
  if (options.signal.aborted) {
5139
- handle.unsafeInterrupt()
5405
+ fiber.unsafeInterrupt()
5140
5406
  } else {
5141
- options.signal.addEventListener("abort", handle.unsafeInterrupt, { once: true })
5407
+ const abort = () => fiber.unsafeInterrupt()
5408
+ options.signal.addEventListener("abort", abort, { once: true })
5409
+ fiber.addObserver(() => options.signal!.removeEventListener("abort", abort))
5142
5410
  }
5143
5411
  }
5144
- return handle
5412
+ return fiber
5145
5413
  }
5146
5414
 
5147
5415
  /**
@@ -5180,10 +5448,10 @@ export const runPromise = <A, E>(
5180
5448
  } | undefined
5181
5449
  ): Promise<A> =>
5182
5450
  runPromiseExit(effect, options).then((exit) => {
5183
- if (exit._tag === "Left") {
5184
- throw exit.left
5451
+ if (exit._tag === "Failure") {
5452
+ throw exit.cause
5185
5453
  }
5186
- return exit.right
5454
+ return exit.value
5187
5455
  })
5188
5456
 
5189
5457
  /**
@@ -5198,13 +5466,9 @@ export const runPromise = <A, E>(
5198
5466
  */
5199
5467
  export const runSyncExit = <A, E>(effect: Micro<A, E>): MicroExit<A, E> => {
5200
5468
  const scheduler = new MicroSchedulerDefault()
5201
- const handle = runFork(effect, { scheduler })
5469
+ const fiber = runFork(effect, { scheduler })
5202
5470
  scheduler.flush()
5203
- const exit = handle.unsafePoll()
5204
- if (exit === null) {
5205
- return exitDie(handle)
5206
- }
5207
- return exit
5471
+ return fiber._exit ?? exitDie(fiber)
5208
5472
  }
5209
5473
 
5210
5474
  /**
@@ -5217,10 +5481,8 @@ export const runSyncExit = <A, E>(effect: Micro<A, E>): MicroExit<A, E> => {
5217
5481
  */
5218
5482
  export const runSync = <A, E>(effect: Micro<A, E>): A => {
5219
5483
  const exit = runSyncExit(effect)
5220
- if (exit._tag === "Left") {
5221
- throw exit.left
5222
- }
5223
- return exit.right
5484
+ if (exit._tag === "Failure") throw exit.cause
5485
+ return exit.value
5224
5486
  }
5225
5487
 
5226
5488
  // ----------------------------------------------------------------------------
@@ -5233,35 +5495,35 @@ export const runSync = <A, E>(effect: Micro<A, E>): A => {
5233
5495
  * @category errors
5234
5496
  */
5235
5497
  export interface YieldableError extends Pipeable, Inspectable, Readonly<Error> {
5236
- readonly [EffectTypeId]: Effect.VarianceStruct<never, this, never>
5237
- readonly [StreamTypeId]: Stream.VarianceStruct<never, this, never>
5238
- readonly [SinkTypeId]: Sink.VarianceStruct<never, unknown, never, this, never>
5239
- readonly [ChannelTypeId]: Channel.VarianceStruct<never, unknown, this, unknown, never, unknown, never>
5498
+ readonly [Effectable.EffectTypeId]: Effect.VarianceStruct<never, this, never>
5499
+ readonly [Effectable.StreamTypeId]: Stream.VarianceStruct<never, this, never>
5500
+ readonly [Effectable.SinkTypeId]: Sink.VarianceStruct<never, unknown, never, this, never>
5501
+ readonly [Effectable.ChannelTypeId]: Channel.VarianceStruct<never, unknown, this, unknown, never, unknown, never>
5240
5502
  readonly [TypeId]: Micro.Variance<never, this, never>
5241
- readonly [runSymbol]: (env: Env<any>, onExit: (exit: MicroExit<never, this>) => void) => void
5242
5503
  [Symbol.iterator](): MicroIterator<Micro<never, this, never>>
5243
5504
  }
5244
5505
 
5245
5506
  const YieldableError: new(message?: string) => YieldableError = (function() {
5246
- class YieldableError extends globalThis.Error {
5247
- [runSymbol](_env: any, onExit: any) {
5248
- onExit(exitFail(this))
5249
- }
5250
- toString() {
5507
+ class YieldableError extends globalThis.Error {}
5508
+ Object.assign(YieldableError.prototype, MicroProto, StructuralPrototype, {
5509
+ [identifier]: "Failure",
5510
+ [evaluate]() {
5511
+ return fail(this)
5512
+ },
5513
+ toString(this: Error) {
5251
5514
  return this.message ? `${this.name}: ${this.message}` : this.name
5252
- }
5515
+ },
5253
5516
  toJSON() {
5254
5517
  return { ...this }
5255
- }
5256
- [NodeInspectSymbol](): string {
5518
+ },
5519
+ [NodeInspectSymbol](this: Error): string {
5257
5520
  const stack = this.stack
5258
5521
  if (stack) {
5259
5522
  return `${this.toString()}\n${stack.split("\n").slice(1).join("\n")}`
5260
5523
  }
5261
5524
  return this.toString()
5262
5525
  }
5263
- }
5264
- Object.assign(YieldableError.prototype, MicroProto, StructuralPrototype)
5526
+ })
5265
5527
  return YieldableError as any
5266
5528
  })()
5267
5529