effect 4.0.2 → 4.0.4

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 (389) 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 +111 -0
  5. package/ai-docs/src/52_graphql/20_testing.ts +45 -0
  6. package/ai-docs/src/52_graphql/30_batching.ts +116 -0
  7. package/ai-docs/src/52_graphql/40_aliased-batching.ts +122 -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/Context.d.ts.map +1 -1
  11. package/dist/Context.js +12 -3
  12. package/dist/Context.js.map +1 -1
  13. package/dist/Crypto.d.ts +33 -5
  14. package/dist/Crypto.d.ts.map +1 -1
  15. package/dist/Crypto.js +8 -2
  16. package/dist/Crypto.js.map +1 -1
  17. package/dist/DateTime.d.ts +9 -6
  18. package/dist/DateTime.d.ts.map +1 -1
  19. package/dist/DateTime.js +9 -6
  20. package/dist/DateTime.js.map +1 -1
  21. package/dist/Duration.d.ts +6 -6
  22. package/dist/Duration.d.ts.map +1 -1
  23. package/dist/Duration.js +27 -8
  24. package/dist/Duration.js.map +1 -1
  25. package/dist/FileSystem.d.ts +44 -2
  26. package/dist/FileSystem.d.ts.map +1 -1
  27. package/dist/FileSystem.js.map +1 -1
  28. package/dist/RequestResolver.d.ts.map +1 -1
  29. package/dist/RequestResolver.js +4 -10
  30. package/dist/RequestResolver.js.map +1 -1
  31. package/dist/Scheduler.d.ts +9 -0
  32. package/dist/Scheduler.d.ts.map +1 -1
  33. package/dist/Scheduler.js +9 -0
  34. package/dist/Scheduler.js.map +1 -1
  35. package/dist/Schema.d.ts +481 -1
  36. package/dist/Schema.d.ts.map +1 -1
  37. package/dist/Schema.js +362 -4
  38. package/dist/Schema.js.map +1 -1
  39. package/dist/SchemaGetter.d.ts +4 -0
  40. package/dist/SchemaGetter.d.ts.map +1 -1
  41. package/dist/SchemaGetter.js +52 -33
  42. package/dist/SchemaGetter.js.map +1 -1
  43. package/dist/Sink.d.ts.map +1 -1
  44. package/dist/Sink.js +38 -17
  45. package/dist/Sink.js.map +1 -1
  46. package/dist/Stdio.d.ts +7 -1
  47. package/dist/Stdio.d.ts.map +1 -1
  48. package/dist/Stdio.js +1 -0
  49. package/dist/Stdio.js.map +1 -1
  50. package/dist/Stream.d.ts +22 -11
  51. package/dist/Stream.d.ts.map +1 -1
  52. package/dist/Stream.js +21 -6
  53. package/dist/Stream.js.map +1 -1
  54. package/dist/Utils.js +8 -3
  55. package/dist/Utils.js.map +1 -1
  56. package/dist/ai/AnthropicStructuredOutput.js +0 -2
  57. package/dist/ai/AnthropicStructuredOutput.js.map +1 -1
  58. package/dist/ai/Chat.d.ts +2 -2
  59. package/dist/ai/Chat.d.ts.map +1 -1
  60. package/dist/ai/LanguageModel.d.ts +38 -7
  61. package/dist/ai/LanguageModel.d.ts.map +1 -1
  62. package/dist/ai/LanguageModel.js +25 -7
  63. package/dist/ai/LanguageModel.js.map +1 -1
  64. package/dist/ai/McpServer.d.ts +61 -0
  65. package/dist/ai/McpServer.d.ts.map +1 -1
  66. package/dist/ai/McpServer.js +196 -44
  67. package/dist/ai/McpServer.js.map +1 -1
  68. package/dist/ai/Prompt.d.ts.map +1 -1
  69. package/dist/ai/Prompt.js +28 -5
  70. package/dist/ai/Prompt.js.map +1 -1
  71. package/dist/ai/Response.d.ts +4 -3
  72. package/dist/ai/Response.d.ts.map +1 -1
  73. package/dist/ai/Response.js.map +1 -1
  74. package/dist/ai/internal/mcpProtocol/v2026_07_28.js +5 -0
  75. package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
  76. package/dist/ai/internal/mcpProtocol.js.map +1 -1
  77. package/dist/ai/internal/mcpRuntime.js +1 -0
  78. package/dist/ai/internal/mcpRuntime.js.map +1 -1
  79. package/dist/cli/CliOutput.d.ts +27 -0
  80. package/dist/cli/CliOutput.d.ts.map +1 -1
  81. package/dist/cli/CliOutput.js +33 -10
  82. package/dist/cli/CliOutput.js.map +1 -1
  83. package/dist/cli/Command.d.ts.map +1 -1
  84. package/dist/cli/Command.js +6 -3
  85. package/dist/cli/Command.js.map +1 -1
  86. package/dist/cli/Completions.d.ts +3 -3
  87. package/dist/cli/Completions.d.ts.map +1 -1
  88. package/dist/cli/Completions.js +8 -5
  89. package/dist/cli/Completions.js.map +1 -1
  90. package/dist/cli/GlobalFlag.d.ts +5 -4
  91. package/dist/cli/GlobalFlag.d.ts.map +1 -1
  92. package/dist/cli/GlobalFlag.js +3 -3
  93. package/dist/cli/GlobalFlag.js.map +1 -1
  94. package/dist/cli/Prompt.d.ts +17 -1
  95. package/dist/cli/Prompt.d.ts.map +1 -1
  96. package/dist/cli/Prompt.js +119 -114
  97. package/dist/cli/Prompt.js.map +1 -1
  98. package/dist/cli/internal/ansi.d.ts +0 -1
  99. package/dist/cli/internal/ansi.d.ts.map +1 -1
  100. package/dist/cli/internal/ansi.js +20 -3
  101. package/dist/cli/internal/ansi.js.map +1 -1
  102. package/dist/cli/internal/completions/powershell.d.ts +2 -0
  103. package/dist/cli/internal/completions/powershell.d.ts.map +1 -0
  104. package/dist/cli/internal/completions/powershell.js +273 -0
  105. package/dist/cli/internal/completions/powershell.js.map +1 -0
  106. package/dist/cli/internal/completions/zsh.js +3 -2
  107. package/dist/cli/internal/completions/zsh.js.map +1 -1
  108. package/dist/cli/internal/wizard.d.ts +3 -3
  109. package/dist/cli/internal/wizard.d.ts.map +1 -1
  110. package/dist/cli/internal/wizard.js +21 -18
  111. package/dist/cli/internal/wizard.js.map +1 -1
  112. package/dist/cluster/ClusterSchema.d.ts +28 -0
  113. package/dist/cluster/ClusterSchema.d.ts.map +1 -1
  114. package/dist/cluster/ClusterSchema.js +30 -0
  115. package/dist/cluster/ClusterSchema.js.map +1 -1
  116. package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  117. package/dist/cluster/ClusterWorkflowEngine.js +56 -26
  118. package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
  119. package/dist/cluster/MessageStorage.d.ts +18 -3
  120. package/dist/cluster/MessageStorage.d.ts.map +1 -1
  121. package/dist/cluster/MessageStorage.js +31 -11
  122. package/dist/cluster/MessageStorage.js.map +1 -1
  123. package/dist/cluster/Runners.d.ts.map +1 -1
  124. package/dist/cluster/Runners.js +8 -2
  125. package/dist/cluster/Runners.js.map +1 -1
  126. package/dist/cluster/Sharding.d.ts.map +1 -1
  127. package/dist/cluster/Sharding.js +187 -66
  128. package/dist/cluster/Sharding.js.map +1 -1
  129. package/dist/cluster/SqlMessageStorage.d.ts +59 -19
  130. package/dist/cluster/SqlMessageStorage.d.ts.map +1 -1
  131. package/dist/cluster/SqlMessageStorage.js +84 -55
  132. package/dist/cluster/SqlMessageStorage.js.map +1 -1
  133. package/dist/cluster/SqlRunnerStorage.d.ts +68 -19
  134. package/dist/cluster/SqlRunnerStorage.d.ts.map +1 -1
  135. package/dist/cluster/SqlRunnerStorage.js +191 -113
  136. package/dist/cluster/SqlRunnerStorage.js.map +1 -1
  137. package/dist/cluster/internal/entityManager.js +104 -37
  138. package/dist/cluster/internal/entityManager.js.map +1 -1
  139. package/dist/encoding/Sse.d.ts +6 -0
  140. package/dist/encoding/Sse.d.ts.map +1 -1
  141. package/dist/encoding/Sse.js +62 -70
  142. package/dist/encoding/Sse.js.map +1 -1
  143. package/dist/graphql/GraphQL.d.ts +349 -0
  144. package/dist/graphql/GraphQL.d.ts.map +1 -0
  145. package/dist/graphql/GraphQL.js +207 -0
  146. package/dist/graphql/GraphQL.js.map +1 -0
  147. package/dist/graphql/GraphQLClient.d.ts +562 -0
  148. package/dist/graphql/GraphQLClient.d.ts.map +1 -0
  149. package/dist/graphql/GraphQLClient.js +498 -0
  150. package/dist/graphql/GraphQLClient.js.map +1 -0
  151. package/dist/graphql/GraphQLClientError.d.ts +445 -0
  152. package/dist/graphql/GraphQLClientError.d.ts.map +1 -0
  153. package/dist/graphql/GraphQLClientError.js +479 -0
  154. package/dist/graphql/GraphQLClientError.js.map +1 -0
  155. package/dist/graphql/GraphQLGroup.d.ts +118 -0
  156. package/dist/graphql/GraphQLGroup.d.ts.map +1 -0
  157. package/dist/graphql/GraphQLGroup.js +109 -0
  158. package/dist/graphql/GraphQLGroup.js.map +1 -0
  159. package/dist/graphql/GraphQLMiddleware.d.ts +249 -0
  160. package/dist/graphql/GraphQLMiddleware.d.ts.map +1 -0
  161. package/dist/graphql/GraphQLMiddleware.js +130 -0
  162. package/dist/graphql/GraphQLMiddleware.js.map +1 -0
  163. package/dist/graphql/GraphQLProtocol.d.ts +731 -0
  164. package/dist/graphql/GraphQLProtocol.d.ts.map +1 -0
  165. package/dist/graphql/GraphQLProtocol.js +719 -0
  166. package/dist/graphql/GraphQLProtocol.js.map +1 -0
  167. package/dist/graphql/GraphQLResolver.d.ts +453 -0
  168. package/dist/graphql/GraphQLResolver.d.ts.map +1 -0
  169. package/dist/graphql/GraphQLResolver.js +552 -0
  170. package/dist/graphql/GraphQLResolver.js.map +1 -0
  171. package/dist/graphql/index.d.ts +40 -0
  172. package/dist/graphql/index.d.ts.map +1 -0
  173. package/dist/graphql/index.js +41 -0
  174. package/dist/graphql/index.js.map +1 -0
  175. package/dist/http/FindMyWay/internal/router.js +3 -6
  176. package/dist/http/FindMyWay/internal/router.js.map +1 -1
  177. package/dist/http/HttpClient.d.ts +21 -0
  178. package/dist/http/HttpClient.d.ts.map +1 -1
  179. package/dist/http/HttpClient.js +63 -12
  180. package/dist/http/HttpClient.js.map +1 -1
  181. package/dist/http/HttpEffect.d.ts.map +1 -1
  182. package/dist/http/HttpEffect.js +14 -7
  183. package/dist/http/HttpEffect.js.map +1 -1
  184. package/dist/http/HttpMiddleware.d.ts.map +1 -1
  185. package/dist/http/HttpMiddleware.js +31 -32
  186. package/dist/http/HttpMiddleware.js.map +1 -1
  187. package/dist/http/HttpRouter.d.ts +35 -0
  188. package/dist/http/HttpRouter.d.ts.map +1 -1
  189. package/dist/http/HttpRouter.js +35 -0
  190. package/dist/http/HttpRouter.js.map +1 -1
  191. package/dist/http/HttpServerResponse.d.ts +8 -6
  192. package/dist/http/HttpServerResponse.d.ts.map +1 -1
  193. package/dist/http/HttpServerResponse.js +27 -16
  194. package/dist/http/HttpServerResponse.js.map +1 -1
  195. package/dist/http/HttpTraceContext.d.ts.map +1 -1
  196. package/dist/http/HttpTraceContext.js +4 -2
  197. package/dist/http/HttpTraceContext.js.map +1 -1
  198. package/dist/http/Multipart.d.ts.map +1 -1
  199. package/dist/http/Multipart.js +15 -1
  200. package/dist/http/Multipart.js.map +1 -1
  201. package/dist/http-api/HttpApiScalar.d.ts +5 -0
  202. package/dist/http-api/HttpApiScalar.d.ts.map +1 -1
  203. package/dist/http-api/HttpApiScalar.js.map +1 -1
  204. package/dist/internal/dateTime.js +40 -35
  205. package/dist/internal/dateTime.js.map +1 -1
  206. package/dist/internal/effect.js +19 -9
  207. package/dist/internal/effect.js.map +1 -1
  208. package/dist/internal/graphql.d.ts +2 -0
  209. package/dist/internal/graphql.d.ts.map +1 -0
  210. package/dist/internal/graphql.js +195 -0
  211. package/dist/internal/graphql.js.map +1 -0
  212. package/dist/internal/graphqlHeaders.d.ts +4 -0
  213. package/dist/internal/graphqlHeaders.d.ts.map +1 -0
  214. package/dist/internal/graphqlHeaders.js +11 -0
  215. package/dist/internal/graphqlHeaders.js.map +1 -0
  216. package/dist/internal/request.js +20 -1
  217. package/dist/internal/request.js.map +1 -1
  218. package/dist/internal/schema/toCodeDocument.js +4 -1
  219. package/dist/internal/schema/toCodeDocument.js.map +1 -1
  220. package/dist/internal/schema/toJsonSchemaDocument.js +29 -5
  221. package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -1
  222. package/dist/internal/version.js +1 -1
  223. package/dist/net/AddressResolver.d.ts +145 -0
  224. package/dist/net/AddressResolver.d.ts.map +1 -0
  225. package/dist/net/AddressResolver.js +114 -0
  226. package/dist/net/AddressResolver.js.map +1 -0
  227. package/dist/net/Dns.d.ts +596 -0
  228. package/dist/net/Dns.d.ts.map +1 -0
  229. package/dist/net/Dns.js +549 -0
  230. package/dist/net/Dns.js.map +1 -0
  231. package/dist/net/Host.d.ts +369 -0
  232. package/dist/net/Host.d.ts.map +1 -0
  233. package/dist/net/Host.js +397 -0
  234. package/dist/net/Host.js.map +1 -0
  235. package/dist/net/IpInterface.d.ts +76 -3
  236. package/dist/net/IpInterface.d.ts.map +1 -1
  237. package/dist/net/IpInterface.js +53 -4
  238. package/dist/net/IpInterface.js.map +1 -1
  239. package/dist/net/IpNetwork.d.ts +82 -8
  240. package/dist/net/IpNetwork.d.ts.map +1 -1
  241. package/dist/net/IpNetwork.js +60 -4
  242. package/dist/net/IpNetwork.js.map +1 -1
  243. package/dist/net/NetAddress.d.ts +396 -35
  244. package/dist/net/NetAddress.d.ts.map +1 -1
  245. package/dist/net/NetAddress.js +358 -34
  246. package/dist/net/NetAddress.js.map +1 -1
  247. package/dist/net/index.d.ts +15 -0
  248. package/dist/net/index.d.ts.map +1 -1
  249. package/dist/net/index.js +15 -0
  250. package/dist/net/index.js.map +1 -1
  251. package/dist/observability/OtlpMetrics.d.ts.map +1 -1
  252. package/dist/observability/OtlpMetrics.js +15 -21
  253. package/dist/observability/OtlpMetrics.js.map +1 -1
  254. package/dist/observability/PrometheusMetrics.js +1 -0
  255. package/dist/observability/PrometheusMetrics.js.map +1 -1
  256. package/dist/persistence/PersistedQueue.d.ts +32 -3
  257. package/dist/persistence/PersistedQueue.d.ts.map +1 -1
  258. package/dist/persistence/PersistedQueue.js +75 -16
  259. package/dist/persistence/PersistedQueue.js.map +1 -1
  260. package/dist/rpc/RpcClient.d.ts +22 -6
  261. package/dist/rpc/RpcClient.d.ts.map +1 -1
  262. package/dist/rpc/RpcClient.js +12 -5
  263. package/dist/rpc/RpcClient.js.map +1 -1
  264. package/dist/rpc/RpcServer.d.ts +6 -0
  265. package/dist/rpc/RpcServer.d.ts.map +1 -1
  266. package/dist/rpc/RpcServer.js +78 -29
  267. package/dist/rpc/RpcServer.js.map +1 -1
  268. package/dist/socket/DatagramSocket.d.ts +456 -0
  269. package/dist/socket/DatagramSocket.d.ts.map +1 -0
  270. package/dist/socket/DatagramSocket.js +535 -0
  271. package/dist/socket/DatagramSocket.js.map +1 -0
  272. package/dist/socket/Socket.d.ts +20 -1
  273. package/dist/socket/Socket.d.ts.map +1 -1
  274. package/dist/socket/Socket.js +9 -1
  275. package/dist/socket/Socket.js.map +1 -1
  276. package/dist/socket/index.d.ts +5 -0
  277. package/dist/socket/index.d.ts.map +1 -1
  278. package/dist/socket/index.js +5 -0
  279. package/dist/socket/index.js.map +1 -1
  280. package/dist/sql/Migrator.d.ts.map +1 -1
  281. package/dist/sql/Migrator.js +7 -2
  282. package/dist/sql/Migrator.js.map +1 -1
  283. package/dist/sql/SqlClient.d.ts +7 -1
  284. package/dist/sql/SqlClient.d.ts.map +1 -1
  285. package/dist/sql/SqlClient.js +31 -6
  286. package/dist/sql/SqlClient.js.map +1 -1
  287. package/dist/testing/TestCrypto.d.ts +73 -0
  288. package/dist/testing/TestCrypto.d.ts.map +1 -0
  289. package/dist/testing/TestCrypto.js +87 -0
  290. package/dist/testing/TestCrypto.js.map +1 -0
  291. package/dist/testing/index.d.ts +5 -0
  292. package/dist/testing/index.d.ts.map +1 -1
  293. package/dist/testing/index.js +5 -0
  294. package/dist/testing/index.js.map +1 -1
  295. package/dist/workflow/DurableDeferred.d.ts +54 -0
  296. package/dist/workflow/DurableDeferred.d.ts.map +1 -1
  297. package/dist/workflow/DurableDeferred.js +108 -50
  298. package/dist/workflow/DurableDeferred.js.map +1 -1
  299. package/dist/workflow/WorkflowEngine.d.ts +24 -2
  300. package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
  301. package/dist/workflow/WorkflowEngine.js +13 -3
  302. package/dist/workflow/WorkflowEngine.js.map +1 -1
  303. package/package.json +6 -3
  304. package/src/Context.ts +12 -3
  305. package/src/Crypto.ts +43 -9
  306. package/src/DateTime.ts +9 -6
  307. package/src/Duration.ts +36 -16
  308. package/src/FileSystem.ts +48 -2
  309. package/src/RequestResolver.ts +4 -10
  310. package/src/Scheduler.ts +9 -0
  311. package/src/Schema.ts +677 -5
  312. package/src/SchemaGetter.ts +47 -35
  313. package/src/Sink.ts +45 -18
  314. package/src/Stdio.ts +9 -2
  315. package/src/Stream.ts +44 -15
  316. package/src/Utils.ts +8 -5
  317. package/src/ai/AnthropicStructuredOutput.ts +2 -2
  318. package/src/ai/Chat.ts +2 -2
  319. package/src/ai/LanguageModel.ts +96 -24
  320. package/src/ai/McpServer.ts +288 -94
  321. package/src/ai/Prompt.ts +24 -10
  322. package/src/ai/Response.ts +6 -3
  323. package/src/ai/internal/mcpProtocol/v2026_07_28.ts +5 -0
  324. package/src/ai/internal/mcpProtocol.ts +3 -0
  325. package/src/ai/internal/mcpRuntime.ts +2 -0
  326. package/src/cli/CliOutput.ts +33 -16
  327. package/src/cli/Command.ts +4 -3
  328. package/src/cli/Completions.ts +9 -6
  329. package/src/cli/GlobalFlag.ts +19 -11
  330. package/src/cli/Prompt.ts +159 -149
  331. package/src/cli/internal/ansi.ts +26 -3
  332. package/src/cli/internal/completions/powershell.ts +322 -0
  333. package/src/cli/internal/completions/zsh.ts +4 -2
  334. package/src/cli/internal/wizard.ts +34 -26
  335. package/src/cluster/ClusterSchema.ts +32 -0
  336. package/src/cluster/ClusterWorkflowEngine.ts +64 -36
  337. package/src/cluster/MessageStorage.ts +45 -14
  338. package/src/cluster/Runners.ts +8 -2
  339. package/src/cluster/Sharding.ts +219 -58
  340. package/src/cluster/SqlMessageStorage.ts +118 -84
  341. package/src/cluster/SqlRunnerStorage.ts +224 -128
  342. package/src/cluster/internal/entityManager.ts +151 -55
  343. package/src/encoding/Sse.ts +69 -79
  344. package/src/graphql/GraphQL.ts +494 -0
  345. package/src/graphql/GraphQLClient.ts +912 -0
  346. package/src/graphql/GraphQLClientError.ts +542 -0
  347. package/src/graphql/GraphQLGroup.ts +167 -0
  348. package/src/graphql/GraphQLMiddleware.ts +253 -0
  349. package/src/graphql/GraphQLProtocol.ts +1286 -0
  350. package/src/graphql/GraphQLResolver.ts +1010 -0
  351. package/src/graphql/index.ts +48 -0
  352. package/src/http/FindMyWay/internal/router.ts +4 -7
  353. package/src/http/HttpClient.ts +110 -12
  354. package/src/http/HttpEffect.ts +11 -5
  355. package/src/http/HttpMiddleware.ts +33 -34
  356. package/src/http/HttpRouter.ts +35 -0
  357. package/src/http/HttpServerResponse.ts +28 -16
  358. package/src/http/HttpTraceContext.ts +8 -2
  359. package/src/http/Multipart.ts +17 -1
  360. package/src/http-api/HttpApiScalar.ts +5 -0
  361. package/src/internal/dateTime.ts +13 -10
  362. package/src/internal/effect.ts +22 -15
  363. package/src/internal/graphql.ts +263 -0
  364. package/src/internal/graphqlHeaders.ts +11 -0
  365. package/src/internal/request.ts +31 -3
  366. package/src/internal/schema/toCodeDocument.ts +7 -1
  367. package/src/internal/schema/toJsonSchemaDocument.ts +34 -2
  368. package/src/internal/version.ts +1 -1
  369. package/src/net/AddressResolver.ts +222 -0
  370. package/src/net/Dns.ts +1035 -0
  371. package/src/net/Host.ts +544 -0
  372. package/src/net/IpInterface.ts +117 -7
  373. package/src/net/IpNetwork.ts +116 -17
  374. package/src/net/NetAddress.ts +620 -76
  375. package/src/net/index.ts +18 -0
  376. package/src/observability/OtlpMetrics.ts +12 -23
  377. package/src/observability/PrometheusMetrics.ts +1 -0
  378. package/src/persistence/PersistedQueue.ts +146 -53
  379. package/src/rpc/RpcClient.ts +41 -19
  380. package/src/rpc/RpcServer.ts +115 -40
  381. package/src/socket/DatagramSocket.ts +919 -0
  382. package/src/socket/Socket.ts +28 -2
  383. package/src/socket/index.ts +6 -0
  384. package/src/sql/Migrator.ts +21 -5
  385. package/src/sql/SqlClient.ts +39 -15
  386. package/src/testing/TestCrypto.ts +94 -0
  387. package/src/testing/index.ts +6 -0
  388. package/src/workflow/DurableDeferred.ts +160 -47
  389. package/src/workflow/WorkflowEngine.ts +50 -5
