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
@@ -0,0 +1,731 @@
1
+ import * as Context from "../Context.ts";
2
+ import * as Duration from "../Duration.ts";
3
+ import * as Effect from "../Effect.ts";
4
+ import * as Headers from "../http/Headers.ts";
5
+ import * as HttpClient from "../http/HttpClient.ts";
6
+ import * as UrlParams from "../http/UrlParams.ts";
7
+ import * as Layer from "../Layer.ts";
8
+ import * as Schema from "../Schema.ts";
9
+ import type * as Scope from "../Scope.ts";
10
+ import * as Socket from "../socket/Socket.ts";
11
+ import * as Stream from "../Stream.ts";
12
+ import type { Kind } from "./GraphQL.ts";
13
+ import { TransportError } from "./GraphQLClientError.ts";
14
+ /**
15
+ * The request a transport sends. Middleware sees and may rewrite it before it
16
+ * reaches the transport.
17
+ *
18
+ * **Details**
19
+ *
20
+ * `kind` is the operation type, which the HTTP transport uses to send queries
21
+ * as `GET` when `queryMethod: "GET"` is set. `variables` are already encoded
22
+ * through the operation's variables Schema.
23
+ *
24
+ * `headers` and `urlParams` are applied by the HTTP transport, to queries,
25
+ * mutations and graphql-sse subscriptions alike. A graphql-ws transport
26
+ * ignores both, because graphql-ws has no per-operation headers or URL.
27
+ * Request headers are normalized, immutable `Headers.Headers` values.
28
+ *
29
+ * @stability experimental
30
+ * @category models
31
+ * @since 4.0.0
32
+ */
33
+ export interface GraphQLRequest {
34
+ readonly kind: Kind;
35
+ readonly query: string;
36
+ readonly operationName: string;
37
+ readonly variables: unknown;
38
+ readonly extensions?: Record<string, unknown> | undefined;
39
+ readonly headers: Headers.Headers;
40
+ readonly urlParams: UrlParams.UrlParams;
41
+ }
42
+ /**
43
+ * A raw GraphQL result before schema decoding. Middleware receive it from
44
+ * `next` and can read response `extensions`, such as rate-limit costs.
45
+ *
46
+ * **Details**
47
+ *
48
+ * `status` and `headers` are transport metadata, not part of the GraphQL
49
+ * response body: the client decodes the body without them and then copies
50
+ * what the transport reported. Middleware may read or rewrite them, and a
51
+ * failed call's `ResponseError` carries the final values. Headers use
52
+ * `Headers.Headers` at runtime and encode as a plain string record.
53
+ *
54
+ * @stability experimental
55
+ * @category schemas
56
+ * @since 4.0.0
57
+ */
58
+ export declare const ExecutionResult: Schema.Struct<{
59
+ readonly data: Schema.optional<Schema.Unknown>;
60
+ readonly errors: Schema.optional<Schema.$Array<Schema.StructWithRest<Schema.Struct<{
61
+ readonly message: Schema.String;
62
+ readonly locations: Schema.optional<Schema.$Array<Schema.Struct<{
63
+ readonly line: Schema.Number;
64
+ readonly column: Schema.Number;
65
+ }>>>;
66
+ readonly path: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.String, Schema.Number]>>>;
67
+ readonly extensions: Schema.optional<Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>>;
68
+ }>, readonly [Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>]>>>;
69
+ readonly extensions: Schema.optional<Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>>;
70
+ readonly status: Schema.optional<Schema.Int>;
71
+ readonly headers: Schema.optional<Schema.decodeTo<Schema.declare<Headers.Headers, Headers.Headers>, Schema.$Record<Schema.String, Schema.String>, never, never>>;
72
+ }>;
73
+ /**
74
+ * The decoded type of {@link ExecutionResult}.
75
+ *
76
+ * @stability experimental
77
+ * @category models
78
+ * @since 4.0.0
79
+ */
80
+ export type ExecutionResult = typeof ExecutionResult.Type;
81
+ declare const GraphQLProtocol_base: Context.ServiceClass<GraphQLProtocol, "effect/graphql/GraphQLProtocol", {
82
+ readonly execute: (request: GraphQLRequest) => Effect.Effect<{
83
+ readonly body: unknown;
84
+ readonly status?: number | undefined;
85
+ readonly headers?: Headers.Headers | undefined;
86
+ }, TransportError>;
87
+ readonly subscribe: (request: GraphQLRequest) => Stream.Stream<{
88
+ readonly body: unknown;
89
+ readonly status?: number | undefined;
90
+ readonly headers?: Headers.Headers | undefined;
91
+ }, TransportError>;
92
+ }>;
93
+ /**
94
+ * The transport service. `execute` answers a query or mutation with the raw
95
+ * JSON body, and `subscribe` turns a subscription into a stream of raw events.
96
+ * Both fail only with `TransportError`; GraphQL `errors` are left in the body
97
+ * for the client to interpret.
98
+ *
99
+ * **Details**
100
+ *
101
+ * Each answer is `{ body, status?, headers? }`. The HTTP transport sets
102
+ * `headers` on every answer, including graphql-sse events, and `status` on
103
+ * all but graphql-sse events. Headers are `Headers.Headers` values.
104
+ * graphql-ws leaves both unset.
105
+ *
106
+ * **Example** (A scripted transport for tests)
107
+ *
108
+ * ```ts import.meta.vitest
109
+ * import { Effect, Layer, Schema, Stream } from "effect"
110
+ * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql"
111
+ *
112
+ * const Viewer = GraphQL.query("Viewer", {
113
+ * document: "query Viewer{viewer{login}}",
114
+ * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) })
115
+ * })
116
+ *
117
+ * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, {
118
+ * execute: () => Effect.succeed({ body: { data: { viewer: { login: "tim" } } } }),
119
+ * subscribe: () => Stream.empty
120
+ * })
121
+ *
122
+ * const program = Effect.gen(function*() {
123
+ * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer))
124
+ * return yield* client.Viewer()
125
+ * })
126
+ *
127
+ * await Effect.runPromise(program.pipe(Effect.provide(Scripted))) // => { viewer: { login: "tim" } }
128
+ * ```
129
+ *
130
+ * @stability experimental
131
+ * @category services
132
+ * @since 4.0.0
133
+ */
134
+ export declare class GraphQLProtocol extends GraphQLProtocol_base {
135
+ }
136
+ /**
137
+ * Builds the HTTP transport as an effect, for composing transports by hand.
138
+ * Most code uses {@link layerHttp}.
139
+ *
140
+ * **Details**
141
+ *
142
+ * Takes the same options as {@link layerHttp}, including `queryMethod`.
143
+ * Without `subscriptions`, subscriptions use graphql-sse distinct mode on
144
+ * `url`. With `subscriptions.webSocket`, they go over graphql-ws instead, and
145
+ * the effect also builds the graphql-ws transport, so it needs a
146
+ * `Socket.WebSocketConstructor` and a `Scope`.
147
+ *
148
+ * @stability experimental
149
+ * @category constructors
150
+ * @since 4.0.0
151
+ */
152
+ export declare const makeHttp: {
153
+ /**
154
+ * Builds the HTTP transport as an effect, for composing transports by hand.
155
+ * Most code uses {@link layerHttp}.
156
+ *
157
+ * **Details**
158
+ *
159
+ * Takes the same options as {@link layerHttp}, including `queryMethod`.
160
+ * Without `subscriptions`, subscriptions use graphql-sse distinct mode on
161
+ * `url`. With `subscriptions.webSocket`, they go over graphql-ws instead, and
162
+ * the effect also builds the graphql-ws transport, so it needs a
163
+ * `Socket.WebSocketConstructor` and a `Scope`.
164
+ *
165
+ * @stability experimental
166
+ * @category constructors
167
+ * @since 4.0.0
168
+ */
169
+ <R = never>(options: {
170
+ readonly url: string;
171
+ readonly queryMethod?: "GET" | "POST" | undefined;
172
+ readonly subscriptions: {
173
+ readonly webSocket: {
174
+ readonly url: string;
175
+ readonly headers?: Headers.Input | undefined;
176
+ readonly connectionParams?: Effect.Effect<Record<string, unknown> | undefined, unknown, R> | undefined;
177
+ readonly connectionAckTimeout?: Duration.Input | undefined;
178
+ readonly keepAlive?: Duration.Input | false | undefined;
179
+ readonly idleTimeout?: Duration.Input | undefined;
180
+ };
181
+ };
182
+ }): Effect.Effect<GraphQLProtocol["Service"], never, HttpClient.HttpClient | Socket.WebSocketConstructor | Scope.Scope | R>;
183
+ /**
184
+ * Builds the HTTP transport as an effect, for composing transports by hand.
185
+ * Most code uses {@link layerHttp}.
186
+ *
187
+ * **Details**
188
+ *
189
+ * Takes the same options as {@link layerHttp}, including `queryMethod`.
190
+ * Without `subscriptions`, subscriptions use graphql-sse distinct mode on
191
+ * `url`. With `subscriptions.webSocket`, they go over graphql-ws instead, and
192
+ * the effect also builds the graphql-ws transport, so it needs a
193
+ * `Socket.WebSocketConstructor` and a `Scope`.
194
+ *
195
+ * @stability experimental
196
+ * @category constructors
197
+ * @since 4.0.0
198
+ */
199
+ (options: {
200
+ readonly url: string;
201
+ readonly queryMethod?: "GET" | "POST" | undefined;
202
+ readonly subscriptions?: undefined;
203
+ }): Effect.Effect<GraphQLProtocol["Service"], never, HttpClient.HttpClient>;
204
+ };
205
+ /**
206
+ * The HTTP transport: queries and mutations are sent as `POST` with a JSON
207
+ * body to `url`, using the `HttpClient` in context. Subscriptions use
208
+ * graphql-sse distinct mode on the same URL, or graphql-ws when
209
+ * `subscriptions.webSocket` is set.
210
+ *
211
+ * **Details**
212
+ *
213
+ * With `queryMethod: "GET"` (default `"POST"`), queries are sent as `GET`
214
+ * with no body: `query` and `operationName` become URL params, plus
215
+ * `variables` and `extensions` as JSON when set. Mutations are always
216
+ * `POST`, and so are `GraphQLResolver.aliased` batches. A long query is not
217
+ * retried as `POST`.
218
+ *
219
+ * A request's `headers` and `urlParams`, from the call options or from
220
+ * middleware, are applied to every HTTP request. A query string already on
221
+ * `url` is kept. On `GET`, the request's `urlParams` come before the GraphQL
222
+ * params, which replace any caller param with the same name.
223
+ *
224
+ * Every response's HTTP `status` is passed to the client as
225
+ * `ExecutionResult.status`, and a call that fails with GraphQL `errors`
226
+ * reports it as `ResponseError.status`. Response headers are passed the
227
+ * same way, as `ExecutionResult.headers` and `ResponseError.headers`.
228
+ *
229
+ * A response is a GraphQL response when its `Content-Type` is
230
+ * `application/graphql-response+json`, whatever the status, or when it is
231
+ * `application/json` and the body has a list of `errors` or a `data` object
232
+ * (or `null`). Media types match case-insensitively. Anything else
233
+ * is a `TransportError` with the response `status` and `headers`, and a
234
+ * `Retry-After` header (whole seconds or an HTTP date, measured from when the
235
+ * response arrived) becomes `retryAfter`.
236
+ *
237
+ * A subscription is a `POST` with `Accept: text/event-stream`. Each `next`
238
+ * event is emitted with the response headers but no status, and the stream
239
+ * ends on a `complete` event, with or without a `data:` line. A body that
240
+ * fails, or ends without a `complete` event, is a retryable `TransportError`
241
+ * with a server `retry:` line as its `retryAfter`, so the client's
242
+ * `subscriptionRetry` resubscribes. A non-stream answer, such as a `400` with
243
+ * `errors`, is read like a query's response. Interrupting the stream aborts
244
+ * the request.
245
+ *
246
+ * With `subscriptions: { webSocket }`, subscriptions go over graphql-ws as in
247
+ * {@link layerWebSocket}, and the layer needs a `Socket.WebSocketConstructor`.
248
+ *
249
+ * **Example** (Building a client over HTTP)
250
+ *
251
+ * ```ts import.meta.vitest
252
+ * import { Effect, Layer, Schema } from "effect"
253
+ * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql"
254
+ * import { HttpClient, HttpClientResponse } from "effect/http"
255
+ *
256
+ * const Viewer = GraphQL.query("Viewer", {
257
+ * document: "query Viewer{viewer{login}}",
258
+ * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) })
259
+ * })
260
+ *
261
+ * // A stand-in for a real HttpClient layer such as FetchHttpClient.layer
262
+ * const FakeServer = Layer.succeed(
263
+ * HttpClient.HttpClient,
264
+ * HttpClient.make((request) =>
265
+ * Effect.succeed(HttpClientResponse.fromWeb(
266
+ * request,
267
+ * new Response(JSON.stringify({ data: { viewer: { login: "tim" } } }), {
268
+ * headers: { "content-type": "application/graphql-response+json" }
269
+ * })
270
+ * ))
271
+ * )
272
+ * )
273
+ *
274
+ * const program = Effect.gen(function*() {
275
+ * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer))
276
+ * return yield* client.Viewer()
277
+ * }).pipe(
278
+ * Effect.provide(GraphQLProtocol.layerHttp({ url: "https://api.github.com/graphql" })),
279
+ * Effect.provide(FakeServer)
280
+ * )
281
+ *
282
+ * await Effect.runPromise(program) // => { viewer: { login: "tim" } }
283
+ * ```
284
+ *
285
+ * **Example** (Queries over GET with a per-call URL param)
286
+ *
287
+ * ```ts import.meta.vitest
288
+ * import { Effect, Layer, Schema } from "effect"
289
+ * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql"
290
+ * import { HttpClient, HttpClientResponse } from "effect/http"
291
+ *
292
+ * const Viewer = GraphQL.query("Viewer", {
293
+ * document: "query Viewer{viewer{login}}",
294
+ * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) })
295
+ * })
296
+ *
297
+ * // A stand-in server that answers with the method and the `preview` param
298
+ * const FakeServer = Layer.succeed(
299
+ * HttpClient.HttpClient,
300
+ * HttpClient.make((request, url) =>
301
+ * Effect.succeed(HttpClientResponse.fromWeb(
302
+ * request,
303
+ * new Response(
304
+ * JSON.stringify({ data: { viewer: { login: `${request.method} ${url.searchParams.get("preview")}` } } }),
305
+ * { headers: { "content-type": "application/graphql-response+json" } }
306
+ * )
307
+ * ))
308
+ * )
309
+ * )
310
+ *
311
+ * const program = Effect.gen(function*() {
312
+ * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer))
313
+ * return yield* client.Viewer(undefined, { urlParams: { preview: "draft-token" } })
314
+ * }).pipe(
315
+ * Effect.provide(GraphQLProtocol.layerHttp({ url: "https://cms.example.com/graphql", queryMethod: "GET" })),
316
+ * Effect.provide(FakeServer)
317
+ * )
318
+ *
319
+ * await Effect.runPromise(program) // => { viewer: { login: "GET draft-token" } }
320
+ * ```
321
+ *
322
+ * **Example** (Subscriptions over graphql-ws, everything else over POST)
323
+ *
324
+ * ```ts import.meta.vitest
325
+ * import { Effect } from "effect"
326
+ * import { GraphQLProtocol } from "effect/graphql"
327
+ *
328
+ * const token = Effect.succeed("secret")
329
+ *
330
+ * // Provide an HttpClient and a Socket.WebSocketConstructor, such as
331
+ * // FetchHttpClient.layer and NodeSocket.layerWebSocketConstructor
332
+ * export const Protocol = GraphQLProtocol.layerHttp({
333
+ * url: "https://example.com/graphql",
334
+ * subscriptions: {
335
+ * webSocket: {
336
+ * url: "wss://example.com/graphql",
337
+ * connectionParams: Effect.map(token, (token) => ({ authorization: `Bearer ${token}` }))
338
+ * }
339
+ * }
340
+ * })
341
+ * ```
342
+ *
343
+ * @stability experimental
344
+ * @category layers
345
+ * @since 4.0.0
346
+ */
347
+ export declare const layerHttp: {
348
+ /**
349
+ * The HTTP transport: queries and mutations are sent as `POST` with a JSON
350
+ * body to `url`, using the `HttpClient` in context. Subscriptions use
351
+ * graphql-sse distinct mode on the same URL, or graphql-ws when
352
+ * `subscriptions.webSocket` is set.
353
+ *
354
+ * **Details**
355
+ *
356
+ * With `queryMethod: "GET"` (default `"POST"`), queries are sent as `GET`
357
+ * with no body: `query` and `operationName` become URL params, plus
358
+ * `variables` and `extensions` as JSON when set. Mutations are always
359
+ * `POST`, and so are `GraphQLResolver.aliased` batches. A long query is not
360
+ * retried as `POST`.
361
+ *
362
+ * A request's `headers` and `urlParams`, from the call options or from
363
+ * middleware, are applied to every HTTP request. A query string already on
364
+ * `url` is kept. On `GET`, the request's `urlParams` come before the GraphQL
365
+ * params, which replace any caller param with the same name.
366
+ *
367
+ * Every response's HTTP `status` is passed to the client as
368
+ * `ExecutionResult.status`, and a call that fails with GraphQL `errors`
369
+ * reports it as `ResponseError.status`. Response headers are passed the
370
+ * same way, as `ExecutionResult.headers` and `ResponseError.headers`.
371
+ *
372
+ * A response is a GraphQL response when its `Content-Type` is
373
+ * `application/graphql-response+json`, whatever the status, or when it is
374
+ * `application/json` and the body has a list of `errors` or a `data` object
375
+ * (or `null`). Media types match case-insensitively. Anything else
376
+ * is a `TransportError` with the response `status` and `headers`, and a
377
+ * `Retry-After` header (whole seconds or an HTTP date, measured from when the
378
+ * response arrived) becomes `retryAfter`.
379
+ *
380
+ * A subscription is a `POST` with `Accept: text/event-stream`. Each `next`
381
+ * event is emitted with the response headers but no status, and the stream
382
+ * ends on a `complete` event, with or without a `data:` line. A body that
383
+ * fails, or ends without a `complete` event, is a retryable `TransportError`
384
+ * with a server `retry:` line as its `retryAfter`, so the client's
385
+ * `subscriptionRetry` resubscribes. A non-stream answer, such as a `400` with
386
+ * `errors`, is read like a query's response. Interrupting the stream aborts
387
+ * the request.
388
+ *
389
+ * With `subscriptions: { webSocket }`, subscriptions go over graphql-ws as in
390
+ * {@link layerWebSocket}, and the layer needs a `Socket.WebSocketConstructor`.
391
+ *
392
+ * **Example** (Building a client over HTTP)
393
+ *
394
+ * ```ts import.meta.vitest
395
+ * import { Effect, Layer, Schema } from "effect"
396
+ * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql"
397
+ * import { HttpClient, HttpClientResponse } from "effect/http"
398
+ *
399
+ * const Viewer = GraphQL.query("Viewer", {
400
+ * document: "query Viewer{viewer{login}}",
401
+ * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) })
402
+ * })
403
+ *
404
+ * // A stand-in for a real HttpClient layer such as FetchHttpClient.layer
405
+ * const FakeServer = Layer.succeed(
406
+ * HttpClient.HttpClient,
407
+ * HttpClient.make((request) =>
408
+ * Effect.succeed(HttpClientResponse.fromWeb(
409
+ * request,
410
+ * new Response(JSON.stringify({ data: { viewer: { login: "tim" } } }), {
411
+ * headers: { "content-type": "application/graphql-response+json" }
412
+ * })
413
+ * ))
414
+ * )
415
+ * )
416
+ *
417
+ * const program = Effect.gen(function*() {
418
+ * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer))
419
+ * return yield* client.Viewer()
420
+ * }).pipe(
421
+ * Effect.provide(GraphQLProtocol.layerHttp({ url: "https://api.github.com/graphql" })),
422
+ * Effect.provide(FakeServer)
423
+ * )
424
+ *
425
+ * await Effect.runPromise(program) // => { viewer: { login: "tim" } }
426
+ * ```
427
+ *
428
+ * **Example** (Queries over GET with a per-call URL param)
429
+ *
430
+ * ```ts import.meta.vitest
431
+ * import { Effect, Layer, Schema } from "effect"
432
+ * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql"
433
+ * import { HttpClient, HttpClientResponse } from "effect/http"
434
+ *
435
+ * const Viewer = GraphQL.query("Viewer", {
436
+ * document: "query Viewer{viewer{login}}",
437
+ * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) })
438
+ * })
439
+ *
440
+ * // A stand-in server that answers with the method and the `preview` param
441
+ * const FakeServer = Layer.succeed(
442
+ * HttpClient.HttpClient,
443
+ * HttpClient.make((request, url) =>
444
+ * Effect.succeed(HttpClientResponse.fromWeb(
445
+ * request,
446
+ * new Response(
447
+ * JSON.stringify({ data: { viewer: { login: `${request.method} ${url.searchParams.get("preview")}` } } }),
448
+ * { headers: { "content-type": "application/graphql-response+json" } }
449
+ * )
450
+ * ))
451
+ * )
452
+ * )
453
+ *
454
+ * const program = Effect.gen(function*() {
455
+ * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer))
456
+ * return yield* client.Viewer(undefined, { urlParams: { preview: "draft-token" } })
457
+ * }).pipe(
458
+ * Effect.provide(GraphQLProtocol.layerHttp({ url: "https://cms.example.com/graphql", queryMethod: "GET" })),
459
+ * Effect.provide(FakeServer)
460
+ * )
461
+ *
462
+ * await Effect.runPromise(program) // => { viewer: { login: "GET draft-token" } }
463
+ * ```
464
+ *
465
+ * **Example** (Subscriptions over graphql-ws, everything else over POST)
466
+ *
467
+ * ```ts import.meta.vitest
468
+ * import { Effect } from "effect"
469
+ * import { GraphQLProtocol } from "effect/graphql"
470
+ *
471
+ * const token = Effect.succeed("secret")
472
+ *
473
+ * // Provide an HttpClient and a Socket.WebSocketConstructor, such as
474
+ * // FetchHttpClient.layer and NodeSocket.layerWebSocketConstructor
475
+ * export const Protocol = GraphQLProtocol.layerHttp({
476
+ * url: "https://example.com/graphql",
477
+ * subscriptions: {
478
+ * webSocket: {
479
+ * url: "wss://example.com/graphql",
480
+ * connectionParams: Effect.map(token, (token) => ({ authorization: `Bearer ${token}` }))
481
+ * }
482
+ * }
483
+ * })
484
+ * ```
485
+ *
486
+ * @stability experimental
487
+ * @category layers
488
+ * @since 4.0.0
489
+ */
490
+ <R = never>(options: {
491
+ readonly url: string;
492
+ readonly queryMethod?: "GET" | "POST" | undefined;
493
+ readonly subscriptions: {
494
+ readonly webSocket: {
495
+ readonly url: string;
496
+ readonly headers?: Headers.Input | undefined;
497
+ readonly connectionParams?: Effect.Effect<Record<string, unknown> | undefined, unknown, R> | undefined;
498
+ readonly connectionAckTimeout?: Duration.Input | undefined;
499
+ readonly keepAlive?: Duration.Input | false | undefined;
500
+ readonly idleTimeout?: Duration.Input | undefined;
501
+ };
502
+ };
503
+ }): Layer.Layer<GraphQLProtocol, never, HttpClient.HttpClient | Socket.WebSocketConstructor | R>;
504
+ /**
505
+ * The HTTP transport: queries and mutations are sent as `POST` with a JSON
506
+ * body to `url`, using the `HttpClient` in context. Subscriptions use
507
+ * graphql-sse distinct mode on the same URL, or graphql-ws when
508
+ * `subscriptions.webSocket` is set.
509
+ *
510
+ * **Details**
511
+ *
512
+ * With `queryMethod: "GET"` (default `"POST"`), queries are sent as `GET`
513
+ * with no body: `query` and `operationName` become URL params, plus
514
+ * `variables` and `extensions` as JSON when set. Mutations are always
515
+ * `POST`, and so are `GraphQLResolver.aliased` batches. A long query is not
516
+ * retried as `POST`.
517
+ *
518
+ * A request's `headers` and `urlParams`, from the call options or from
519
+ * middleware, are applied to every HTTP request. A query string already on
520
+ * `url` is kept. On `GET`, the request's `urlParams` come before the GraphQL
521
+ * params, which replace any caller param with the same name.
522
+ *
523
+ * Every response's HTTP `status` is passed to the client as
524
+ * `ExecutionResult.status`, and a call that fails with GraphQL `errors`
525
+ * reports it as `ResponseError.status`. Response headers are passed the
526
+ * same way, as `ExecutionResult.headers` and `ResponseError.headers`.
527
+ *
528
+ * A response is a GraphQL response when its `Content-Type` is
529
+ * `application/graphql-response+json`, whatever the status, or when it is
530
+ * `application/json` and the body has a list of `errors` or a `data` object
531
+ * (or `null`). Media types match case-insensitively. Anything else
532
+ * is a `TransportError` with the response `status` and `headers`, and a
533
+ * `Retry-After` header (whole seconds or an HTTP date, measured from when the
534
+ * response arrived) becomes `retryAfter`.
535
+ *
536
+ * A subscription is a `POST` with `Accept: text/event-stream`. Each `next`
537
+ * event is emitted with the response headers but no status, and the stream
538
+ * ends on a `complete` event, with or without a `data:` line. A body that
539
+ * fails, or ends without a `complete` event, is a retryable `TransportError`
540
+ * with a server `retry:` line as its `retryAfter`, so the client's
541
+ * `subscriptionRetry` resubscribes. A non-stream answer, such as a `400` with
542
+ * `errors`, is read like a query's response. Interrupting the stream aborts
543
+ * the request.
544
+ *
545
+ * With `subscriptions: { webSocket }`, subscriptions go over graphql-ws as in
546
+ * {@link layerWebSocket}, and the layer needs a `Socket.WebSocketConstructor`.
547
+ *
548
+ * **Example** (Building a client over HTTP)
549
+ *
550
+ * ```ts import.meta.vitest
551
+ * import { Effect, Layer, Schema } from "effect"
552
+ * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql"
553
+ * import { HttpClient, HttpClientResponse } from "effect/http"
554
+ *
555
+ * const Viewer = GraphQL.query("Viewer", {
556
+ * document: "query Viewer{viewer{login}}",
557
+ * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) })
558
+ * })
559
+ *
560
+ * // A stand-in for a real HttpClient layer such as FetchHttpClient.layer
561
+ * const FakeServer = Layer.succeed(
562
+ * HttpClient.HttpClient,
563
+ * HttpClient.make((request) =>
564
+ * Effect.succeed(HttpClientResponse.fromWeb(
565
+ * request,
566
+ * new Response(JSON.stringify({ data: { viewer: { login: "tim" } } }), {
567
+ * headers: { "content-type": "application/graphql-response+json" }
568
+ * })
569
+ * ))
570
+ * )
571
+ * )
572
+ *
573
+ * const program = Effect.gen(function*() {
574
+ * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer))
575
+ * return yield* client.Viewer()
576
+ * }).pipe(
577
+ * Effect.provide(GraphQLProtocol.layerHttp({ url: "https://api.github.com/graphql" })),
578
+ * Effect.provide(FakeServer)
579
+ * )
580
+ *
581
+ * await Effect.runPromise(program) // => { viewer: { login: "tim" } }
582
+ * ```
583
+ *
584
+ * **Example** (Queries over GET with a per-call URL param)
585
+ *
586
+ * ```ts import.meta.vitest
587
+ * import { Effect, Layer, Schema } from "effect"
588
+ * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql"
589
+ * import { HttpClient, HttpClientResponse } from "effect/http"
590
+ *
591
+ * const Viewer = GraphQL.query("Viewer", {
592
+ * document: "query Viewer{viewer{login}}",
593
+ * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) })
594
+ * })
595
+ *
596
+ * // A stand-in server that answers with the method and the `preview` param
597
+ * const FakeServer = Layer.succeed(
598
+ * HttpClient.HttpClient,
599
+ * HttpClient.make((request, url) =>
600
+ * Effect.succeed(HttpClientResponse.fromWeb(
601
+ * request,
602
+ * new Response(
603
+ * JSON.stringify({ data: { viewer: { login: `${request.method} ${url.searchParams.get("preview")}` } } }),
604
+ * { headers: { "content-type": "application/graphql-response+json" } }
605
+ * )
606
+ * ))
607
+ * )
608
+ * )
609
+ *
610
+ * const program = Effect.gen(function*() {
611
+ * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer))
612
+ * return yield* client.Viewer(undefined, { urlParams: { preview: "draft-token" } })
613
+ * }).pipe(
614
+ * Effect.provide(GraphQLProtocol.layerHttp({ url: "https://cms.example.com/graphql", queryMethod: "GET" })),
615
+ * Effect.provide(FakeServer)
616
+ * )
617
+ *
618
+ * await Effect.runPromise(program) // => { viewer: { login: "GET draft-token" } }
619
+ * ```
620
+ *
621
+ * **Example** (Subscriptions over graphql-ws, everything else over POST)
622
+ *
623
+ * ```ts import.meta.vitest
624
+ * import { Effect } from "effect"
625
+ * import { GraphQLProtocol } from "effect/graphql"
626
+ *
627
+ * const token = Effect.succeed("secret")
628
+ *
629
+ * // Provide an HttpClient and a Socket.WebSocketConstructor, such as
630
+ * // FetchHttpClient.layer and NodeSocket.layerWebSocketConstructor
631
+ * export const Protocol = GraphQLProtocol.layerHttp({
632
+ * url: "https://example.com/graphql",
633
+ * subscriptions: {
634
+ * webSocket: {
635
+ * url: "wss://example.com/graphql",
636
+ * connectionParams: Effect.map(token, (token) => ({ authorization: `Bearer ${token}` }))
637
+ * }
638
+ * }
639
+ * })
640
+ * ```
641
+ *
642
+ * @stability experimental
643
+ * @category layers
644
+ * @since 4.0.0
645
+ */
646
+ (options: {
647
+ readonly url: string;
648
+ readonly queryMethod?: "GET" | "POST" | undefined;
649
+ readonly subscriptions?: undefined;
650
+ }): Layer.Layer<GraphQLProtocol, never, HttpClient.HttpClient>;
651
+ };
652
+ /**
653
+ * Builds the graphql-ws transport as an effect, for composing transports by
654
+ * hand. Most code uses {@link layerWebSocket}, which describes the options.
655
+ *
656
+ * @stability experimental
657
+ * @category constructors
658
+ * @since 4.0.0
659
+ */
660
+ export declare const makeWebSocket: <R = never>(options: {
661
+ readonly url: string;
662
+ readonly headers?: Headers.Input | undefined;
663
+ readonly connectionParams?: Effect.Effect<Record<string, unknown> | undefined, unknown, R> | undefined;
664
+ readonly connectionAckTimeout?: Duration.Input | undefined;
665
+ readonly keepAlive?: Duration.Input | false | undefined;
666
+ readonly idleTimeout?: Duration.Input | undefined;
667
+ }) => Effect.Effect<GraphQLProtocol["Service"], never, Socket.WebSocketConstructor | Scope.Scope | R>;
668
+ /**
669
+ * The graphql-ws transport: every operation goes over one WebSocket using the
670
+ * `graphql-transport-ws` subprotocol, with the `Socket.WebSocketConstructor`
671
+ * in context.
672
+ *
673
+ * **Details**
674
+ *
675
+ * The socket connects lazily and multiplexes operations by id. It closes after
676
+ * `idleTimeout` (default 0) with no active operations, or with code `1000`
677
+ * when the layer's scope closes.
678
+ *
679
+ * - Operations wait for `connection_ack`. `connectionAckTimeout` (default
680
+ * 10 seconds) starts after sending `connection_init`.
681
+ * - `connectionParams` runs on every connection, allowing token refresh.
682
+ * Failure or a socket close during evaluation is a `TransportError`.
683
+ * - Handshake `headers` accept `Headers.Input` and are normalized before
684
+ * reaching the socket. They require a Node or Bun WebSocket constructor;
685
+ * browsers cannot set them. Per-operation `headers` and `urlParams` are ignored.
686
+ * - Results carry no HTTP `status`.
687
+ * - `keepAlive` (default 10 seconds, or `false` to disable) sends `ping`.
688
+ * No server frame in the following interval causes a retryable failure.
689
+ * Server `ping` receives `pong`.
690
+ * - Lost connections fail every active operation with a `TransportError`
691
+ * carrying the close code. See `GraphQLClientError.isFatalCloseCode` for
692
+ * non-retryable codes. The transport never replays operations; the client
693
+ * retries subscriptions and the next operation reconnects.
694
+ * - Once the layer's scope has closed, every new operation fails at once
695
+ * with a non-retryable `TransportError` marked `fatal`.
696
+ * - Messages follow graphql-ws validation. Invalid messages close the socket
697
+ * with fatal code `4400`; valid messages for unknown ids are ignored.
698
+ * - Server `error` messages become `ResponseError` values. Interrupting a
699
+ * subscription sends `complete`.
700
+ *
701
+ * **Example** (A client over graphql-ws)
702
+ *
703
+ * ```ts import.meta.vitest
704
+ * import { Effect, Layer } from "effect"
705
+ * import { GraphQLProtocol } from "effect/graphql"
706
+ * import type { Socket } from "effect/socket"
707
+ *
708
+ * // Provide a Socket.WebSocketConstructor, such as
709
+ * // Socket.layerWebSocketConstructorGlobal in a browser
710
+ * export const Protocol: Layer.Layer<GraphQLProtocol.GraphQLProtocol, never, Socket.WebSocketConstructor> =
711
+ * GraphQLProtocol.layerWebSocket({
712
+ * url: "wss://example.com/graphql",
713
+ * connectionParams: Effect.succeed({ authorization: "Bearer secret" }),
714
+ * idleTimeout: "30 seconds"
715
+ * })
716
+ * ```
717
+ *
718
+ * @stability experimental
719
+ * @category layers
720
+ * @since 4.0.0
721
+ */
722
+ export declare const layerWebSocket: <R = never>(options: {
723
+ readonly url: string;
724
+ readonly headers?: Headers.Input | undefined;
725
+ readonly connectionParams?: Effect.Effect<Record<string, unknown> | undefined, unknown, R> | undefined;
726
+ readonly connectionAckTimeout?: Duration.Input | undefined;
727
+ readonly keepAlive?: Duration.Input | false | undefined;
728
+ readonly idleTimeout?: Duration.Input | undefined;
729
+ }) => Layer.Layer<GraphQLProtocol, never, Socket.WebSocketConstructor | R>;
730
+ export {};
731
+ //# sourceMappingURL=GraphQLProtocol.d.ts.map