effect 4.0.3 → 4.0.5

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 (449) hide show
  1. package/AGENTS.md +24 -0
  2. package/CLAUDE.md +24 -0
  3. package/ai-docs/package.json +2 -2
  4. package/ai-docs/src/52_graphql/10_basics.ts +117 -0
  5. package/ai-docs/src/52_graphql/20_testing.ts +45 -0
  6. package/ai-docs/src/52_graphql/30_batching.ts +118 -0
  7. package/ai-docs/src/52_graphql/40_aliased-batching.ts +124 -0
  8. package/ai-docs/src/52_graphql/50_errors-and-retries.ts +74 -0
  9. package/ai-docs/src/52_graphql/index.md +6 -0
  10. package/dist/Array.d.ts +90 -6
  11. package/dist/Array.d.ts.map +1 -1
  12. package/dist/Array.js +4 -2
  13. package/dist/Array.js.map +1 -1
  14. package/dist/Channel.d.ts +6 -1
  15. package/dist/Channel.d.ts.map +1 -1
  16. package/dist/Channel.js +17 -3
  17. package/dist/Channel.js.map +1 -1
  18. package/dist/ConfigProvider.d.ts.map +1 -1
  19. package/dist/ConfigProvider.js +33 -32
  20. package/dist/ConfigProvider.js.map +1 -1
  21. package/dist/Context.d.ts.map +1 -1
  22. package/dist/Context.js +9 -0
  23. package/dist/Context.js.map +1 -1
  24. package/dist/Duration.d.ts.map +1 -1
  25. package/dist/Duration.js +2 -5
  26. package/dist/Duration.js.map +1 -1
  27. package/dist/Effect.d.ts +61 -19
  28. package/dist/Effect.d.ts.map +1 -1
  29. package/dist/Effect.js +58 -39
  30. package/dist/Effect.js.map +1 -1
  31. package/dist/FileSystem.d.ts +23 -9
  32. package/dist/FileSystem.d.ts.map +1 -1
  33. package/dist/FileSystem.js.map +1 -1
  34. package/dist/Match.d.ts +20 -6
  35. package/dist/Match.d.ts.map +1 -1
  36. package/dist/Match.js +2 -2
  37. package/dist/Match.js.map +1 -1
  38. package/dist/Path.d.ts +37 -5
  39. package/dist/Path.d.ts.map +1 -1
  40. package/dist/Path.js +36 -5
  41. package/dist/Path.js.map +1 -1
  42. package/dist/RequestResolver.d.ts.map +1 -1
  43. package/dist/RequestResolver.js +4 -10
  44. package/dist/RequestResolver.js.map +1 -1
  45. package/dist/Scheduler.d.ts +9 -0
  46. package/dist/Scheduler.d.ts.map +1 -1
  47. package/dist/Scheduler.js +9 -0
  48. package/dist/Scheduler.js.map +1 -1
  49. package/dist/Schema.d.ts +15 -2
  50. package/dist/Schema.d.ts.map +1 -1
  51. package/dist/Schema.js +16 -2
  52. package/dist/Schema.js.map +1 -1
  53. package/dist/SchemaGetter.d.ts +4 -0
  54. package/dist/SchemaGetter.d.ts.map +1 -1
  55. package/dist/SchemaGetter.js +52 -33
  56. package/dist/SchemaGetter.js.map +1 -1
  57. package/dist/Sink.d.ts.map +1 -1
  58. package/dist/Sink.js +38 -17
  59. package/dist/Sink.js.map +1 -1
  60. package/dist/Stream.d.ts +11 -0
  61. package/dist/Stream.d.ts.map +1 -1
  62. package/dist/Stream.js +16 -1
  63. package/dist/Stream.js.map +1 -1
  64. package/dist/String.d.ts +12 -0
  65. package/dist/String.d.ts.map +1 -1
  66. package/dist/String.js +17 -4
  67. package/dist/String.js.map +1 -1
  68. package/dist/TxRef.d.ts.map +1 -1
  69. package/dist/TxRef.js +3 -2
  70. package/dist/TxRef.js.map +1 -1
  71. package/dist/Utils.js +8 -3
  72. package/dist/Utils.js.map +1 -1
  73. package/dist/ai/AiError.d.ts +10 -10
  74. package/dist/ai/AiError.d.ts.map +1 -1
  75. package/dist/ai/AiError.js +1 -1
  76. package/dist/ai/AiError.js.map +1 -1
  77. package/dist/ai/AnthropicStructuredOutput.js +0 -2
  78. package/dist/ai/AnthropicStructuredOutput.js.map +1 -1
  79. package/dist/ai/Chat.d.ts +2 -2
  80. package/dist/ai/Chat.d.ts.map +1 -1
  81. package/dist/ai/Decision.d.ts +70 -19
  82. package/dist/ai/Decision.d.ts.map +1 -1
  83. package/dist/ai/Decision.js +37 -3
  84. package/dist/ai/Decision.js.map +1 -1
  85. package/dist/ai/DecisionModel.js +1 -1
  86. package/dist/ai/DecisionModel.js.map +1 -1
  87. package/dist/ai/LanguageModel.d.ts +38 -7
  88. package/dist/ai/LanguageModel.d.ts.map +1 -1
  89. package/dist/ai/LanguageModel.js +70 -40
  90. package/dist/ai/LanguageModel.js.map +1 -1
  91. package/dist/ai/McpServer.d.ts +61 -52
  92. package/dist/ai/McpServer.d.ts.map +1 -1
  93. package/dist/ai/McpServer.js +134 -50
  94. package/dist/ai/McpServer.js.map +1 -1
  95. package/dist/ai/Prompt.d.ts.map +1 -1
  96. package/dist/ai/Prompt.js +28 -5
  97. package/dist/ai/Prompt.js.map +1 -1
  98. package/dist/ai/Response.d.ts +5 -4
  99. package/dist/ai/Response.d.ts.map +1 -1
  100. package/dist/ai/Response.js.map +1 -1
  101. package/dist/cli/Completions.d.ts +5 -0
  102. package/dist/cli/Completions.d.ts.map +1 -1
  103. package/dist/cli/Completions.js.map +1 -1
  104. package/dist/cli/Flag.d.ts +100 -0
  105. package/dist/cli/Flag.d.ts.map +1 -1
  106. package/dist/cli/Flag.js +33 -0
  107. package/dist/cli/Flag.js.map +1 -1
  108. package/dist/cli/Param.d.ts +87 -0
  109. package/dist/cli/Param.d.ts.map +1 -1
  110. package/dist/cli/Param.js +30 -0
  111. package/dist/cli/Param.js.map +1 -1
  112. package/dist/cli/internal/command.d.ts.map +1 -1
  113. package/dist/cli/internal/command.js +2 -1
  114. package/dist/cli/internal/command.js.map +1 -1
  115. package/dist/cli/internal/completions/bash.js +4 -3
  116. package/dist/cli/internal/completions/bash.js.map +1 -1
  117. package/dist/cli/internal/completions/descriptor.js +8 -1
  118. package/dist/cli/internal/completions/descriptor.js.map +1 -1
  119. package/dist/cli/internal/completions/fish.js +4 -4
  120. package/dist/cli/internal/completions/fish.js.map +1 -1
  121. package/dist/cli/internal/completions/powershell.js +3 -2
  122. package/dist/cli/internal/completions/powershell.js.map +1 -1
  123. package/dist/cli/internal/completions/zsh.js +7 -3
  124. package/dist/cli/internal/completions/zsh.js.map +1 -1
  125. package/dist/cli/internal/parser.js +11 -3
  126. package/dist/cli/internal/parser.js.map +1 -1
  127. package/dist/cli/internal/wizard.d.ts.map +1 -1
  128. package/dist/cli/internal/wizard.js +2 -1
  129. package/dist/cli/internal/wizard.js.map +1 -1
  130. package/dist/cluster/ClusterWorkflowEngine.d.ts +1 -0
  131. package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  132. package/dist/cluster/ClusterWorkflowEngine.js +113 -21
  133. package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
  134. package/dist/cluster/MessageStorage.d.ts.map +1 -1
  135. package/dist/cluster/MessageStorage.js +20 -12
  136. package/dist/cluster/MessageStorage.js.map +1 -1
  137. package/dist/cluster/Runners.d.ts.map +1 -1
  138. package/dist/cluster/Runners.js +54 -34
  139. package/dist/cluster/Runners.js.map +1 -1
  140. package/dist/cluster/Sharding.d.ts.map +1 -1
  141. package/dist/cluster/Sharding.js +6 -4
  142. package/dist/cluster/Sharding.js.map +1 -1
  143. package/dist/cluster/internal/entityManager.js +1 -1
  144. package/dist/cluster/internal/entityManager.js.map +1 -1
  145. package/dist/encoding/Sse.d.ts +6 -0
  146. package/dist/encoding/Sse.d.ts.map +1 -1
  147. package/dist/encoding/Sse.js +63 -71
  148. package/dist/encoding/Sse.js.map +1 -1
  149. package/dist/graphql/GraphQL.d.ts +349 -0
  150. package/dist/graphql/GraphQL.d.ts.map +1 -0
  151. package/dist/graphql/GraphQL.js +207 -0
  152. package/dist/graphql/GraphQL.js.map +1 -0
  153. package/dist/graphql/GraphQLClient.d.ts +562 -0
  154. package/dist/graphql/GraphQLClient.d.ts.map +1 -0
  155. package/dist/graphql/GraphQLClient.js +505 -0
  156. package/dist/graphql/GraphQLClient.js.map +1 -0
  157. package/dist/graphql/GraphQLClientError.d.ts +445 -0
  158. package/dist/graphql/GraphQLClientError.d.ts.map +1 -0
  159. package/dist/graphql/GraphQLClientError.js +479 -0
  160. package/dist/graphql/GraphQLClientError.js.map +1 -0
  161. package/dist/graphql/GraphQLGroup.d.ts +118 -0
  162. package/dist/graphql/GraphQLGroup.d.ts.map +1 -0
  163. package/dist/graphql/GraphQLGroup.js +109 -0
  164. package/dist/graphql/GraphQLGroup.js.map +1 -0
  165. package/dist/graphql/GraphQLMiddleware.d.ts +249 -0
  166. package/dist/graphql/GraphQLMiddleware.d.ts.map +1 -0
  167. package/dist/graphql/GraphQLMiddleware.js +130 -0
  168. package/dist/graphql/GraphQLMiddleware.js.map +1 -0
  169. package/dist/graphql/GraphQLProtocol.d.ts +969 -0
  170. package/dist/graphql/GraphQLProtocol.d.ts.map +1 -0
  171. package/dist/graphql/GraphQLProtocol.js +809 -0
  172. package/dist/graphql/GraphQLProtocol.js.map +1 -0
  173. package/dist/graphql/GraphQLResolver.d.ts +453 -0
  174. package/dist/graphql/GraphQLResolver.d.ts.map +1 -0
  175. package/dist/graphql/GraphQLResolver.js +582 -0
  176. package/dist/graphql/GraphQLResolver.js.map +1 -0
  177. package/dist/graphql/index.d.ts +40 -0
  178. package/dist/graphql/index.d.ts.map +1 -0
  179. package/dist/graphql/index.js +41 -0
  180. package/dist/graphql/index.js.map +1 -0
  181. package/dist/http/FetchHttpClient.d.ts +6 -3
  182. package/dist/http/FetchHttpClient.d.ts.map +1 -1
  183. package/dist/http/FetchHttpClient.js +6 -3
  184. package/dist/http/FetchHttpClient.js.map +1 -1
  185. package/dist/http/FindMyWay/internal/router.js +2 -1
  186. package/dist/http/FindMyWay/internal/router.js.map +1 -1
  187. package/dist/http/Headers.d.ts +3 -3
  188. package/dist/http/Headers.d.ts.map +1 -1
  189. package/dist/http/Headers.js +6 -5
  190. package/dist/http/Headers.js.map +1 -1
  191. package/dist/http/HttpClient.d.ts +27 -0
  192. package/dist/http/HttpClient.d.ts.map +1 -1
  193. package/dist/http/HttpClient.js +38 -11
  194. package/dist/http/HttpClient.js.map +1 -1
  195. package/dist/http/HttpClientError.d.ts.map +1 -1
  196. package/dist/http/HttpClientError.js +8 -6
  197. package/dist/http/HttpClientError.js.map +1 -1
  198. package/dist/http/HttpClientRequest.d.ts +147 -4
  199. package/dist/http/HttpClientRequest.d.ts.map +1 -1
  200. package/dist/http/HttpClientRequest.js +47 -1
  201. package/dist/http/HttpClientRequest.js.map +1 -1
  202. package/dist/http/HttpEffect.d.ts.map +1 -1
  203. package/dist/http/HttpEffect.js +14 -7
  204. package/dist/http/HttpEffect.js.map +1 -1
  205. package/dist/http/HttpMiddleware.d.ts +60 -0
  206. package/dist/http/HttpMiddleware.d.ts.map +1 -1
  207. package/dist/http/HttpMiddleware.js +93 -32
  208. package/dist/http/HttpMiddleware.js.map +1 -1
  209. package/dist/http/HttpRouter.d.ts +35 -0
  210. package/dist/http/HttpRouter.d.ts.map +1 -1
  211. package/dist/http/HttpRouter.js +87 -13
  212. package/dist/http/HttpRouter.js.map +1 -1
  213. package/dist/http/HttpServerError.d.ts.map +1 -1
  214. package/dist/http/HttpServerError.js +6 -4
  215. package/dist/http/HttpServerError.js.map +1 -1
  216. package/dist/http/HttpServerRequest.js +2 -2
  217. package/dist/http/HttpServerRequest.js.map +1 -1
  218. package/dist/http/HttpServerResponse.d.ts +8 -6
  219. package/dist/http/HttpServerResponse.d.ts.map +1 -1
  220. package/dist/http/HttpServerResponse.js +27 -16
  221. package/dist/http/HttpServerResponse.js.map +1 -1
  222. package/dist/http/HttpStaticServer.d.ts.map +1 -1
  223. package/dist/http/HttpStaticServer.js +4 -10
  224. package/dist/http/HttpStaticServer.js.map +1 -1
  225. package/dist/http/HttpTraceContext.js +1 -1
  226. package/dist/http/HttpTraceContext.js.map +1 -1
  227. package/dist/http/Multipart.d.ts.map +1 -1
  228. package/dist/http/Multipart.js +15 -1
  229. package/dist/http/Multipart.js.map +1 -1
  230. package/dist/http/Url.d.ts.map +1 -1
  231. package/dist/http/Url.js +2 -1
  232. package/dist/http/Url.js.map +1 -1
  233. package/dist/http/UrlParams.d.ts +112 -8
  234. package/dist/http/UrlParams.d.ts.map +1 -1
  235. package/dist/http/UrlParams.js +141 -14
  236. package/dist/http/UrlParams.js.map +1 -1
  237. package/dist/http/internal/compression.d.ts +1 -1
  238. package/dist/http/internal/compression.d.ts.map +1 -1
  239. package/dist/http/internal/compression.js +2 -10
  240. package/dist/http/internal/compression.js.map +1 -1
  241. package/dist/http/internal/compressionBody.d.ts +2 -0
  242. package/dist/http/internal/compressionBody.d.ts.map +1 -0
  243. package/dist/http/internal/compressionBody.js +36 -0
  244. package/dist/http/internal/compressionBody.js.map +1 -0
  245. package/dist/http/internal/decompression.d.ts +2 -0
  246. package/dist/http/internal/decompression.d.ts.map +1 -0
  247. package/dist/http/internal/decompression.js +162 -0
  248. package/dist/http/internal/decompression.js.map +1 -0
  249. package/dist/http/internal/tracing.js +14 -4
  250. package/dist/http/internal/tracing.js.map +1 -1
  251. package/dist/http/internal/urlParams.d.ts +2 -0
  252. package/dist/http/internal/urlParams.d.ts.map +1 -0
  253. package/dist/http/internal/urlParams.js +4 -0
  254. package/dist/http/internal/urlParams.js.map +1 -0
  255. package/dist/http-api/HttpApiClient.d.ts.map +1 -1
  256. package/dist/http-api/HttpApiClient.js +2 -1
  257. package/dist/http-api/HttpApiClient.js.map +1 -1
  258. package/dist/http-api/HttpApiScalar.d.ts +5 -0
  259. package/dist/http-api/HttpApiScalar.d.ts.map +1 -1
  260. package/dist/http-api/HttpApiScalar.js.map +1 -1
  261. package/dist/internal/core.js +17 -1
  262. package/dist/internal/core.js.map +1 -1
  263. package/dist/internal/dateTime.js +40 -35
  264. package/dist/internal/dateTime.js.map +1 -1
  265. package/dist/internal/effect.js +13 -6
  266. package/dist/internal/effect.js.map +1 -1
  267. package/dist/internal/graphql.d.ts +2 -0
  268. package/dist/internal/graphql.d.ts.map +1 -0
  269. package/dist/internal/graphql.js +205 -0
  270. package/dist/internal/graphql.js.map +1 -0
  271. package/dist/internal/graphqlHeaders.d.ts +4 -0
  272. package/dist/internal/graphqlHeaders.d.ts.map +1 -0
  273. package/dist/internal/graphqlHeaders.js +11 -0
  274. package/dist/internal/graphqlHeaders.js.map +1 -0
  275. package/dist/internal/request.js +20 -1
  276. package/dist/internal/request.js.map +1 -1
  277. package/dist/internal/schema/toCodeDocument.js +4 -1
  278. package/dist/internal/schema/toCodeDocument.js.map +1 -1
  279. package/dist/internal/schema/toJsonSchemaDocument.js +29 -5
  280. package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -1
  281. package/dist/internal/version.js +1 -1
  282. package/dist/net/Host.d.ts +49 -0
  283. package/dist/net/Host.d.ts.map +1 -1
  284. package/dist/net/Host.js +55 -0
  285. package/dist/net/Host.js.map +1 -1
  286. package/dist/net/NetAddress.d.ts +8 -0
  287. package/dist/net/NetAddress.d.ts.map +1 -1
  288. package/dist/net/NetAddress.js +8 -0
  289. package/dist/net/NetAddress.js.map +1 -1
  290. package/dist/observability/Otlp.d.ts +15 -0
  291. package/dist/observability/Otlp.d.ts.map +1 -1
  292. package/dist/observability/Otlp.js +3 -0
  293. package/dist/observability/Otlp.js.map +1 -1
  294. package/dist/observability/OtlpExporter.d.ts +8 -0
  295. package/dist/observability/OtlpExporter.d.ts.map +1 -1
  296. package/dist/observability/OtlpExporter.js +10 -1
  297. package/dist/observability/OtlpExporter.js.map +1 -1
  298. package/dist/observability/OtlpLogger.d.ts +17 -0
  299. package/dist/observability/OtlpLogger.d.ts.map +1 -1
  300. package/dist/observability/OtlpLogger.js +14 -1
  301. package/dist/observability/OtlpLogger.js.map +1 -1
  302. package/dist/observability/OtlpMetrics.d.ts +17 -0
  303. package/dist/observability/OtlpMetrics.d.ts.map +1 -1
  304. package/dist/observability/OtlpMetrics.js +13 -0
  305. package/dist/observability/OtlpMetrics.js.map +1 -1
  306. package/dist/observability/OtlpTracer.d.ts +17 -0
  307. package/dist/observability/OtlpTracer.d.ts.map +1 -1
  308. package/dist/observability/OtlpTracer.js +15 -2
  309. package/dist/observability/OtlpTracer.js.map +1 -1
  310. package/dist/reactivity/AsyncResult.d.ts +6 -0
  311. package/dist/reactivity/AsyncResult.d.ts.map +1 -1
  312. package/dist/reactivity/AsyncResult.js +27 -0
  313. package/dist/reactivity/AsyncResult.js.map +1 -1
  314. package/dist/reactivity/AtomRegistry.js +3 -1
  315. package/dist/reactivity/AtomRegistry.js.map +1 -1
  316. package/dist/rpc/RpcClient.d.ts.map +1 -1
  317. package/dist/rpc/RpcClient.js +6 -1
  318. package/dist/rpc/RpcClient.js.map +1 -1
  319. package/dist/rpc/RpcServer.d.ts.map +1 -1
  320. package/dist/rpc/RpcServer.js +36 -9
  321. package/dist/rpc/RpcServer.js.map +1 -1
  322. package/dist/socket/Socket.d.ts +6 -0
  323. package/dist/socket/Socket.d.ts.map +1 -1
  324. package/dist/socket/Socket.js.map +1 -1
  325. package/dist/sql/SqlClient.d.ts +8 -7
  326. package/dist/sql/SqlClient.d.ts.map +1 -1
  327. package/dist/sql/SqlClient.js +8 -7
  328. package/dist/sql/SqlClient.js.map +1 -1
  329. package/dist/testing/TestClock.d.ts +16 -3
  330. package/dist/testing/TestClock.d.ts.map +1 -1
  331. package/dist/testing/TestClock.js +112 -22
  332. package/dist/testing/TestClock.js.map +1 -1
  333. package/dist/workflow/Activity.js +1 -0
  334. package/dist/workflow/Activity.js.map +1 -1
  335. package/dist/workflow/DurableDeferred.d.ts.map +1 -1
  336. package/dist/workflow/DurableDeferred.js +32 -3
  337. package/dist/workflow/DurableDeferred.js.map +1 -1
  338. package/dist/workflow/Workflow.d.ts +22 -0
  339. package/dist/workflow/Workflow.d.ts.map +1 -1
  340. package/dist/workflow/Workflow.js +15 -3
  341. package/dist/workflow/Workflow.js.map +1 -1
  342. package/dist/workflow/WorkflowEngine.d.ts +44 -3
  343. package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
  344. package/dist/workflow/WorkflowEngine.js +45 -22
  345. package/dist/workflow/WorkflowEngine.js.map +1 -1
  346. package/package.json +6 -3
  347. package/src/Array.ts +95 -6
  348. package/src/Channel.ts +24 -3
  349. package/src/ConfigProvider.ts +40 -44
  350. package/src/Context.ts +9 -0
  351. package/src/Duration.ts +4 -5
  352. package/src/Effect.ts +140 -53
  353. package/src/FileSystem.ts +23 -9
  354. package/src/Match.ts +65 -12
  355. package/src/Path.ts +52 -7
  356. package/src/RequestResolver.ts +4 -10
  357. package/src/Scheduler.ts +9 -0
  358. package/src/Schema.ts +25 -4
  359. package/src/SchemaGetter.ts +47 -35
  360. package/src/Sink.ts +45 -18
  361. package/src/Stream.ts +33 -4
  362. package/src/String.ts +17 -4
  363. package/src/TxRef.ts +4 -2
  364. package/src/Utils.ts +8 -5
  365. package/src/ai/AiError.ts +3 -1
  366. package/src/ai/AnthropicStructuredOutput.ts +2 -2
  367. package/src/ai/Chat.ts +2 -2
  368. package/src/ai/Decision.ts +70 -21
  369. package/src/ai/DecisionModel.ts +1 -1
  370. package/src/ai/LanguageModel.ts +141 -63
  371. package/src/ai/McpServer.ts +259 -145
  372. package/src/ai/Prompt.ts +24 -10
  373. package/src/ai/Response.ts +6 -3
  374. package/src/cli/Completions.ts +5 -0
  375. package/src/cli/Flag.ts +101 -0
  376. package/src/cli/Param.ts +96 -0
  377. package/src/cli/internal/command.ts +2 -1
  378. package/src/cli/internal/completions/bash.ts +4 -3
  379. package/src/cli/internal/completions/descriptor.ts +10 -1
  380. package/src/cli/internal/completions/fish.ts +4 -4
  381. package/src/cli/internal/completions/powershell.ts +5 -2
  382. package/src/cli/internal/completions/zsh.ts +7 -3
  383. package/src/cli/internal/parser.ts +12 -3
  384. package/src/cli/internal/wizard.ts +2 -1
  385. package/src/cluster/ClusterWorkflowEngine.ts +143 -36
  386. package/src/cluster/MessageStorage.ts +14 -3
  387. package/src/cluster/Runners.ts +88 -66
  388. package/src/cluster/Sharding.ts +12 -9
  389. package/src/cluster/internal/entityManager.ts +1 -1
  390. package/src/encoding/Sse.ts +70 -80
  391. package/src/graphql/GraphQL.ts +494 -0
  392. package/src/graphql/GraphQLClient.ts +924 -0
  393. package/src/graphql/GraphQLClientError.ts +542 -0
  394. package/src/graphql/GraphQLGroup.ts +167 -0
  395. package/src/graphql/GraphQLMiddleware.ts +253 -0
  396. package/src/graphql/GraphQLProtocol.ts +1540 -0
  397. package/src/graphql/GraphQLResolver.ts +1038 -0
  398. package/src/graphql/index.ts +48 -0
  399. package/src/http/FetchHttpClient.ts +6 -3
  400. package/src/http/FindMyWay/internal/router.ts +2 -1
  401. package/src/http/Headers.ts +6 -9
  402. package/src/http/HttpClient.ts +72 -11
  403. package/src/http/HttpClientError.ts +10 -6
  404. package/src/http/HttpClientRequest.ts +173 -7
  405. package/src/http/HttpEffect.ts +11 -5
  406. package/src/http/HttpMiddleware.ts +113 -34
  407. package/src/http/HttpRouter.ts +95 -13
  408. package/src/http/HttpServerError.ts +8 -4
  409. package/src/http/HttpServerRequest.ts +2 -2
  410. package/src/http/HttpServerResponse.ts +28 -16
  411. package/src/http/HttpStaticServer.ts +4 -10
  412. package/src/http/HttpTraceContext.ts +1 -1
  413. package/src/http/Multipart.ts +17 -1
  414. package/src/http/Url.ts +2 -1
  415. package/src/http/UrlParams.ts +225 -26
  416. package/src/http/internal/compression.ts +3 -17
  417. package/src/http/internal/compressionBody.ts +56 -0
  418. package/src/http/internal/decompression.ts +226 -0
  419. package/src/http/internal/tracing.ts +21 -4
  420. package/src/http/internal/urlParams.ts +5 -0
  421. package/src/http-api/HttpApiClient.ts +2 -1
  422. package/src/http-api/HttpApiScalar.ts +5 -0
  423. package/src/internal/core.ts +21 -1
  424. package/src/internal/dateTime.ts +13 -10
  425. package/src/internal/effect.ts +13 -7
  426. package/src/internal/graphql.ts +286 -0
  427. package/src/internal/graphqlHeaders.ts +11 -0
  428. package/src/internal/request.ts +31 -3
  429. package/src/internal/schema/toCodeDocument.ts +7 -1
  430. package/src/internal/schema/toJsonSchemaDocument.ts +34 -2
  431. package/src/internal/version.ts +1 -1
  432. package/src/net/Host.ts +72 -0
  433. package/src/net/NetAddress.ts +9 -0
  434. package/src/observability/Otlp.ts +18 -0
  435. package/src/observability/OtlpExporter.ts +14 -3
  436. package/src/observability/OtlpLogger.ts +31 -2
  437. package/src/observability/OtlpMetrics.ts +30 -1
  438. package/src/observability/OtlpTracer.ts +32 -3
  439. package/src/reactivity/AsyncResult.ts +31 -0
  440. package/src/reactivity/AtomRegistry.ts +3 -1
  441. package/src/rpc/RpcClient.ts +6 -1
  442. package/src/rpc/RpcServer.ts +55 -15
  443. package/src/socket/Socket.ts +6 -0
  444. package/src/sql/SqlClient.ts +9 -7
  445. package/src/testing/TestClock.ts +144 -29
  446. package/src/workflow/Activity.ts +1 -0
  447. package/src/workflow/DurableDeferred.ts +43 -5
  448. package/src/workflow/Workflow.ts +31 -5
  449. package/src/workflow/WorkflowEngine.ts +107 -25