@@ -82,6 +82,12 @@ export interface RpcServer<A extends Rpc.Any> {
82
82
  * handlers for a group and sending decoded server responses through
83
83
  * `onFromServer`.
84
84
  *
85
+ * **Details**
86
+ *
87
+ * If writing a stream `Chunk` fails with anything other than an interruption,
88
+ * the request fails with that cause. `onFromServer` is assumed to have already
89
+ * answered the client and reported it, so nothing else is sent or reported.
90
+ *
85
91
  * @stability unstable
86
92
  * @category constructors
87
93
  * @since 4.0.0
@@ -188,7 +194,7 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
188
194
  clients.set(clientId, client)
189
195
  } else if (
190
196
  client.ended &&
191
- (message._tag !== "Interrupt" || !client.fibers.has(message.requestId))
197
+ ((message._tag !== "Interrupt" && message._tag !== "Ack") || !client.fibers.has(message.requestId))
192
198
  ) {
193
199
  return Effect.interrupt
194
200
  }
@@ -199,7 +205,7 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
199
205
  }
200
206
  case "Ack": {
201
207
  const latch = client.latches?.get(message.requestId)
202
- return latch ? latch.open : Effect.void
208
+ return latch ? Effect.asVoid(latch.open) : Effect.void
203
209
  }
