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.
- package/AGENTS.md +24 -0
- package/CLAUDE.md +24 -0
- package/ai-docs/package.json +2 -2
- package/ai-docs/src/52_graphql/10_basics.ts +111 -0
- package/ai-docs/src/52_graphql/20_testing.ts +45 -0
- package/ai-docs/src/52_graphql/30_batching.ts +116 -0
- package/ai-docs/src/52_graphql/40_aliased-batching.ts +122 -0
- package/ai-docs/src/52_graphql/50_errors-and-retries.ts +74 -0
- package/ai-docs/src/52_graphql/index.md +6 -0
- package/dist/Context.d.ts.map +1 -1
- package/dist/Context.js +12 -3
- package/dist/Context.js.map +1 -1
- package/dist/Crypto.d.ts +33 -5
- package/dist/Crypto.d.ts.map +1 -1
- package/dist/Crypto.js +8 -2
- package/dist/Crypto.js.map +1 -1
- package/dist/DateTime.d.ts +9 -6
- package/dist/DateTime.d.ts.map +1 -1
- package/dist/DateTime.js +9 -6
- package/dist/DateTime.js.map +1 -1
- package/dist/Duration.d.ts +6 -6
- package/dist/Duration.d.ts.map +1 -1
- package/dist/Duration.js +27 -8
- package/dist/Duration.js.map +1 -1
- package/dist/FileSystem.d.ts +44 -2
- package/dist/FileSystem.d.ts.map +1 -1
- package/dist/FileSystem.js.map +1 -1
- package/dist/RequestResolver.d.ts.map +1 -1
- package/dist/RequestResolver.js +4 -10
- package/dist/RequestResolver.js.map +1 -1
- package/dist/Scheduler.d.ts +9 -0
- package/dist/Scheduler.d.ts.map +1 -1
- package/dist/Scheduler.js +9 -0
- package/dist/Scheduler.js.map +1 -1
- package/dist/Schema.d.ts +481 -1
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +362 -4
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaGetter.d.ts +4 -0
- package/dist/SchemaGetter.d.ts.map +1 -1
- package/dist/SchemaGetter.js +52 -33
- package/dist/SchemaGetter.js.map +1 -1
- package/dist/Sink.d.ts.map +1 -1
- package/dist/Sink.js +38 -17
- package/dist/Sink.js.map +1 -1
- package/dist/Stdio.d.ts +7 -1
- package/dist/Stdio.d.ts.map +1 -1
- package/dist/Stdio.js +1 -0
- package/dist/Stdio.js.map +1 -1
- package/dist/Stream.d.ts +22 -11
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +21 -6
- package/dist/Stream.js.map +1 -1
- package/dist/Utils.js +8 -3
- package/dist/Utils.js.map +1 -1
- package/dist/ai/AnthropicStructuredOutput.js +0 -2
- package/dist/ai/AnthropicStructuredOutput.js.map +1 -1
- package/dist/ai/Chat.d.ts +2 -2
- package/dist/ai/Chat.d.ts.map +1 -1
- package/dist/ai/LanguageModel.d.ts +38 -7
- package/dist/ai/LanguageModel.d.ts.map +1 -1
- package/dist/ai/LanguageModel.js +25 -7
- package/dist/ai/LanguageModel.js.map +1 -1
- package/dist/ai/McpServer.d.ts +61 -0
- package/dist/ai/McpServer.d.ts.map +1 -1
- package/dist/ai/McpServer.js +196 -44
- package/dist/ai/McpServer.js.map +1 -1
- package/dist/ai/Prompt.d.ts.map +1 -1
- package/dist/ai/Prompt.js +28 -5
- package/dist/ai/Prompt.js.map +1 -1
- package/dist/ai/Response.d.ts +4 -3
- package/dist/ai/Response.d.ts.map +1 -1
- package/dist/ai/Response.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js +5 -0
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
- package/dist/ai/internal/mcpProtocol.js.map +1 -1
- package/dist/ai/internal/mcpRuntime.js +1 -0
- package/dist/ai/internal/mcpRuntime.js.map +1 -1
- package/dist/cli/CliOutput.d.ts +27 -0
- package/dist/cli/CliOutput.d.ts.map +1 -1
- package/dist/cli/CliOutput.js +33 -10
- package/dist/cli/CliOutput.js.map +1 -1
- package/dist/cli/Command.d.ts.map +1 -1
- package/dist/cli/Command.js +6 -3
- package/dist/cli/Command.js.map +1 -1
- package/dist/cli/Completions.d.ts +3 -3
- package/dist/cli/Completions.d.ts.map +1 -1
- package/dist/cli/Completions.js +8 -5
- package/dist/cli/Completions.js.map +1 -1
- package/dist/cli/GlobalFlag.d.ts +5 -4
- package/dist/cli/GlobalFlag.d.ts.map +1 -1
- package/dist/cli/GlobalFlag.js +3 -3
- package/dist/cli/GlobalFlag.js.map +1 -1
- package/dist/cli/Prompt.d.ts +17 -1
- package/dist/cli/Prompt.d.ts.map +1 -1
- package/dist/cli/Prompt.js +119 -114
- package/dist/cli/Prompt.js.map +1 -1
- package/dist/cli/internal/ansi.d.ts +0 -1
- package/dist/cli/internal/ansi.d.ts.map +1 -1
- package/dist/cli/internal/ansi.js +20 -3
- package/dist/cli/internal/ansi.js.map +1 -1
- package/dist/cli/internal/completions/powershell.d.ts +2 -0
- package/dist/cli/internal/completions/powershell.d.ts.map +1 -0
- package/dist/cli/internal/completions/powershell.js +273 -0
- package/dist/cli/internal/completions/powershell.js.map +1 -0
- package/dist/cli/internal/completions/zsh.js +3 -2
- package/dist/cli/internal/completions/zsh.js.map +1 -1
- package/dist/cli/internal/wizard.d.ts +3 -3
- package/dist/cli/internal/wizard.d.ts.map +1 -1
- package/dist/cli/internal/wizard.js +21 -18
- package/dist/cli/internal/wizard.js.map +1 -1
- package/dist/cluster/ClusterSchema.d.ts +28 -0
- package/dist/cluster/ClusterSchema.d.ts.map +1 -1
- package/dist/cluster/ClusterSchema.js +30 -0
- package/dist/cluster/ClusterSchema.js.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.js +56 -26
- package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/cluster/MessageStorage.d.ts +18 -3
- package/dist/cluster/MessageStorage.d.ts.map +1 -1
- package/dist/cluster/MessageStorage.js +31 -11
- package/dist/cluster/MessageStorage.js.map +1 -1
- package/dist/cluster/Runners.d.ts.map +1 -1
- package/dist/cluster/Runners.js +8 -2
- package/dist/cluster/Runners.js.map +1 -1
- package/dist/cluster/Sharding.d.ts.map +1 -1
- package/dist/cluster/Sharding.js +187 -66
- package/dist/cluster/Sharding.js.map +1 -1
- package/dist/cluster/SqlMessageStorage.d.ts +59 -19
- package/dist/cluster/SqlMessageStorage.d.ts.map +1 -1
- package/dist/cluster/SqlMessageStorage.js +84 -55
- package/dist/cluster/SqlMessageStorage.js.map +1 -1
- package/dist/cluster/SqlRunnerStorage.d.ts +68 -19
- package/dist/cluster/SqlRunnerStorage.d.ts.map +1 -1
- package/dist/cluster/SqlRunnerStorage.js +191 -113
- package/dist/cluster/SqlRunnerStorage.js.map +1 -1
- package/dist/cluster/internal/entityManager.js +104 -37
- package/dist/cluster/internal/entityManager.js.map +1 -1
- package/dist/encoding/Sse.d.ts +6 -0
- package/dist/encoding/Sse.d.ts.map +1 -1
- package/dist/encoding/Sse.js +62 -70
- package/dist/encoding/Sse.js.map +1 -1
- package/dist/graphql/GraphQL.d.ts +349 -0
- package/dist/graphql/GraphQL.d.ts.map +1 -0
- package/dist/graphql/GraphQL.js +207 -0
- package/dist/graphql/GraphQL.js.map +1 -0
- package/dist/graphql/GraphQLClient.d.ts +562 -0
- package/dist/graphql/GraphQLClient.d.ts.map +1 -0
- package/dist/graphql/GraphQLClient.js +498 -0
- package/dist/graphql/GraphQLClient.js.map +1 -0
- package/dist/graphql/GraphQLClientError.d.ts +445 -0
- package/dist/graphql/GraphQLClientError.d.ts.map +1 -0
- package/dist/graphql/GraphQLClientError.js +479 -0
- package/dist/graphql/GraphQLClientError.js.map +1 -0
- package/dist/graphql/GraphQLGroup.d.ts +118 -0
- package/dist/graphql/GraphQLGroup.d.ts.map +1 -0
- package/dist/graphql/GraphQLGroup.js +109 -0
- package/dist/graphql/GraphQLGroup.js.map +1 -0
- package/dist/graphql/GraphQLMiddleware.d.ts +249 -0
- package/dist/graphql/GraphQLMiddleware.d.ts.map +1 -0
- package/dist/graphql/GraphQLMiddleware.js +130 -0
- package/dist/graphql/GraphQLMiddleware.js.map +1 -0
- package/dist/graphql/GraphQLProtocol.d.ts +731 -0
- package/dist/graphql/GraphQLProtocol.d.ts.map +1 -0
- package/dist/graphql/GraphQLProtocol.js +719 -0
- package/dist/graphql/GraphQLProtocol.js.map +1 -0
- package/dist/graphql/GraphQLResolver.d.ts +453 -0
- package/dist/graphql/GraphQLResolver.d.ts.map +1 -0
- package/dist/graphql/GraphQLResolver.js +552 -0
- package/dist/graphql/GraphQLResolver.js.map +1 -0
- package/dist/graphql/index.d.ts +40 -0
- package/dist/graphql/index.d.ts.map +1 -0
- package/dist/graphql/index.js +41 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/http/FindMyWay/internal/router.js +3 -6
- package/dist/http/FindMyWay/internal/router.js.map +1 -1
- package/dist/http/HttpClient.d.ts +21 -0
- package/dist/http/HttpClient.d.ts.map +1 -1
- package/dist/http/HttpClient.js +63 -12
- package/dist/http/HttpClient.js.map +1 -1
- package/dist/http/HttpEffect.d.ts.map +1 -1
- package/dist/http/HttpEffect.js +14 -7
- package/dist/http/HttpEffect.js.map +1 -1
- package/dist/http/HttpMiddleware.d.ts.map +1 -1
- package/dist/http/HttpMiddleware.js +31 -32
- package/dist/http/HttpMiddleware.js.map +1 -1
- package/dist/http/HttpRouter.d.ts +35 -0
- package/dist/http/HttpRouter.d.ts.map +1 -1
- package/dist/http/HttpRouter.js +35 -0
- package/dist/http/HttpRouter.js.map +1 -1
- package/dist/http/HttpServerResponse.d.ts +8 -6
- package/dist/http/HttpServerResponse.d.ts.map +1 -1
- package/dist/http/HttpServerResponse.js +27 -16
- package/dist/http/HttpServerResponse.js.map +1 -1
- package/dist/http/HttpTraceContext.d.ts.map +1 -1
- package/dist/http/HttpTraceContext.js +4 -2
- package/dist/http/HttpTraceContext.js.map +1 -1
- package/dist/http/Multipart.d.ts.map +1 -1
- package/dist/http/Multipart.js +15 -1
- package/dist/http/Multipart.js.map +1 -1
- package/dist/http-api/HttpApiScalar.d.ts +5 -0
- package/dist/http-api/HttpApiScalar.d.ts.map +1 -1
- package/dist/http-api/HttpApiScalar.js.map +1 -1
- package/dist/internal/dateTime.js +40 -35
- package/dist/internal/dateTime.js.map +1 -1
- package/dist/internal/effect.js +19 -9
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/graphql.d.ts +2 -0
- package/dist/internal/graphql.d.ts.map +1 -0
- package/dist/internal/graphql.js +195 -0
- package/dist/internal/graphql.js.map +1 -0
- package/dist/internal/graphqlHeaders.d.ts +4 -0
- package/dist/internal/graphqlHeaders.d.ts.map +1 -0
- package/dist/internal/graphqlHeaders.js +11 -0
- package/dist/internal/graphqlHeaders.js.map +1 -0
- package/dist/internal/request.js +20 -1
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/schema/toCodeDocument.js +4 -1
- package/dist/internal/schema/toCodeDocument.js.map +1 -1
- package/dist/internal/schema/toJsonSchemaDocument.js +29 -5
- package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -1
- package/dist/internal/version.js +1 -1
- package/dist/net/AddressResolver.d.ts +145 -0
- package/dist/net/AddressResolver.d.ts.map +1 -0
- package/dist/net/AddressResolver.js +114 -0
- package/dist/net/AddressResolver.js.map +1 -0
- package/dist/net/Dns.d.ts +596 -0
- package/dist/net/Dns.d.ts.map +1 -0
- package/dist/net/Dns.js +549 -0
- package/dist/net/Dns.js.map +1 -0
- package/dist/net/Host.d.ts +369 -0
- package/dist/net/Host.d.ts.map +1 -0
- package/dist/net/Host.js +397 -0
- package/dist/net/Host.js.map +1 -0
- package/dist/net/IpInterface.d.ts +76 -3
- package/dist/net/IpInterface.d.ts.map +1 -1
- package/dist/net/IpInterface.js +53 -4
- package/dist/net/IpInterface.js.map +1 -1
- package/dist/net/IpNetwork.d.ts +82 -8
- package/dist/net/IpNetwork.d.ts.map +1 -1
- package/dist/net/IpNetwork.js +60 -4
- package/dist/net/IpNetwork.js.map +1 -1
- package/dist/net/NetAddress.d.ts +396 -35
- package/dist/net/NetAddress.d.ts.map +1 -1
- package/dist/net/NetAddress.js +358 -34
- package/dist/net/NetAddress.js.map +1 -1
- package/dist/net/index.d.ts +15 -0
- package/dist/net/index.d.ts.map +1 -1
- package/dist/net/index.js +15 -0
- package/dist/net/index.js.map +1 -1
- package/dist/observability/OtlpMetrics.d.ts.map +1 -1
- package/dist/observability/OtlpMetrics.js +15 -21
- package/dist/observability/OtlpMetrics.js.map +1 -1
- package/dist/observability/PrometheusMetrics.js +1 -0
- package/dist/observability/PrometheusMetrics.js.map +1 -1
- package/dist/persistence/PersistedQueue.d.ts +32 -3
- package/dist/persistence/PersistedQueue.d.ts.map +1 -1
- package/dist/persistence/PersistedQueue.js +75 -16
- package/dist/persistence/PersistedQueue.js.map +1 -1
- package/dist/rpc/RpcClient.d.ts +22 -6
- package/dist/rpc/RpcClient.d.ts.map +1 -1
- package/dist/rpc/RpcClient.js +12 -5
- package/dist/rpc/RpcClient.js.map +1 -1
- package/dist/rpc/RpcServer.d.ts +6 -0
- package/dist/rpc/RpcServer.d.ts.map +1 -1
- package/dist/rpc/RpcServer.js +78 -29
- package/dist/rpc/RpcServer.js.map +1 -1
- package/dist/socket/DatagramSocket.d.ts +456 -0
- package/dist/socket/DatagramSocket.d.ts.map +1 -0
- package/dist/socket/DatagramSocket.js +535 -0
- package/dist/socket/DatagramSocket.js.map +1 -0
- package/dist/socket/Socket.d.ts +20 -1
- package/dist/socket/Socket.d.ts.map +1 -1
- package/dist/socket/Socket.js +9 -1
- package/dist/socket/Socket.js.map +1 -1
- package/dist/socket/index.d.ts +5 -0
- package/dist/socket/index.d.ts.map +1 -1
- package/dist/socket/index.js +5 -0
- package/dist/socket/index.js.map +1 -1
- package/dist/sql/Migrator.d.ts.map +1 -1
- package/dist/sql/Migrator.js +7 -2
- package/dist/sql/Migrator.js.map +1 -1
- package/dist/sql/SqlClient.d.ts +7 -1
- package/dist/sql/SqlClient.d.ts.map +1 -1
- package/dist/sql/SqlClient.js +31 -6
- package/dist/sql/SqlClient.js.map +1 -1
- package/dist/testing/TestCrypto.d.ts +73 -0
- package/dist/testing/TestCrypto.d.ts.map +1 -0
- package/dist/testing/TestCrypto.js +87 -0
- package/dist/testing/TestCrypto.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/workflow/DurableDeferred.d.ts +54 -0
- package/dist/workflow/DurableDeferred.d.ts.map +1 -1
- package/dist/workflow/DurableDeferred.js +108 -50
- package/dist/workflow/DurableDeferred.js.map +1 -1
- package/dist/workflow/WorkflowEngine.d.ts +24 -2
- package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/workflow/WorkflowEngine.js +13 -3
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +6 -3
- package/src/Context.ts +12 -3
- package/src/Crypto.ts +43 -9
- package/src/DateTime.ts +9 -6
- package/src/Duration.ts +36 -16
- package/src/FileSystem.ts +48 -2
- package/src/RequestResolver.ts +4 -10
- package/src/Scheduler.ts +9 -0
- package/src/Schema.ts +677 -5
- package/src/SchemaGetter.ts +47 -35
- package/src/Sink.ts +45 -18
- package/src/Stdio.ts +9 -2
- package/src/Stream.ts +44 -15
- package/src/Utils.ts +8 -5
- package/src/ai/AnthropicStructuredOutput.ts +2 -2
- package/src/ai/Chat.ts +2 -2
- package/src/ai/LanguageModel.ts +96 -24
- package/src/ai/McpServer.ts +288 -94
- package/src/ai/Prompt.ts +24 -10
- package/src/ai/Response.ts +6 -3
- package/src/ai/internal/mcpProtocol/v2026_07_28.ts +5 -0
- package/src/ai/internal/mcpProtocol.ts +3 -0
- package/src/ai/internal/mcpRuntime.ts +2 -0
- package/src/cli/CliOutput.ts +33 -16
- package/src/cli/Command.ts +4 -3
- package/src/cli/Completions.ts +9 -6
- package/src/cli/GlobalFlag.ts +19 -11
- package/src/cli/Prompt.ts +159 -149
- package/src/cli/internal/ansi.ts +26 -3
- package/src/cli/internal/completions/powershell.ts +322 -0
- package/src/cli/internal/completions/zsh.ts +4 -2
- package/src/cli/internal/wizard.ts +34 -26
- package/src/cluster/ClusterSchema.ts +32 -0
- package/src/cluster/ClusterWorkflowEngine.ts +64 -36
- package/src/cluster/MessageStorage.ts +45 -14
- package/src/cluster/Runners.ts +8 -2
- package/src/cluster/Sharding.ts +219 -58
- package/src/cluster/SqlMessageStorage.ts +118 -84
- package/src/cluster/SqlRunnerStorage.ts +224 -128
- package/src/cluster/internal/entityManager.ts +151 -55
- package/src/encoding/Sse.ts +69 -79
- package/src/graphql/GraphQL.ts +494 -0
- package/src/graphql/GraphQLClient.ts +912 -0
- package/src/graphql/GraphQLClientError.ts +542 -0
- package/src/graphql/GraphQLGroup.ts +167 -0
- package/src/graphql/GraphQLMiddleware.ts +253 -0
- package/src/graphql/GraphQLProtocol.ts +1286 -0
- package/src/graphql/GraphQLResolver.ts +1010 -0
- package/src/graphql/index.ts +48 -0
- package/src/http/FindMyWay/internal/router.ts +4 -7
- package/src/http/HttpClient.ts +110 -12
- package/src/http/HttpEffect.ts +11 -5
- package/src/http/HttpMiddleware.ts +33 -34
- package/src/http/HttpRouter.ts +35 -0
- package/src/http/HttpServerResponse.ts +28 -16
- package/src/http/HttpTraceContext.ts +8 -2
- package/src/http/Multipart.ts +17 -1
- package/src/http-api/HttpApiScalar.ts +5 -0
- package/src/internal/dateTime.ts +13 -10
- package/src/internal/effect.ts +22 -15
- package/src/internal/graphql.ts +263 -0
- package/src/internal/graphqlHeaders.ts +11 -0
- package/src/internal/request.ts +31 -3
- package/src/internal/schema/toCodeDocument.ts +7 -1
- package/src/internal/schema/toJsonSchemaDocument.ts +34 -2
- package/src/internal/version.ts +1 -1
- package/src/net/AddressResolver.ts +222 -0
- package/src/net/Dns.ts +1035 -0
- package/src/net/Host.ts +544 -0
- package/src/net/IpInterface.ts +117 -7
- package/src/net/IpNetwork.ts +116 -17
- package/src/net/NetAddress.ts +620 -76
- package/src/net/index.ts +18 -0
- package/src/observability/OtlpMetrics.ts +12 -23
- package/src/observability/PrometheusMetrics.ts +1 -0
- package/src/persistence/PersistedQueue.ts +146 -53
- package/src/rpc/RpcClient.ts +41 -19
- package/src/rpc/RpcServer.ts +115 -40
- package/src/socket/DatagramSocket.ts +919 -0
- package/src/socket/Socket.ts +28 -2
- package/src/socket/index.ts +6 -0
- package/src/sql/Migrator.ts +21 -5
- package/src/sql/SqlClient.ts +39 -15
- package/src/testing/TestCrypto.ts +94 -0
- package/src/testing/index.ts +6 -0
- package/src/workflow/DurableDeferred.ts +160 -47
- 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
|