package/src/Array.ts CHANGED
@@ -521,8 +521,10 @@ export const fromOption: <A>(self: Option.Option<A>) => Array<A> = Option.toArra
521
521
  *
522
522
  * **Details**
523
523
  *
524
- * `onNonEmpty` receives a `NonEmptyReadonlyArray`. Supports both data-first and
525
- * data-last usage.
524
+ * `onNonEmpty` receives a `NonEmptyArray` for mutable arrays and a
525
+ * `NonEmptyReadonlyArray` otherwise. Data-last calls default to the readonly
526
+ * callback, so the returned function still accepts `ReadonlyArray`. Supports
527
+ * both data-first and data-last usage.
526
528
  *
527
529
  * **Example** (Branching on emptiness)
528
530
  *
@@ -555,8 +557,10 @@ export const match: {
555
557
  *
556
558
  * **Details**
557
559
  *
558
- * `onNonEmpty` receives a `NonEmptyReadonlyArray`. Supports both data-first and
559
- * data-last usage.
560
+ * `onNonEmpty` receives a `NonEmptyArray` for mutable arrays and a
561
+ * `NonEmptyReadonlyArray` otherwise. Data-last calls default to the readonly
562
+ * callback, so the returned function still accepts `ReadonlyArray`. Supports
563
+ * both data-first and data-last usage.
560
564
  *
561
565
  * **Example** (Branching on emptiness)
562
566
  *
@@ -594,8 +598,93 @@ export const match: {
594
598
  *
595
599
  * **Details**
596
600
  *
597
- * `onNonEmpty` receives a `NonEmptyReadonlyArray`. Supports both data-first and
598
- * data-last usage.
601
+ * `onNonEmpty` receives a `NonEmptyArray` for mutable arrays and a
602
+ * `NonEmptyReadonlyArray` otherwise. Data-last calls default to the readonly
603
+ * callback, so the returned function still accepts `ReadonlyArray`. Supports
604
+ * both data-first and data-last usage.
605
+ *
606
+ * **Example** (Branching on emptiness)
607
+ *
608
+ * ```ts import.meta.vitest
609
+ * import { Array } from "effect"
610
+ *
611
+ * const describe = Array.match({
612
+ * onEmpty: () => "empty",
613
+ * onNonEmpty: ([head, ...tail]) => `head: ${head}, tail: ${tail.length}`
614
+ * })
615
+ *
616
+ * describe([]) // => "empty"
617
+ * describe([1, 2, 3]) // => "head: 1, tail: 2"
618
+ * ```
619
+ *
620
+ * @see {@link matchLeft} — destructures into head + tail
621
+ * @see {@link matchRight} — destructures into init + last
622
+ *
623
+ * @stability stable
624
+ * @category pattern matching
625
+ * @since 2.0.0
626
+ */
627
+ <B, A, C = B>(
628
+ options: {
629
+ readonly onEmpty: LazyArg<B>
630
+ readonly onNonEmpty: (self: NonEmptyArray<A>) => C
631
+ }
632
+ ): (self: Array<A>) => B | C
633
+ /**
634
+ * Pattern-matches on an array, handling empty and non-empty cases separately.
635
+ *
636
+ * **When to use**
637
+ *
638
+ * Use when you need to branch on whether an array is empty.
639
+ *
640
+ * **Details**
641
+ *
642
+ * `onNonEmpty` receives a `NonEmptyArray` for mutable arrays and a
643
+ * `NonEmptyReadonlyArray` otherwise. Data-last calls default to the readonly
644
+ * callback, so the returned function still accepts `ReadonlyArray`. Supports
645
+ * both data-first and data-last usage.
646
+ *
647
+ * **Example** (Branching on emptiness)
648
+ *
649
+ * ```ts import.meta.vitest
650
+ * import { Array } from "effect"
651
+ *
652
+ * const describe = Array.match({
653
+ * onEmpty: () => "empty",
654
+ * onNonEmpty: ([head, ...tail]) => `head: ${head}, tail: ${tail.length}`
655
+ * })
656
+ *
657
+ * describe([]) // => "empty"
658
+ * describe([1, 2, 3]) // => "head: 1, tail: 2"
659
+ * ```
660
+ *
661
+ * @see {@link matchLeft} — destructures into head + tail
662
+ * @see {@link matchRight} — destructures into init + last
663
+ *
664
+ * @stability stable
665
+ * @category pattern matching
666
+ * @since 2.0.0
667
+ */
668
+ <A, B, C = B>(
669
+ self: Array<A>,
670
+ options: {
671
+ readonly onEmpty: LazyArg<B>
672
+ readonly onNonEmpty: (self: NonEmptyArray<A>) => C
673
+ }
674
+ ): B | C
675
+ /**
676
+ * Pattern-matches on an array, handling empty and non-empty cases separately.
677
+ *
678
+ * **When to use**
679
+ *
680
+ * Use when you need to branch on whether an array is empty.
681
+ *
682
+ * **Details**
683
+ *
684
+ * `onNonEmpty` receives a `NonEmptyArray` for mutable arrays and a
685
+ * `NonEmptyReadonlyArray` otherwise. Data-last calls default to the readonly
686
+ * callback, so the returned function still accepts `ReadonlyArray`. Supports
687
+ * both data-first and data-last usage.
599
688
  *
600
689
  * **Example** (Branching on emptiness)
601
690
  *
package/src/Channel.ts CHANGED
@@ -1984,7 +1984,9 @@ const readableStreamToPullUnsafe = <A, E, E2 = never>(options: {
1984
1984
  * Each yielded value is emitted as an output element. The iterator's return
1985
1985
  * value becomes the channel's done value. Thrown or rejected iterator errors
1986
1986
  * are converted with `onError`. If the channel scope closes early and the
1987
- * iterator has a `return` method, that method is called.
1987
+ * iterator has a `return` method, that method is called. It is awaited unless
1988
+ * a `next()` call is still pending, in which case its result is ignored and an
1989
+ * async generator may not run its cleanup until that pull settles.
1988
1990
  *
1989
1991
  * @stability stable
1990
1992
  * @category constructors
@@ -1996,12 +1998,28 @@ export const fromAsyncIterable = <A, D, E>(
1996
1998
  ): Channel<A, E, D> =>
1997
1999
  fromTransform(Effect.fnUntraced(function*(_, scope) {
1998
2000
  const iter = iterable[Symbol.asyncIterator]()
2001
+ let pulling = false
1999
2002
  if (iter.return) {
2000
- yield* Scope.addFinalizer(scope, Effect.promise(() => iter.return!()))
2003
+ // `return()` may not settle until a pending `next()` does, so only
2004
+ // await it when the iterator is idle.
2005
+ yield* Scope.addFinalizer(
2006
+ scope,
2007
+ Effect.suspend(() =>
2008
+ pulling
2009
+ ? Effect.sync(() => void iter.return!().catch(constVoid))
2010
+ : Effect.promise(() => iter.return!())
2011
+ )
2012
+ )
2001
2013
  }
2002
2014
  return Effect.flatMap(
2003
2015
  Effect.tryPromise({
2004
- try: () => iter.next(),
2016
+ try: () => {
2017
+ const promise = iter.next()
2018
+ pulling = true
2019
+ return promise.finally(() => {
2020
+ pulling = false
2021
+ })
2022
+ },
2005
2023
  catch: onError
2006
2024
  }),
2007
2025
  (result) => result.done ? Cause.done(result.value) : Effect.succeed(result.value)
@@ -2017,6 +2035,9 @@ export const fromAsyncIterable = <A, D, E>(
2017
2035
  * The iterator's return value becomes the channel's done value. Thrown or
2018
2036
  * rejected iterator errors are converted with `onError`. If the channel scope
2019
2037
  * closes early and the iterator has a `return` method, that method is called.
2038
+ * It is awaited unless a `next()` call is still pending, in which case its
2039
+ * result is ignored and an async generator may not run its cleanup until that
2040
+ * pull settles.
2020
2041
  *
2021
2042
  * @stability stable
2022
2043
  * @category constructors
@@ -1380,56 +1380,52 @@ function dotEnvExpand(parsed: Record<string, string>): Record<string, string> {
1380
1380
 
1381
1381
  for (const configKey of Object.keys(parsed)) {
1382
1382
  // resolve escape sequences
1383
- newParsed[configKey] = interpolate(parsed[configKey], parsed).replace(/\\\$/g, "$")
1383
+ newParsed[configKey] = interpolate(parsed[configKey], parsed, new Set([configKey])).replace(/\\\$/g, "$")
1384
1384
  }
1385
1385
 
1386
1386
  return newParsed
1387
1387
  }
1388
1388
 
1389
- function interpolate(envValue: string, parsed: Record<string, string>): string {
1390
- // find the last unescaped dollar sign in the
1391
- // value so that we can evaluate it
1392
- const lastUnescapedDollarSignIndex = searchLast(envValue, /(?!(?<=\\))\$/g)
1393
-
1394
- // If we couldn't match any unescaped dollar sign
1395
- // let's return the string as is
1396
- if (lastUnescapedDollarSignIndex === -1) return envValue
1397
-
1398
- // This is the right-most group of variables in the string
1399
- const rightMostGroup = envValue.slice(lastUnescapedDollarSignIndex)
1400
-
1401
- /**
1402
- * This finds the inner most variable/group divided
1403
- * by variable name and default value (if present)
1404
- * (
1405
- * (?!(?<=\\))\$ // only match dollar signs that are not escaped
1406
- * {? // optional opening curly brace
1407
- * ([\w]+) // match the variable name
1408
- * (?::-([^}\\]*))? // match an optional default value
1409
- * }? // optional closing curly brace
1410
- * )
1411
- */
1412
- const matchGroup = /((?!(?<=\\))\${?([\w]+)(?::-([^}\\]*))?}?)/
1413
- const match = rightMostGroup.match(matchGroup)
1414
-
1415
- if (match !== null) {
1416
- const [_, group, variableName, defaultValue] = match
1417
- const value = Object.hasOwn(parsed, variableName) && parsed[variableName] !== ""
1418
- ? parsed[variableName]
1419
- : defaultValue ?? ""
1420
-
1421
- return interpolate(
1422
- envValue.replace(group, () => value),
1423
- parsed
1424
- )
1389
+ function interpolate(
1390
+ envValue: string,
1391
+ parsed: Record<string, string>,
1392
+ seen: ReadonlySet<string>
1393
+ ): string {
1394
+ const reference = /(?<!\\)\${?(\w+)/g
1395
+ let result = ""
1396
+ let cursor = 0
1397
+ let match: RegExpExecArray | null
1398
+ while ((match = reference.exec(envValue)) != null) {
1399
+ const [, name] = match
1400
+ let end = reference.lastIndex
1401
+ let defaultValue = ""
1402
+ if (envValue.startsWith(":-", end)) {
1403
+ end += 2
1404
+ const start = end
1405
+ let depth = 0
1406
+ // Match default braces in the source, not in substituted values.
1407
+ for (; end < envValue.length; end++) {
1408
+ if (envValue.startsWith("${", end)) {
1409
+ depth++
1410
+ end++
1411
+ } else if (envValue[end] === "}") {
1412
+ if (depth === 0) break
1413
+ depth--
1414
+ }
1415
+ }
1416
+ defaultValue = envValue.slice(start, end)
1417
+ }
1418
+ if (envValue[end] === "}") end++
1419
+
1420
+ // References already being expanded resolve as unset.
1421
+ const expanded = Object.hasOwn(parsed, name) && !seen.has(name)
1422
+ ? interpolate(parsed[name], parsed, new Set([...seen, name]))
1423
+ : ""
1424
+ result += envValue.slice(cursor, match.index) + (expanded || interpolate(defaultValue, parsed, seen))
1425
+ cursor = end
1426
+ reference.lastIndex = end
1425
1427
  }
1426
-
1427
- return envValue
1428
- }
1429
-
1430
- function searchLast(str: string, rgx: RegExp): number {
1431
- const matches = Array.from(str.matchAll(rgx))
1432
- return matches.length > 0 ? matches.slice(-1)[0].index : -1
1428
+ return result + envValue.slice(cursor)
1433
1429
  }
1434
1430
 
1435
1431
  /**
package/src/Context.ts CHANGED
@@ -1986,6 +1986,15 @@ export const pick = <S extends ReadonlyArray<Key<any, any>>>(
1986
1986
  ...services: S
1987
1987
  ) =>
1988
1988
  <Services>(self: Context<Services>): Context<Services & Service.Identifier<S[number]>> => {
1989
+ if (services.length <= 1) {
1990
+ const map = new Map<string, unknown>()
1991
+ if (services.length === 1) {
1992
+ const key = services[0].key
1993
+ const value = lookup(self, key)
1994
+ if (value !== notFound) map.set(key, value)
1995
+ }
1996
+ return makeUnsafe(map)
1997
+ }
1989
1998
  const keep = new Set(services.map((key) => key.key))
1990
1999
  return withFlat(self, (map) =>
1991
2000
  map.forEach((_, key) => {
package/src/Duration.ts CHANGED
@@ -38,7 +38,8 @@ const bigint1e9 = BigInt(1_000_000_000)
38
38
 
39
39
  const roundTiesAwayFromZero = (input: number): bigint => BigInt(Math.sign(input) * Math.round(Math.abs(input)))
40
40
 
41
- const roundMillisToNanos = (millis: number): bigint => roundTiesAwayFromZero(millis * 1_000_000)
41
+ const roundMillisToNanos = (millis: number): bigint =>
42
+ Number.isInteger(millis) ? BigInt(millis) * bigint1e6 : roundTiesAwayFromZero(millis * 1_000_000)
42
43
 
43
44
  const fromNanosNumber = (nanos: number): Duration => make(Number.isFinite(nanos) ? roundTiesAwayFromZero(nanos) : nanos)
44
45
 
@@ -365,10 +366,8 @@ const DurationProto: Omit<Duration, "value"> = {
365
366
  // Hash equal finite durations using the same canonical nanoseconds
366
367
  // representation used by `equals`.
367
368
  switch (this.value._tag) {
368
- case "Millis": {
369
- const nanos = this.value.millis * 1_000_000
370
- return Number.isFinite(nanos) ? Hash.hash(roundTiesAwayFromZero(nanos)) : Hash.number(this.value.millis)
371
- }
369
+ case "Millis":
370
+ return Hash.hash(roundMillisToNanos(this.value.millis))
372
371
  case "Nanos":
373
372
  return Hash.hash(this.value.nanos)
374
373
  default:
package/src/Effect.ts CHANGED
@@ -20,7 +20,7 @@ import type * as ExecutionPlan from "./ExecutionPlan.ts"
20
20
  import * as Exit from "./Exit.ts"
21
21
  import type { Fiber } from "./Fiber.ts"
22
22
  import type * as Filter from "./Filter.ts"
23
- import { constant, dual, type LazyArg } from "./Function.ts"
23
+ import { dual, type LazyArg } from "./Function.ts"
24
24
  import type { TypeLambda } from "./HKT.ts"
25
25
  import type { Inspectable } from "./Inspectable.ts"
26
26
  import * as core from "./internal/core.ts"
@@ -25245,50 +25245,113 @@ export const trackDuration: {
25245
25245
  // Transactions
25246
25246
  // -----------------------------------------------------------------------------
25247
25247
 
25248
+ /**
25249
+ * Why the current transaction attempt started after a previous attempt did not commit.
25250
+ *
25251
+ * **Details**
25252
+ *
25253
+ * `"retry"` means the previous attempt called {@link txRetry}. `"conflict"`
25254
+ * means an accessed `TxRef` changed before commit. The first attempt has no
25255
+ * retry reason.
25256
+ *
25257
+ * @stability stable
25258
+ * @category models
25259
+ * @since 4.0.0
25260
+ */
25261
+ export type TransactionRetryReason = "retry" | "conflict"
25262
+
25263
+ /**
25264
+ * Journal and attempt metadata for an Effect transaction.
25265
+ *
25266
+ * **When to use**
25267
+ *
25268
+ * Use to type the value provided by {@link Transaction}.
25269
+ *
25270
+ * **Details**
25271
+ *
25272
+ * `attempt` starts at `1` and counts each run of the outermost transaction body.
25273
+ * `retryReason` is `"retry"` after {@link txRetry} and `"conflict"` after an
25274
+ * accessed `TxRef` changes before commit; it is unset on the first attempt.
25275
+ * `start`, `now`, `elapsed`, and `elapsedSincePrevious` are millisecond
25276
+ * timestamps and durations for the current attempt, matching {@link Schedule}
25277
+ * metadata. Each journal entry stores the observed version and value of a
25278
+ * `TxRef`. `written` is true when this transaction has updated that ref.
25279
+ *
25280
+ * @see {@link Transaction} for the context service that provides this metadata
25281
+ * @see {@link TransactionRetryReason} for the retry-reason tags recorded on later attempts
25282
+ *
25283
+ * @stability stable
25284
+ * @category models
25285
+ * @since 4.0.0
25286
+ */
25287
+ export interface TransactionMeta {
25288
+ readonly journal: ReadonlyMap<
25289
+ TxRef<any>,
25290
+ {
25291
+ readonly version: number
25292
+ readonly value: any
25293
+ readonly written: boolean
25294
+ }
25295
+ >
25296
+ readonly attempt: number
25297
+ readonly retryReason: TransactionRetryReason | undefined
25298
+ readonly start: number
25299
+ readonly now: number
25300
+ readonly elapsed: number
25301
+ readonly elapsedSincePrevious: number
25302
+ }
25303
+
25304
+ /** @internal */
25305
+ export interface TransactionMetaInner {
25306
+ retry: boolean
25307
+ journal: Map<
25308
+ TxRef<any>,
25309
+ {
25310
+ readonly version: number
25311
+ value: any
25312
+ written: boolean
25313
+ }
25314
+ >
25315
+ attempt: number
25316
+ retryReason: TransactionRetryReason | undefined
25317
+ start: number
25318
+ now: number
25319
+ elapsed: number
25320
+ elapsedSincePrevious: number
25321
+ }
25322
+
25248
25323
  /**
25249
25324
  * Service that holds the current transaction state.
25250
25325
  *
25251
25326
  * **Details**
25252
25327
  *
25253
- * It includes a journal that stores non-committed changes to `TxRef` values and
25254
- * a retry flag that records whether the transaction should be retried.
25328
+ * Nested {@link tx} calls reuse this same service instance. Yield it inside a
25329
+ * transaction body to read {@link TransactionMeta} fields such as `attempt`
25330
+ * and `retryReason`.
25255
25331
  *
25256
- * **Example** (Building transactions)
25332
+ * **Example** (Reading transaction metadata)
25257
25333
  *
25258
25334
  * ```ts import.meta.vitest
25259
25335
  * import { Effect } from "effect"
25260
25336
  *
25261
- * // Transaction class for software transactional memory operations
25262
- * const txEffect = Effect.gen(function*() {
25337
+ * const program = Effect.tx(Effect.gen(function*() {
25263
25338
  * const tx = yield* Effect.Transaction
25264
- * // Use transaction for coordinated state changes
25265
- * return "Transaction complete"
25266
- * })
25339
+ * return [tx.attempt, tx.retryReason, tx.elapsed, tx.elapsedSincePrevious]
25340
+ * }))
25267
25341
  *
25268
- * const runnable = Effect.provideService(txEffect, Effect.Transaction, {
25269
- * retry: false,
25270
- * journal: new Map()
25271
- * })
25272
- * Effect.runSync(runnable) // => "Transaction complete"
25342
+ * Effect.runSync(program) // => [1, undefined, 0, 0]
25273
25343
  * ```
25274
25344
  *
25345
+ * @see {@link tx} for the outermost transaction boundary that creates this service
25346
+ * @see {@link TransactionMeta} for the journal and attempt metadata
25347
+ *
25275
25348
  * @stability stable
25276
25349
  * @category transactions
25277
25350
  * @since 4.0.0
25278
25351
  */
25279
25352
  export class Transaction extends Context.Service<
25280
25353
  Transaction,
25281
- {
25282
- retry: boolean
25283
- readonly journal: Map<
25284
- TxRef<any>,
25285
- {
25286
- readonly version: number
25287
- value: any
25288
- written: boolean
25289
- }
25290
- >
25291
- }
25354
+ TransactionMeta
25292
25355
  >()("effect/Effect/Transaction") {}
25293
25356
 
25294
25357
  /**
@@ -25342,52 +25405,75 @@ export const tx = <A, E, R>(
25342
25405
  effect: Effect<A, E, R>
25343
25406
  ): Effect<A, E, Exclude<R, Transaction>> =>
25344
25407
  withFiber((fiber) => {
25345
- let state = Context.getOrUndefined(fiber.context, Transaction)
25408
+ const state = Context.getOrUndefined(fiber.context, Transaction)
25346
25409
  if (state && !completedTransactions.has(state)) {
25347
25410
  return effect as Effect<A, E, Exclude<R, Transaction>>
25348
25411
  }
25412
+ const clock = fiber.getRef(internal.ClockRef)
25413
+ const now = clock.currentTimeMillisUnsafe()
25349
25414
  // Create transaction state only at the outermost boundary
25350
- state = { journal: new Map(), retry: false }
25415
+ const mutable: TransactionMetaInner = {
25416
+ journal: new Map(),
25417
+ retry: false,
25418
+ attempt: 1,
25419
+ retryReason: undefined,
25420
+ start: now,
25421
+ now,
25422
+ elapsed: 0,
25423
+ elapsedSincePrevious: 0
25424
+ }
25351
25425
  let result: Exit.Exit<A, E> | undefined
25352
- return uninterruptibleMask((restore) =>
25353
- flatMap(
25426
+ return uninterruptibleMask((restore) => {
25427
+ const run = restore(effect).pipe(
25428
+ provideService(Transaction, mutable),
25429
+ tapCause((cause) => {
25430
+ if (!mutable.retry) return void_
25431
+ // txRetry interrupts the body; any other reason in the cause is a real failure.
25432
+ // Roll back now so the step below fails instead of waiting or rerunning.
25433
+ if (!internal.hasInterruptsOnly(cause)) return sync(() => clearTransaction(mutable))
25434
+ return restore(awaitPendingTransaction(mutable))
25435
+ }),
25436
+ exit
25437
+ )
25438
+ return flatMap(
25354
25439
  whileLoop({
25355
25440
  while: () => !result,
25356
- body: constant(
25357
- restore(effect).pipe(
25358
- provideService(Transaction, state),
25359
- tapCause((cause) => {
25360
- if (!state.retry) return void_
25361
- // txRetry interrupts the body; any other reason in the cause is a real failure.
25362
- // Roll back now so the step below fails instead of waiting or rerunning.
25363
- if (!internal.hasInterruptsOnly(cause)) return sync(() => clearTransaction(state))
25364
- return restore(awaitPendingTransaction(state))
25365
- }),
25366
- exit
25367
- )
25368
- ),
25441
+ body: () => {
25442
+ if (mutable.attempt > 1) {
25443
+ stampTransaction(mutable, clock.currentTimeMillisUnsafe())
25444
+ }
25445
+ return run
25446
+ },
25369
25447
  step(exit: Exit.Exit<A, E>) {
25370
- if (state.retry || !isTransactionConsistent(state)) {
25371
- return clearTransaction(state)
25448
+ if (mutable.retry || !isTransactionConsistent(mutable)) {
25449
+ mutable.attempt++
25450
+ mutable.retryReason = mutable.retry ? "retry" : "conflict"
25451
+ return clearTransaction(mutable)
25372
25452
  }
25373
25453
  if (Exit.isSuccess(exit)) {
25374
- commitTransaction(fiber, state)
25454
+ commitTransaction(fiber, mutable)
25375
25455
  }
25376
- clearTransaction(state)
25377
- completedTransactions.add(state)
25456
+ clearTransaction(mutable)
25457
+ completedTransactions.add(mutable)
25378
25458
  result = exit
25379
25459
  }
25380
25460
  }),
25381
25461
  () => result!
25382
25462
  )
25383
- )
25463
+ })
25384
25464
  })
25385
25465
 
25386
25466
  // Child fibers inherit the boundary's state, so mark it completed once the
25387
25467
  // boundary finishes and let later `tx` calls start a fresh boundary.
25388
25468
  const completedTransactions = new WeakSet<Transaction["Service"]>()
25389
25469
 
25390
- const isTransactionConsistent = (state: Transaction["Service"]) => {
25470
+ const stampTransaction = (state: TransactionMetaInner, now: number) => {
25471
+ state.elapsedSincePrevious = now - state.now
25472
+ state.now = now
25473
+ state.elapsed = now - state.start
25474
+ }
25475
+
25476
+ const isTransactionConsistent = (state: TransactionMeta) => {
25391
25477
  for (const [ref, { version }] of state.journal) {
25392
25478
  if (ref.version !== version) {
25393
25479
  return false
@@ -25396,7 +25482,7 @@ const isTransactionConsistent = (state: Transaction["Service"]) => {
25396
25482
  return true
25397
25483
  }
25398
25484
 
25399
- const awaitPendingTransaction = (state: Transaction["Service"]) =>
25485
+ const awaitPendingTransaction = (state: TransactionMeta) =>
25400
25486
  callback<void>((resume) => {
25401
25487
  // Validate the read set and register the waiter in one synchronous step.
25402
25488
  // A commit that landed after the reads has already signalled its waiters
@@ -25421,7 +25507,7 @@ const awaitPendingTransaction = (state: Transaction["Service"]) =>
25421
25507
  return sync(clearPending)
25422
25508
  })
25423
25509
 
25424
- function commitTransaction(fiber: Fiber<unknown, unknown>, state: Transaction["Service"]) {
25510
+ function commitTransaction(fiber: Fiber<unknown, unknown>, state: TransactionMeta) {
25425
25511
  for (const [ref, { value, written }] of state.journal) {
25426
25512
  if (!written) continue
25427
25513
  if (!Object.is(value, ref.value)) {
@@ -25435,7 +25521,7 @@ function commitTransaction(fiber: Fiber<unknown, unknown>, state: Transaction["S
25435
25521
  }
25436
25522
  }
25437
25523
 
25438
- function clearTransaction(state: Transaction["Service"]) {
25524
+ function clearTransaction(state: TransactionMetaInner) {
25439
25525
  state.retry = false
25440
25526
  state.journal.clear()
25441
25527
  }
@@ -25480,7 +25566,8 @@ function clearTransaction(state: Transaction["Service"]) {
25480
25566
  export const txRetry: Effect<never, never, Transaction> = flatMap(
25481
25567
  Transaction,
25482
25568
  (state) => {
25483
- state.retry = true
25569
+ const mutable = state as TransactionMetaInner
25570
+ mutable.retry = true
25484
25571
  return interrupt
25485
25572
  }
25486
25573
  )
package/src/FileSystem.ts CHANGED
@@ -968,9 +968,17 @@ export declare namespace File {
968
968
  * permissions, and size information. This structure is returned by file
969
969
  * stat operations.
970
970
  *
971
- * Node and Bun preserve `size` and `blksize` exactly. Optional `number`
972
- * metadata is `Option.none()` when absent or outside the safe integer range.
973
- * Unsafe `dev` or `mode` values fail the stat operation with `BadArgument`.
971
+ * `dev`, `ino`, `rdev`, `nlink`, and `blocks` are `bigint` values, so
972
+ * 64-bit device identifiers, inode numbers, and counts are not limited to
973
+ * the safe integer range. `mode`, `uid`, and `gid` are 32-bit values and
974
+ * remain `number`. Optional metadata is `Option.none()` only when the
975
+ * platform does not report it.
976
+ *
977
+ * Node and Bun report all fields exactly, with `dev`, `ino`, `rdev`, and
978
+ * `nlink` interpreted as unsigned 64-bit integers. Unsafe `mode` values fail
979
+ * the stat operation with `BadArgument`. Deno reports these fields as
980
+ * `number`, so on Deno values above `Number.MAX_SAFE_INTEGER` are already
981
+ * rounded before they are converted to `bigint`.
974
982
  *
975
983
  * **Example** (Inspecting file information)
976
984
  *
@@ -982,7 +990,7 @@ export declare namespace File {
982
990
  * mtime: Option.none(),
983
991
  * atime: Option.none(),
984
992
  * birthtime: Option.none(),
985
- * dev: 1,
993
+ * dev: 1n,
986
994
  * ino: Option.none(),
987
995
  * mode: 0o644,
988
996
  * nlink: Option.none(),
@@ -1014,16 +1022,16 @@ export declare namespace File {
1014
1022
  readonly mtime: Option.Option<Date>
1015
1023
  readonly atime: Option.Option<Date>
1016
1024
  readonly birthtime: Option.Option<Date>
1017
- readonly dev: number
1018
- readonly ino: Option.Option<number>
1025
+ readonly dev: bigint
1026
+ readonly ino: Option.Option<bigint>
1019
1027
  readonly mode: number
1020
- readonly nlink: Option.Option<number>
1028
+ readonly nlink: Option.Option<bigint>
1021
1029
  readonly uid: Option.Option<number>
1022
1030
  readonly gid: Option.Option<number>
1023
- readonly rdev: Option.Option<number>
1031
+ readonly rdev: Option.Option<bigint>
1024
1032
  readonly size: ByteSize.ByteSize
1025
1033
  readonly blksize: Option.Option<ByteSize.ByteSize>
1026
- readonly blocks: Option.Option<number>
1034
+ readonly blocks: Option.Option<bigint>
1027
1035
  }
1028
1036
  }
1029
1037
 
@@ -1061,6 +1069,12 @@ export interface WatchOptions {
1061
1069
  * When `true`, changes in subdirectories are also reported.
1062
1070
  */
1063
1071
  readonly recursive?: boolean | undefined
1072
+ /**
1073
+ * Called once the underlying watcher is installed and can buffer events.
1074
+ * Stream construction alone does not install a watcher. Custom watch
1075
+ * backends must also call this callback after installation, when supplied.
1076
+ */
1077
+ readonly onReady?: (() => void) | undefined
1064
1078
  }
1065
1079
 
1066
1080
  /**