204
210
  case "Interrupt": {
205
211
  const fiber = client.fibers.get(message.requestId)
@@ -279,13 +285,23 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
279
285
  const isUninterruptible = isWrapper && result.uninterruptible
280
286
  // unwrap the fork data type
281
287
  const streamOrEffect = isWrapper ? result.value : result
288
+ // set when a chunk could not be written; the writer has already responded
289
+ let writeFailure: Cause.Cause<never> | undefined
282
290
  const handler = isStream
283
- ? (streamEffect(client, request, streamOrEffect) as Effect.Effect<{} | Deferred.Deferred<any, any>>)
291
+ ? (streamEffect(client, request, streamOrEffect, (cause) => {
292
+ writeFailure = cause
293
+ }) as Effect.Effect<{} | Deferred.Deferred<any, any>>)
284
294
  : (streamOrEffect as Effect.Effect<{} | Deferred.Deferred<any, any>>)
285
295
 
286
- const withMiddleware = rpc.middlewares.size > 0
287
- ? applyMiddleware(services, handler, metadata)
288
- : handler
296
+ const withMiddleware = rpc.middlewares.size === 0
297
+ ? handler
298
+ : isStream
299
+ // middleware may rewrite or swallow a chunk write failure, so restore it
300
+ ? Effect.flatMap(
301
+ Effect.exit(applyMiddleware(services, handler, metadata)),
302
+ (exit) => writeFailure ? Effect.failCause(writeFailure) : exit
303
+ )
304
+ : applyMiddleware(services, handler, metadata)
289
305
  let responded = false
290
306
  const scope = Scope.makeUnsafe()
291
307
  let deferred: Deferred.Deferred<unknown, unknown> | undefined = undefined
@@ -304,6 +320,9 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
304
320
  exit: exit as any
305
321
  })
306
322
  }
323
+ } else if (writeFailure) {
324
+ // onFromServer has already answered the client and reported the failure
325
+ return Scope.closeUnsafe(scope, exit) ?? Effect.void
307
326
  } else if (
308
327
  !disableFatalDefects &&
309
328
  Cause.hasDies(exit.cause) &&
@@ -409,8 +428,17 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
409
428
  request: Request<Rpcs>,
410
429
  stream:
411
430
  | Stream.Stream<any, any>
412
- | Effect.Effect<Queue.Dequeue<any, any>, any, Scope.Scope>
431
+ | Effect.Effect<Queue.Dequeue<any, any>, any, Scope.Scope>,
432
+ onWriteFailure: (cause: Cause.Cause<never>) => void
413
433
  ) => {
434
+ const writeChunk = (values: NonEmptyReadonlyArray<any>) =>
435
+ Effect.onError(
436
+ options.onFromServer({ _tag: "Chunk", clientId: client.id, requestId: request.id, values }),
437
+ (cause) => {
438
+ if (!Cause.hasInterruptsOnly(cause)) onWriteFailure(cause)
439
+ return Effect.void
440
+ }
441
+ )
414
442
  let latch: Latch.Latch | undefined
415
443
  if (supportsAck) {
416
444
  client.latches ??= new Map()
@@ -427,12 +455,7 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
427
455
  while: constTrue,
428
456
  body: constant(
429
457
  Effect.flatMap(Queue.takeAll(queue), (values) => {
430
- const write = options.onFromServer({
431
- _tag: "Chunk",
432
- clientId: client.id,
433
- requestId: request.id,
434
- values
435
- })
458
+ const write = writeChunk(values)
436
459
  if (!latch) return write
437
460
  latch.closeUnsafe()
438
461
  return Effect.flatMap(write, () => latch.await)
@@ -446,12 +469,7 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
446
469
  )
447
470
  }
448
471
  return Stream.runForEachArray(stream, (values) => {
449
- const write = options.onFromServer({
450
- _tag: "Chunk",
451
- clientId: client.id,
452
- requestId: request.id,
453
- values
454
- })
472
+ const write = writeChunk(values)
455
473
  if (!latch) return write
456
474
  latch.closeUnsafe()
457
475
  return Effect.andThen(write, latch.await)
@@ -476,6 +494,57 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
476
494
  })
477
495
  })
478
496
 
497
+ // Built-in JSON codecs depend only on the RPC schemas and can be shared.
498
+ // Other factories may capture state at construction, so keep them per server.
499
+ const isSharedCodecFor = (codecFor: RpcSerialization.CodecFor) => codecFor === RpcSerialization.json.codecFor
500
+
501
+ interface RpcCodecs {
502
+ readonly decode: (u: unknown) => Effect.Effect<any, Schema.SchemaError>
503
+ readonly encodeChunk: (
504
+ u: NonEmptyReadonlyArray<unknown>
505
+ ) => Effect.Effect<NonEmptyReadonlyArray<unknown>, Schema.SchemaError>
506
+ readonly encodeExit: (u: unknown) => Effect.Effect<ResponseExitEncoded["exit"], Schema.SchemaError>
507
+ }
508
+
509
+ const sharedRpcCodecs = new WeakMap<Rpc.AnyWithProps, RpcCodecs>()
510
+
511
+ const rpcCodecs = (codecFor: RpcSerialization.CodecFor, rpc: Rpc.AnyWithProps): RpcCodecs => {
512
+ const shared = isSharedCodecFor(codecFor)
513
+ let codecs = shared ? sharedRpcCodecs.get(rpc) : undefined
514
+ if (codecs === undefined) {
515
+ const streamSchemas = RpcSchema.getStreamSchemas(rpc.successSchema)
516
+ codecs = {
517
+ decode: Schema.decodeUnknownEffect(codecFor(rpc.payloadSchema)) as any,
518
+ encodeChunk: Schema.encodeUnknownEffect(
519
+ codecFor(
520
+ Schema.NonEmptyArray(Option.isSome(streamSchemas) ? streamSchemas.value.success : Schema.Any)
521
+ )
522
+ ) as any,
523
+ encodeExit: Schema.encodeUnknownEffect(codecFor(Rpc.exitSchema(rpc as any))) as any
524
+ }
525
+ if (shared) sharedRpcCodecs.set(rpc, codecs)
526
+ }
527
+ return codecs
528
+ }
529
+
530
+ interface DefectCodecs {
531
+ readonly encodeDefectUnsafe: (defect: unknown) => unknown
532
+ readonly encodeUnknownRequestExit: (u: unknown) => Effect.Effect<ResponseExitEncoded["exit"], Schema.SchemaError>
533
+ }
534
+
535
+ let sharedDefectCodecs: DefectCodecs | undefined
536
+
537
+ const makeDefectCodecs = (codecFor: RpcSerialization.CodecFor): DefectCodecs => ({
538
+ encodeDefectUnsafe: Schema.encodeSync(codecFor(Schema.Defect())),
539
+ // Unknown tags have no RPC schema, so use a defect-only exit schema.
540
+ encodeUnknownRequestExit: Schema.encodeUnknownEffect(
541
+ codecFor(Schema.Exit(Schema.Never, Schema.Never, Schema.Defect()))
542
+ ) as any
543
+ })
544
+
545
+ const defectCodecs = (codecFor: RpcSerialization.CodecFor): DefectCodecs =>
546
+ isSharedCodecFor(codecFor) ? (sharedDefectCodecs ??= makeDefectCodecs(codecFor)) : makeDefectCodecs(codecFor)
547
+
479
548
  // Merging the handler entry services with the request fiber services costs
480
549
  // O(services), so the merged context is cached per (entry, fiber context)
481
550
  // pair. Request fibers on persistent connections keep one context across
@@ -568,11 +637,7 @@ export const make: <Rpcs extends Rpc.Any>(
568
637
  supportsSpanPropagation,
569
638
  supportsTransferables
570
639
  } = yield* Protocol
571
- const encodeDefectUnsafe = Schema.encodeSync(codecFor(Schema.Defect()))
572
- // Unknown tags have no RPC schema, so use a defect-only exit schema.
573
- const encodeUnknownRequestExit: Schemas["encodeExit"] = Schema.encodeUnknownEffect(
574
- codecFor(Schema.Exit(Schema.Never, Schema.Never, Schema.Defect()))
575
- ) as any
640
+ const { encodeDefectUnsafe, encodeUnknownRequestExit } = defectCodecs(codecFor)
576
641
  const services = yield* Effect.context<Rpc.ToHandler<Rpcs> | Rpc.Middleware<Rpcs>>()
577
642
  const scope = yield* Scope.make()
578
643
 
@@ -633,6 +698,7 @@ export const make: <Rpcs extends Rpc.Any>(
633
698
  )
634
699
 
635
700
  type Schemas = {
701
+ readonly tag: string
636
702
  readonly decode: (u: unknown) => Effect.Effect<Rpc.Payload<Rpcs>, Schema.SchemaError>
637
703
  readonly encodeChunk: (
638
704
  u: NonEmptyReadonlyArray<unknown>
@@ -647,15 +713,9 @@ export const make: <Rpcs extends Rpc.Any>(
647
713
  let schemas = schemasCache.get(rpc)
648
714
  if (!schemas) {
649
715
  const entry = Context.getOrUndefinedUnsafe(services, rpc.key) as Rpc.Handler<Rpcs["_tag"]>
650
- const streamSchemas = RpcSchema.getStreamSchemas(rpc.successSchema)
651
716
  schemas = {
652
- decode: Schema.decodeUnknownEffect(codecFor(rpc.payloadSchema)) as any,
653
- encodeChunk: Schema.encodeUnknownEffect(
654
- codecFor(
655
- Schema.NonEmptyArray(Option.isSome(streamSchemas) ? streamSchemas.value.success : Schema.Any)
656
- )
657
- ) as any,
658
- encodeExit: Schema.encodeUnknownEffect(codecFor(Rpc.exitSchema(rpc as any))) as any,
717
+ tag: rpc._tag,
718
+ ...rpcCodecs(codecFor, rpc),
659
719
  context: entry.context
660
720
  }
661
721
  schemasCache.set(rpc, schemas)
@@ -686,23 +746,38 @@ export const make: <Rpcs extends Rpc.Any>(
686
746
  tag: "Chunk" | "Exit"
687
747
  ) => {
688
748
  const collector = schemas.collector
749
+ let encodeFailed = false
689
750
  // The schema encoders evaluate eagerly, so an encode that needs no
690
751
  // services is already a resolved success and can skip the effect wrappers.
691
752
  const write = Exit.isExit(effect) && Exit.isSuccess(effect)
692
753
  ? send(client.id, responseEnvelope(requestId, tag, effect.value), collector && collector.clearUnsafe())
693
754
  : Effect.flatMap(
694
- Effect.provideContext(
695
- collector ? Effect.provideService(effect, Transferable.Collector, collector) : effect,
696
- schemas.context
755
+ Effect.catch(
756
+ Effect.provideContext(
757
+ collector ? Effect.provideService(effect, Transferable.Collector, collector) : effect,
758
+ schemas.context
759
+ ),
760
+ (error) =>
761
+ Effect.withFiber((fiber) => {
762
+ const defect = Cause.die(
763
+ `Failed to encode response for RPC "${schemas.tag}": ${SchemaIssue.defaultFormatter(error.issue)}`
764
+ )
765
+ reportCauseUnsafe(fiber, defect)
766
+ encodeFailed = true
767
+ return Effect.failCause(defect)
768
+ })
697
769
  ),
698
770
  (value) => send(client.id, responseEnvelope(requestId, tag, value), collector && collector.clearUnsafe())
699
771
  )
700
772
  return Effect.catchCause(write, (cause) => {
701
773
  client.schemas.delete(requestId)
702
- const defect = Cause.squash(Cause.map(cause, (e) => SchemaIssue.defaultFormatter(e.issue)))
774
+ // An encode failure ends the request with the defect, so the request
775
+ // span records it. Other failures stop the request as a cancellation.
703
776
  return Effect.andThen(
704
- sendRequestDefect(client, requestId, schemas.encodeExit, defect),
705
- server.write(client.id, { _tag: "Interrupt", requestId, interruptors: [] })
777
+ sendRequestDefect(client, requestId, schemas.encodeExit, Cause.squash(cause)),
778
+ encodeFailed
779
+ ? Effect.failCause(cause)
780
+ : server.write(client.id, { _tag: "Interrupt", requestId, interruptors: [] })
706
781
  )
707
782
  })
708
783
  }
@@ -1074,7 +1149,7 @@ export const makeProtocolWithHttpEffect: (
1074
1149
  RpcSerialization.RpcSerialization
1075
1150
  > = Effect.fnUntraced(function*(options = {}) {
1076
1151
  const serialization = yield* RpcSerialization.RpcSerialization
1077
- const encodeDefectUnsafe = Schema.encodeSync(serialization.codecFor(Schema.Defect()))
1152
+ const { encodeDefectUnsafe } = defectCodecs(serialization.codecFor)
1078
1153
  const includesFraming = serialization.includesFraming
1079
1154
  const isBinary = !serialization.contentType.includes("json")
1080
1155
 
@@ -1534,7 +1609,7 @@ const makeSocketProtocol: Effect.Effect<
1534
1609
  RpcSerialization.RpcSerialization
1535
1610
  > = Effect.gen(function*() {
1536
1611
  const serialization = yield* RpcSerialization.RpcSerialization
1537
- const encodeDefectUnsafe = Schema.encodeSync(serialization.codecFor(Schema.Defect()))
1612
+ const { encodeDefectUnsafe } = defectCodecs(serialization.codecFor)
1538
1613
  const disconnects = yield* Queue.make<number>()
1539
1614
 
1540
1615
  let clientId = 0