effect 4.0.4 → 4.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai-docs/src/52_graphql/10_basics.ts +19 -13
- package/ai-docs/src/52_graphql/30_batching.ts +6 -4
- package/ai-docs/src/52_graphql/40_aliased-batching.ts +6 -4
- package/dist/Array.d.ts +90 -6
- package/dist/Array.d.ts.map +1 -1
- package/dist/Array.js +4 -2
- package/dist/Array.js.map +1 -1
- package/dist/Channel.d.ts +6 -1
- package/dist/Channel.d.ts.map +1 -1
- package/dist/Channel.js +17 -3
- package/dist/Channel.js.map +1 -1
- package/dist/ConfigProvider.d.ts.map +1 -1
- package/dist/ConfigProvider.js +33 -32
- package/dist/ConfigProvider.js.map +1 -1
- package/dist/Duration.d.ts.map +1 -1
- package/dist/Duration.js +2 -5
- package/dist/Duration.js.map +1 -1
- package/dist/Effect.d.ts +61 -19
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +58 -39
- package/dist/Effect.js.map +1 -1
- package/dist/FileSystem.d.ts +23 -9
- package/dist/FileSystem.d.ts.map +1 -1
- package/dist/FileSystem.js.map +1 -1
- package/dist/Match.d.ts +20 -6
- package/dist/Match.d.ts.map +1 -1
- package/dist/Match.js +2 -2
- package/dist/Match.js.map +1 -1
- package/dist/Path.d.ts +37 -5
- package/dist/Path.d.ts.map +1 -1
- package/dist/Path.js +36 -5
- package/dist/Path.js.map +1 -1
- package/dist/Schema.d.ts +7 -2
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +9 -2
- package/dist/Schema.js.map +1 -1
- package/dist/String.d.ts +12 -0
- package/dist/String.d.ts.map +1 -1
- package/dist/String.js +17 -4
- package/dist/String.js.map +1 -1
- package/dist/TxRef.d.ts.map +1 -1
- package/dist/TxRef.js +3 -2
- package/dist/TxRef.js.map +1 -1
- package/dist/ai/AiError.d.ts +10 -10
- package/dist/ai/AiError.d.ts.map +1 -1
- package/dist/ai/AiError.js +1 -1
- package/dist/ai/AiError.js.map +1 -1
- package/dist/ai/Decision.d.ts +70 -19
- package/dist/ai/Decision.d.ts.map +1 -1
- package/dist/ai/Decision.js +37 -3
- package/dist/ai/Decision.js.map +1 -1
- package/dist/ai/DecisionModel.js +1 -1
- package/dist/ai/DecisionModel.js.map +1 -1
- package/dist/ai/LanguageModel.d.ts.map +1 -1
- package/dist/ai/LanguageModel.js +47 -35
- package/dist/ai/LanguageModel.js.map +1 -1
- package/dist/ai/McpServer.d.ts +6 -52
- package/dist/ai/McpServer.d.ts.map +1 -1
- package/dist/ai/McpServer.js +2 -28
- package/dist/ai/McpServer.js.map +1 -1
- package/dist/ai/Response.d.ts +1 -1
- package/dist/cli/Completions.d.ts +5 -0
- package/dist/cli/Completions.d.ts.map +1 -1
- package/dist/cli/Completions.js.map +1 -1
- package/dist/cli/Flag.d.ts +100 -0
- package/dist/cli/Flag.d.ts.map +1 -1
- package/dist/cli/Flag.js +33 -0
- package/dist/cli/Flag.js.map +1 -1
- package/dist/cli/Param.d.ts +87 -0
- package/dist/cli/Param.d.ts.map +1 -1
- package/dist/cli/Param.js +30 -0
- package/dist/cli/Param.js.map +1 -1
- package/dist/cli/internal/command.d.ts.map +1 -1
- package/dist/cli/internal/command.js +2 -1
- package/dist/cli/internal/command.js.map +1 -1
- package/dist/cli/internal/completions/bash.js +4 -3
- package/dist/cli/internal/completions/bash.js.map +1 -1
- package/dist/cli/internal/completions/descriptor.js +8 -1
- package/dist/cli/internal/completions/descriptor.js.map +1 -1
- package/dist/cli/internal/completions/fish.js +4 -4
- package/dist/cli/internal/completions/fish.js.map +1 -1
- package/dist/cli/internal/completions/powershell.js +3 -2
- package/dist/cli/internal/completions/powershell.js.map +1 -1
- package/dist/cli/internal/completions/zsh.js +7 -3
- package/dist/cli/internal/completions/zsh.js.map +1 -1
- package/dist/cli/internal/parser.js +11 -3
- package/dist/cli/internal/parser.js.map +1 -1
- package/dist/cli/internal/wizard.d.ts.map +1 -1
- package/dist/cli/internal/wizard.js +2 -1
- package/dist/cli/internal/wizard.js.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.d.ts +1 -0
- package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.js +67 -13
- package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/cluster/MessageStorage.d.ts.map +1 -1
- package/dist/cluster/MessageStorage.js +20 -12
- package/dist/cluster/MessageStorage.js.map +1 -1
- package/dist/cluster/Runners.d.ts.map +1 -1
- package/dist/cluster/Runners.js +54 -34
- package/dist/cluster/Runners.js.map +1 -1
- package/dist/cluster/internal/entityManager.js +1 -1
- package/dist/cluster/internal/entityManager.js.map +1 -1
- package/dist/encoding/Sse.js +1 -1
- package/dist/encoding/Sse.js.map +1 -1
- package/dist/graphql/GraphQLClient.d.ts.map +1 -1
- package/dist/graphql/GraphQLClient.js +12 -5
- package/dist/graphql/GraphQLClient.js.map +1 -1
- package/dist/graphql/GraphQLProtocol.d.ts +249 -11
- package/dist/graphql/GraphQLProtocol.d.ts.map +1 -1
- package/dist/graphql/GraphQLProtocol.js +98 -8
- package/dist/graphql/GraphQLProtocol.js.map +1 -1
- package/dist/graphql/GraphQLResolver.d.ts +1 -1
- package/dist/graphql/GraphQLResolver.d.ts.map +1 -1
- package/dist/graphql/GraphQLResolver.js +46 -16
- package/dist/graphql/GraphQLResolver.js.map +1 -1
- package/dist/http/FetchHttpClient.d.ts +6 -3
- package/dist/http/FetchHttpClient.d.ts.map +1 -1
- package/dist/http/FetchHttpClient.js +6 -3
- package/dist/http/FetchHttpClient.js.map +1 -1
- package/dist/http/FindMyWay/internal/router.js +2 -1
- package/dist/http/FindMyWay/internal/router.js.map +1 -1
- package/dist/http/Headers.d.ts +3 -3
- package/dist/http/Headers.d.ts.map +1 -1
- package/dist/http/Headers.js +6 -5
- package/dist/http/Headers.js.map +1 -1
- package/dist/http/HttpClient.d.ts +12 -0
- package/dist/http/HttpClient.d.ts.map +1 -1
- package/dist/http/HttpClient.js +14 -1
- package/dist/http/HttpClient.js.map +1 -1
- package/dist/http/HttpClientError.d.ts.map +1 -1
- package/dist/http/HttpClientError.js +8 -6
- package/dist/http/HttpClientError.js.map +1 -1
- package/dist/http/HttpClientRequest.d.ts +147 -4
- package/dist/http/HttpClientRequest.d.ts.map +1 -1
- package/dist/http/HttpClientRequest.js +47 -1
- package/dist/http/HttpClientRequest.js.map +1 -1
- package/dist/http/HttpMiddleware.d.ts +60 -0
- package/dist/http/HttpMiddleware.d.ts.map +1 -1
- package/dist/http/HttpMiddleware.js +67 -5
- package/dist/http/HttpMiddleware.js.map +1 -1
- package/dist/http/HttpRouter.d.ts.map +1 -1
- package/dist/http/HttpRouter.js +52 -13
- package/dist/http/HttpRouter.js.map +1 -1
- package/dist/http/HttpServerError.d.ts.map +1 -1
- package/dist/http/HttpServerError.js +6 -4
- package/dist/http/HttpServerError.js.map +1 -1
- package/dist/http/HttpServerRequest.js +2 -2
- package/dist/http/HttpServerRequest.js.map +1 -1
- package/dist/http/HttpStaticServer.d.ts.map +1 -1
- package/dist/http/HttpStaticServer.js +4 -10
- package/dist/http/HttpStaticServer.js.map +1 -1
- package/dist/http/HttpTraceContext.js +1 -1
- package/dist/http/HttpTraceContext.js.map +1 -1
- package/dist/http/Url.d.ts.map +1 -1
- package/dist/http/Url.js +2 -1
- package/dist/http/Url.js.map +1 -1
- package/dist/http/UrlParams.d.ts +112 -8
- package/dist/http/UrlParams.d.ts.map +1 -1
- package/dist/http/UrlParams.js +141 -14
- package/dist/http/UrlParams.js.map +1 -1
- package/dist/http/internal/compression.d.ts +1 -1
- package/dist/http/internal/compression.d.ts.map +1 -1
- package/dist/http/internal/compression.js +2 -10
- package/dist/http/internal/compression.js.map +1 -1
- package/dist/http/internal/compressionBody.d.ts +2 -0
- package/dist/http/internal/compressionBody.d.ts.map +1 -0
- package/dist/http/internal/compressionBody.js +36 -0
- package/dist/http/internal/compressionBody.js.map +1 -0
- package/dist/http/internal/decompression.d.ts +2 -0
- package/dist/http/internal/decompression.d.ts.map +1 -0
- package/dist/http/internal/decompression.js +162 -0
- package/dist/http/internal/decompression.js.map +1 -0
- package/dist/http/internal/tracing.js +14 -4
- package/dist/http/internal/tracing.js.map +1 -1
- package/dist/http/internal/urlParams.d.ts +2 -0
- package/dist/http/internal/urlParams.d.ts.map +1 -0
- package/dist/http/internal/urlParams.js +4 -0
- package/dist/http/internal/urlParams.js.map +1 -0
- package/dist/http-api/HttpApiClient.d.ts.map +1 -1
- package/dist/http-api/HttpApiClient.js +2 -1
- package/dist/http-api/HttpApiClient.js.map +1 -1
- package/dist/internal/core.js +17 -1
- package/dist/internal/core.js.map +1 -1
- package/dist/internal/effect.js +5 -3
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/graphql.js +12 -2
- package/dist/internal/graphql.js.map +1 -1
- package/dist/internal/version.js +1 -1
- package/dist/observability/Otlp.d.ts +15 -0
- package/dist/observability/Otlp.d.ts.map +1 -1
- package/dist/observability/Otlp.js +3 -0
- package/dist/observability/Otlp.js.map +1 -1
- package/dist/observability/OtlpExporter.d.ts +8 -0
- package/dist/observability/OtlpExporter.d.ts.map +1 -1
- package/dist/observability/OtlpExporter.js +10 -1
- package/dist/observability/OtlpExporter.js.map +1 -1
- package/dist/observability/OtlpLogger.d.ts +17 -0
- package/dist/observability/OtlpLogger.d.ts.map +1 -1
- package/dist/observability/OtlpLogger.js +14 -1
- package/dist/observability/OtlpLogger.js.map +1 -1
- package/dist/observability/OtlpMetrics.d.ts +17 -0
- package/dist/observability/OtlpMetrics.d.ts.map +1 -1
- package/dist/observability/OtlpMetrics.js +13 -0
- package/dist/observability/OtlpMetrics.js.map +1 -1
- package/dist/observability/OtlpTracer.d.ts +17 -0
- package/dist/observability/OtlpTracer.d.ts.map +1 -1
- package/dist/observability/OtlpTracer.js +15 -2
- package/dist/observability/OtlpTracer.js.map +1 -1
- package/dist/reactivity/AsyncResult.d.ts +6 -0
- package/dist/reactivity/AsyncResult.d.ts.map +1 -1
- package/dist/reactivity/AsyncResult.js +27 -0
- package/dist/reactivity/AsyncResult.js.map +1 -1
- package/dist/reactivity/AtomRegistry.js +3 -1
- package/dist/reactivity/AtomRegistry.js.map +1 -1
- package/dist/rpc/RpcClient.d.ts.map +1 -1
- package/dist/rpc/RpcClient.js +6 -1
- package/dist/rpc/RpcClient.js.map +1 -1
- package/dist/sql/SqlClient.d.ts +8 -7
- package/dist/sql/SqlClient.d.ts.map +1 -1
- package/dist/sql/SqlClient.js +8 -7
- package/dist/sql/SqlClient.js.map +1 -1
- package/dist/testing/TestClock.d.ts +16 -3
- package/dist/testing/TestClock.d.ts.map +1 -1
- package/dist/testing/TestClock.js +112 -22
- package/dist/testing/TestClock.js.map +1 -1
- package/dist/workflow/Activity.js +1 -0
- package/dist/workflow/Activity.js.map +1 -1
- package/dist/workflow/Workflow.d.ts +22 -0
- package/dist/workflow/Workflow.d.ts.map +1 -1
- package/dist/workflow/Workflow.js +15 -3
- package/dist/workflow/Workflow.js.map +1 -1
- package/dist/workflow/WorkflowEngine.d.ts +20 -1
- package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/workflow/WorkflowEngine.js +35 -21
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +1 -1
- package/src/Array.ts +95 -6
- package/src/Channel.ts +24 -3
- package/src/ConfigProvider.ts +40 -44
- package/src/Duration.ts +4 -5
- package/src/Effect.ts +140 -53
- package/src/FileSystem.ts +23 -9
- package/src/Match.ts +65 -12
- package/src/Path.ts +52 -7
- package/src/Schema.ts +17 -4
- package/src/String.ts +17 -4
- package/src/TxRef.ts +4 -2
- package/src/ai/AiError.ts +3 -1
- package/src/ai/Decision.ts +70 -21
- package/src/ai/DecisionModel.ts +1 -1
- package/src/ai/LanguageModel.ts +57 -51
- package/src/ai/McpServer.ts +15 -55
- package/src/cli/Completions.ts +5 -0
- package/src/cli/Flag.ts +101 -0
- package/src/cli/Param.ts +96 -0
- package/src/cli/internal/command.ts +2 -1
- package/src/cli/internal/completions/bash.ts +4 -3
- package/src/cli/internal/completions/descriptor.ts +10 -1
- package/src/cli/internal/completions/fish.ts +4 -4
- package/src/cli/internal/completions/powershell.ts +5 -2
- package/src/cli/internal/completions/zsh.ts +7 -3
- package/src/cli/internal/parser.ts +12 -3
- package/src/cli/internal/wizard.ts +2 -1
- package/src/cluster/ClusterWorkflowEngine.ts +92 -24
- package/src/cluster/MessageStorage.ts +14 -3
- package/src/cluster/Runners.ts +88 -66
- package/src/cluster/internal/entityManager.ts +1 -1
- package/src/encoding/Sse.ts +1 -1
- package/src/graphql/GraphQLClient.ts +17 -5
- package/src/graphql/GraphQLProtocol.ts +274 -20
- package/src/graphql/GraphQLResolver.ts +45 -17
- package/src/http/FetchHttpClient.ts +6 -3
- package/src/http/FindMyWay/internal/router.ts +2 -1
- package/src/http/Headers.ts +6 -9
- package/src/http/HttpClient.ts +18 -1
- package/src/http/HttpClientError.ts +10 -6
- package/src/http/HttpClientRequest.ts +173 -7
- package/src/http/HttpMiddleware.ts +85 -5
- package/src/http/HttpRouter.ts +60 -13
- package/src/http/HttpServerError.ts +8 -4
- package/src/http/HttpServerRequest.ts +2 -2
- package/src/http/HttpStaticServer.ts +4 -10
- package/src/http/HttpTraceContext.ts +1 -1
- package/src/http/Url.ts +2 -1
- package/src/http/UrlParams.ts +225 -26
- package/src/http/internal/compression.ts +3 -17
- package/src/http/internal/compressionBody.ts +56 -0
- package/src/http/internal/decompression.ts +226 -0
- package/src/http/internal/tracing.ts +21 -4
- package/src/http/internal/urlParams.ts +5 -0
- package/src/http-api/HttpApiClient.ts +2 -1
- package/src/internal/core.ts +21 -1
- package/src/internal/effect.ts +5 -4
- package/src/internal/graphql.ts +30 -7
- package/src/internal/version.ts +1 -1
- package/src/observability/Otlp.ts +18 -0
- package/src/observability/OtlpExporter.ts +14 -3
- package/src/observability/OtlpLogger.ts +31 -2
- package/src/observability/OtlpMetrics.ts +30 -1
- package/src/observability/OtlpTracer.ts +32 -3
- package/src/reactivity/AsyncResult.ts +31 -0
- package/src/reactivity/AtomRegistry.ts +3 -1
- package/src/rpc/RpcClient.ts +6 -1
- package/src/sql/SqlClient.ts +9 -7
- package/src/testing/TestClock.ts +144 -29
- package/src/workflow/Activity.ts +1 -0
- package/src/workflow/Workflow.ts +31 -5
- package/src/workflow/WorkflowEngine.ts +60 -22
|
@@ -23,6 +23,7 @@ import { hasProperty } from "../Predicate.ts"
|
|
|
23
23
|
import type * as Request from "./HttpServerRequest.ts"
|
|
24
24
|
import * as Respondable from "./HttpServerRespondable.ts"
|
|
25
25
|
import * as Response from "./HttpServerResponse.ts"
|
|
26
|
+
import * as UrlParams from "./UrlParams.ts"
|
|
26
27
|
|
|
27
28
|
const TypeId = "~effect/http/HttpServerError"
|
|
28
29
|
|
|
@@ -107,7 +108,7 @@ export class RequestParseError extends Data.TaggedError("RequestParseError")<{
|
|
|
107
108
|
}
|
|
108
109
|
|
|
109
110
|
get methodAndUrl() {
|
|
110
|
-
return
|
|
111
|
+
return formatMethodAndUrl(this.request)
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
override get message() {
|
|
@@ -139,7 +140,7 @@ export class RouteNotFound extends Data.TaggedError("RouteNotFound")<{
|
|
|
139
140
|
override readonly [ErrorReporter.ignore] = true
|
|
140
141
|
|
|
141
142
|
get methodAndUrl() {
|
|
142
|
-
return
|
|
143
|
+
return formatMethodAndUrl(this.request)
|
|
143
144
|
}
|
|
144
145
|
|
|
145
146
|
override get message() {
|
|
@@ -174,7 +175,7 @@ export class InternalError extends Data.TaggedError("InternalError")<{
|
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
get methodAndUrl() {
|
|
177
|
-
return
|
|
178
|
+
return formatMethodAndUrl(this.request)
|
|
178
179
|
}
|
|
179
180
|
|
|
180
181
|
override get message() {
|
|
@@ -214,7 +215,7 @@ export class ResponseError extends Data.TaggedError("ResponseError")<{
|
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
get methodAndUrl() {
|
|
217
|
-
return
|
|
218
|
+
return formatMethodAndUrl(this.request)
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
override get message() {
|
|
@@ -275,6 +276,9 @@ export class ClientAbort extends Context.Service<ClientAbort, true>()("effect/ht
|
|
|
275
276
|
)
|
|
276
277
|
}
|
|
277
278
|
|
|
279
|
+
const formatMethodAndUrl = (request: Request.HttpServerRequest) =>
|
|
280
|
+
`${request.method} ${UrlParams.redactUrl(request.url)}`
|
|
281
|
+
|
|
278
282
|
const formatRequestMessage = (reason: string, description: string | undefined, info: string) => {
|
|
279
283
|
const prefix = `${reason} (${info})`
|
|
280
284
|
return description ? `${prefix}: ${description}` : prefix
|
|
@@ -512,7 +512,7 @@ class ServerRequestImpl extends Inspectable.Class implements HttpServerRequest {
|
|
|
512
512
|
return HttpIncomingMessage.inspect(this, {
|
|
513
513
|
_id: "HttpServerRequest",
|
|
514
514
|
method: this.method,
|
|
515
|
-
url: this.originalUrl
|
|
515
|
+
url: UrlParams.redactUrl(this.originalUrl)
|
|
516
516
|
})
|
|
517
517
|
}
|
|
518
518
|
modify(
|
|
@@ -711,7 +711,7 @@ class ClientRequestImpl extends Inspectable.Class implements HttpServerRequest {
|
|
|
711
711
|
return HttpIncomingMessage.inspect(this, {
|
|
712
712
|
_id: "HttpServerRequest",
|
|
713
713
|
method: this.method,
|
|
714
|
-
url: this.originalUrl
|
|
714
|
+
url: UrlParams.redactUrl(this.originalUrl)
|
|
715
715
|
})
|
|
716
716
|
}
|
|
717
717
|
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import * as Effect from "../Effect.ts"
|
|
14
14
|
import * as FileSystem from "../FileSystem.ts"
|
|
15
15
|
import * as Layer from "../Layer.ts"
|
|
16
|
+
import * as Option from "../Option.ts"
|
|
16
17
|
import * as Path from "../Path.ts"
|
|
17
18
|
import type { PlatformError } from "../PlatformError.ts"
|
|
18
19
|
import * as HttpPlatform from "./HttpPlatform.ts"
|
|
@@ -398,16 +399,9 @@ const resolveFilePath = (path: Path.Path, root: string, url: string): string | u
|
|
|
398
399
|
if (decodedPath.includes("\u0000")) {
|
|
399
400
|
return undefined
|
|
400
401
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
}
|
|
405
|
-
const resolvedPath = path.join(root, normalizedPath)
|
|
406
|
-
const rootPrefix = root.endsWith(path.sep) ? root : `${root}${path.sep}`
|
|
407
|
-
if (resolvedPath !== root && !resolvedPath.startsWith(rootPrefix)) {
|
|
408
|
-
return undefined
|
|
409
|
-
}
|
|
410
|
-
return resolvedPath
|
|
402
|
+
// every leading separator is part of the URL, not a filesystem root
|
|
403
|
+
const relativePath = decodedPath.replace(path.sep === "\\" ? /^[/\\]+/ : /^\/+/, "")
|
|
404
|
+
return Option.getOrUndefined(path.resolveWithin(root, relativePath))
|
|
411
405
|
}
|
|
412
406
|
|
|
413
407
|
const toRouteNotFoundError = (request: HttpServerRequest.HttpServerRequest) =>
|
|
@@ -49,7 +49,7 @@ export const toHeaders = (span: Tracer.Span): Headers.Headers =>
|
|
|
49
49
|
onSome: (parent) => `-${parent.spanId}`
|
|
50
50
|
})
|
|
51
51
|
}`,
|
|
52
|
-
traceparent: `00-${span.traceId}-${span.spanId}-${span.sampled ? "01" : "00"}`
|
|
52
|
+
traceparent: `00-${span.traceId.padStart(32, "0")}-${span.spanId}-${span.sampled ? "01" : "00"}`
|
|
53
53
|
})
|
|
54
54
|
|
|
55
55
|
/**
|
package/src/http/Url.ts
CHANGED
|
@@ -14,6 +14,7 @@ import * as Data from "../Data.ts"
|
|
|
14
14
|
import { dual } from "../Function.ts"
|
|
15
15
|
import * as Redacted from "../Redacted.ts"
|
|
16
16
|
import * as Result from "../Result.ts"
|
|
17
|
+
import * as internal from "./internal/urlParams.ts"
|
|
17
18
|
import * as UrlParams from "./UrlParams.ts"
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -49,7 +50,7 @@ export const make = (
|
|
|
49
50
|
for (let i = 0; i < params.params.length; i++) {
|
|
50
51
|
const [key, value] = params.params[i]
|
|
51
52
|
if (value !== undefined) {
|
|
52
|
-
urlInstance.searchParams.append(key, value)
|
|
53
|
+
urlInstance.searchParams.append(key, internal.unwrap(value))
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
if (hash !== undefined) {
|
package/src/http/UrlParams.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* @since 4.0.0
|
|
11
11
|
*/
|
|
12
12
|
import * as Arr from "../Array.ts"
|
|
13
|
+
import * as Context from "../Context.ts"
|
|
13
14
|
import * as Equal from "../Equal.ts"
|
|
14
15
|
import * as Equ from "../Equivalence.ts"
|
|
15
16
|
import { dual } from "../Function.ts"
|
|
@@ -21,7 +22,11 @@ import * as Option from "../Option.ts"
|
|
|
21
22
|
import type { Pipeable } from "../Pipeable.ts"
|
|
22
23
|
import { hasProperty } from "../Predicate.ts"
|
|
23
24
|
import type { ReadonlyRecord } from "../Record.ts"
|
|
25
|
+
import * as Redactable from "../Redactable.ts"
|
|
26
|
+
import * as Redacted from "../Redacted.ts"
|
|
24
27
|
import * as Tuple from "../Tuple.ts"
|
|
28
|
+
import * as Headers from "./Headers.ts"
|
|
29
|
+
import * as internal from "./internal/urlParams.ts"
|
|
25
30
|
|
|
26
31
|
const TypeId = "~effect/http/UrlParams"
|
|
27
32
|
|
|
@@ -30,16 +35,19 @@ const TypeId = "~effect/http/UrlParams"
|
|
|
30
35
|
*
|
|
31
36
|
* **Details**
|
|
32
37
|
*
|
|
33
|
-
* Parameters are
|
|
34
|
-
*
|
|
38
|
+
* Parameters are ordered key-value pairs, and a key can repeat. Each value is a
|
|
39
|
+
* string or a `Redacted` string, which is sent unwrapped. Inspection redacts
|
|
40
|
+
* `Redacted` values and values whose names match `CurrentRedactedNames`.
|
|
35
41
|
*
|
|
36
42
|
* @stability unstable
|
|
37
43
|
* @category models
|
|
38
44
|
* @since 4.0.0
|
|
39
45
|
*/
|
|
40
|
-
export interface UrlParams
|
|
46
|
+
export interface UrlParams
|
|
47
|
+
extends Pipeable, Inspectable, Redactable.Redactable, Iterable<readonly [string, string | Redacted.Redacted]>
|
|
48
|
+
{
|
|
41
49
|
readonly [TypeId]: typeof TypeId
|
|
42
|
-
readonly params: ReadonlyArray<readonly [string, string]>
|
|
50
|
+
readonly params: ReadonlyArray<readonly [string, string | Redacted.Redacted]>
|
|
43
51
|
}
|
|
44
52
|
|
|
45
53
|
/**
|
|
@@ -74,7 +82,11 @@ type CoercibleRecordInput = CoercibleRecord & {
|
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
/**
|
|
77
|
-
*
|
|
85
|
+
* Value that can be converted into a URL parameter string.
|
|
86
|
+
*
|
|
87
|
+
* **Details**
|
|
88
|
+
*
|
|
89
|
+
* `Redacted` values are stored wrapped and sent unwrapped.
|
|
78
90
|
*
|
|
79
91
|
* **Gotchas**
|
|
80
92
|
*
|
|
@@ -84,7 +96,7 @@ type CoercibleRecordInput = CoercibleRecord & {
|
|
|
84
96
|
* @category models
|
|
85
97
|
* @since 4.0.0
|
|
86
98
|
*/
|
|
87
|
-
export type Coercible = string | number | bigint | boolean | null | undefined
|
|
99
|
+
export type Coercible = string | number | bigint | boolean | null | undefined | Redacted.Redacted
|
|
88
100
|
|
|
89
101
|
/**
|
|
90
102
|
* @stability unstable
|
|
@@ -118,12 +130,15 @@ const Proto = {
|
|
|
118
130
|
[Symbol.iterator](this: UrlParams) {
|
|
119
131
|
return this.params[Symbol.iterator]()
|
|
120
132
|
},
|
|
121
|
-
|
|
133
|
+
[Redactable.symbolRedactable](this: UrlParams, context: Context.Context<never>): unknown {
|
|
122
134
|
return {
|
|
123
135
|
_id: "UrlParams",
|
|
124
|
-
params: Object.fromEntries(this.
|
|
136
|
+
params: Object.fromEntries(redact(this, Context.get(context, CurrentRedactedNames)))
|
|
125
137
|
}
|
|
126
138
|
},
|
|
139
|
+
toJSON(this: UrlParams): unknown {
|
|
140
|
+
return Redactable.redact(this)
|
|
141
|
+
},
|
|
127
142
|
[Equal.symbol](this: UrlParams, that: UrlParams): boolean {
|
|
128
143
|
return Equivalence(this, that)
|
|
129
144
|
},
|
|
@@ -133,7 +148,7 @@ const Proto = {
|
|
|
133
148
|
}
|
|
134
149
|
|
|
135
150
|
/**
|
|
136
|
-
* Creates `UrlParams` from ordered
|
|
151
|
+
* Creates `UrlParams` from ordered key-value pairs.
|
|
137
152
|
*
|
|
138
153
|
* **Details**
|
|
139
154
|
*
|
|
@@ -143,7 +158,7 @@ const Proto = {
|
|
|
143
158
|
* @category constructors
|
|
144
159
|
* @since 4.0.0
|
|
145
160
|
*/
|
|
146
|
-
export const make = (params: ReadonlyArray<readonly [string, string]>): UrlParams => {
|
|
161
|
+
export const make = (params: ReadonlyArray<readonly [string, string | Redacted.Redacted]>): UrlParams => {
|
|
147
162
|
const self = Object.create(Proto)
|
|
148
163
|
self.params = params
|
|
149
164
|
return self
|
|
@@ -156,6 +171,7 @@ export const make = (params: ReadonlyArray<readonly [string, string]>): UrlParam
|
|
|
156
171
|
*
|
|
157
172
|
* Primitive values are converted to strings, arrays produce repeated parameters,
|
|
158
173
|
* nested records use bracket notation, and `undefined` values are omitted.
|
|
174
|
+
* `Redacted` values are kept as-is.
|
|
159
175
|
*
|
|
160
176
|
* @stability unstable
|
|
161
177
|
* @category constructors
|
|
@@ -166,42 +182,44 @@ export const fromInput = (input: Input): UrlParams => {
|
|
|
166
182
|
return input
|
|
167
183
|
}
|
|
168
184
|
const parsed = fromInputNested(input)
|
|
169
|
-
const out: Array<[string, string]> = []
|
|
185
|
+
const out: Array<[string, string | Redacted.Redacted]> = []
|
|
170
186
|
for (let i = 0; i < parsed.length; i++) {
|
|
171
187
|
if (Array.isArray(parsed[i][0])) {
|
|
172
|
-
const [keys, value] = parsed[i] as [Array<string>, string]
|
|
188
|
+
const [keys, value] = parsed[i] as [Array<string>, string | Redacted.Redacted]
|
|
173
189
|
out.push([`${keys[0]}[${keys.slice(1).join("][")}]`, value])
|
|
174
190
|
} else {
|
|
175
|
-
out.push(parsed[i] as [string, string])
|
|
191
|
+
out.push(parsed[i] as [string, string | Redacted.Redacted])
|
|
176
192
|
}
|
|
177
193
|
}
|
|
178
194
|
return make(out)
|
|
179
195
|
}
|
|
180
196
|
|
|
181
|
-
const fromInputNested = (input: Input): Array<[string | Array<string>,
|
|
197
|
+
const fromInputNested = (input: Input): Array<[string | Array<string>, string | Redacted.Redacted]> => {
|
|
182
198
|
const entries = typeof (input as any)[Symbol.iterator] === "function"
|
|
183
199
|
? Arr.fromIterable(input as Iterable<readonly [string, Coercible]>)
|
|
184
200
|
: Object.entries(input)
|
|
185
|
-
const out: Array<[string | Array<string>, string]> = []
|
|
201
|
+
const out: Array<[string | Array<string>, string | Redacted.Redacted]> = []
|
|
186
202
|
for (const [key, value] of entries) {
|
|
187
203
|
if (Array.isArray(value)) {
|
|
188
204
|
for (let i = 0; i < value.length; i++) {
|
|
189
205
|
if (value[i] !== undefined) {
|
|
190
|
-
out.push([key,
|
|
206
|
+
out.push([key, coerce(value[i])])
|
|
191
207
|
}
|
|
192
208
|
}
|
|
193
|
-
} else if (value !== null && typeof value === "object") {
|
|
209
|
+
} else if (value !== null && typeof value === "object" && !Redacted.isRedacted(value)) {
|
|
194
210
|
const nested = fromInputNested(value as CoercibleRecord)
|
|
195
211
|
for (const [k, v] of nested) {
|
|
196
212
|
out.push([[key, ...(typeof k === "string" ? [k] : k)], v])
|
|
197
213
|
}
|
|
198
214
|
} else if (value !== undefined) {
|
|
199
|
-
out.push([key,
|
|
215
|
+
out.push([key, coerce(value)])
|
|
200
216
|
}
|
|
201
217
|
}
|
|
202
218
|
return out
|
|
203
219
|
}
|
|
204
220
|
|
|
221
|
+
const coerce = (value: Coercible): string | Redacted.Redacted => Redacted.isRedacted(value) ? value : String(value)
|
|
222
|
+
|
|
205
223
|
/**
|
|
206
224
|
* Provides an order-sensitive `Equivalence` instance for `UrlParams`.
|
|
207
225
|
*
|
|
@@ -219,7 +237,7 @@ export const Equivalence: Equ.Equivalence<UrlParams> = Equ.make<UrlParams>((a, b
|
|
|
219
237
|
)
|
|
220
238
|
|
|
221
239
|
const arrayEquivalence = Arr.makeEquivalence(
|
|
222
|
-
Tuple.makeEquivalence([Equ.strictEqual<string>(),
|
|
240
|
+
Tuple.makeEquivalence([Equ.strictEqual<string>(), Equal.asEquivalence<string | Redacted.Redacted>()])
|
|
223
241
|
)
|
|
224
242
|
|
|
225
243
|
/**
|
|
@@ -272,7 +290,7 @@ export const getAll: {
|
|
|
272
290
|
(self: UrlParams, key: string): ReadonlyArray<string> =>
|
|
273
291
|
Arr.reduce(self.params, [] as Array<string>, (acc, [k, value]) => {
|
|
274
292
|
if (k === key) {
|
|
275
|
-
acc.push(value)
|
|
293
|
+
acc.push(internal.unwrap(value))
|
|
276
294
|
}
|
|
277
295
|
return acc
|
|
278
296
|
})
|
|
@@ -333,7 +351,7 @@ export const getFirst: {
|
|
|
333
351
|
2,
|
|
334
352
|
(self: UrlParams, key: string): Option.Option<string> =>
|
|
335
353
|
Arr.findFirst(self.params, ([k]) => k === key).pipe(
|
|
336
|
-
Option.map(([, value]) => value)
|
|
354
|
+
Option.map(([, value]) => internal.unwrap(value))
|
|
337
355
|
)
|
|
338
356
|
)
|
|
339
357
|
|
|
@@ -390,7 +408,7 @@ export const getLast: {
|
|
|
390
408
|
(self: UrlParams, key: string): Option.Option<string>
|
|
391
409
|
} = dual(2, (self: UrlParams, key: string): Option.Option<string> =>
|
|
392
410
|
Arr.findLast(self.params, ([k]) => k === key).pipe(
|
|
393
|
-
Option.map(([, value]) => value)
|
|
411
|
+
Option.map(([, value]) => internal.unwrap(value))
|
|
394
412
|
))
|
|
395
413
|
|
|
396
414
|
/**
|
|
@@ -436,7 +454,7 @@ export const set: {
|
|
|
436
454
|
make(
|
|
437
455
|
Arr.append(
|
|
438
456
|
Arr.filter(self.params, ([k]) => k !== key),
|
|
439
|
-
[key,
|
|
457
|
+
[key, coerce(value)]
|
|
440
458
|
)
|
|
441
459
|
))
|
|
442
460
|
|
|
@@ -560,7 +578,7 @@ export const append: {
|
|
|
560
578
|
} = dual(3, (self: UrlParams, key: string, value: Coercible): UrlParams =>
|
|
561
579
|
make(Arr.append(
|
|
562
580
|
self.params,
|
|
563
|
-
[key,
|
|
581
|
+
[key, coerce(value)]
|
|
564
582
|
)))
|
|
565
583
|
|
|
566
584
|
/**
|
|
@@ -630,11 +648,16 @@ export const remove: {
|
|
|
630
648
|
/**
|
|
631
649
|
* Serializes `UrlParams` to a URL query string without a leading question mark.
|
|
632
650
|
*
|
|
651
|
+
* **Gotchas**
|
|
652
|
+
*
|
|
653
|
+
* The output contains the unwrapped values of `Redacted` parameters.
|
|
654
|
+
*
|
|
633
655
|
* @stability unstable
|
|
634
656
|
* @category converting
|
|
635
657
|
* @since 4.0.0
|
|
636
658
|
*/
|
|
637
|
-
export const toString = (input: Input): string =>
|
|
659
|
+
export const toString = (input: Input): string =>
|
|
660
|
+
new URLSearchParams(fromInput(input).params.map(([key, value]) => [key, internal.unwrap(value)])).toString()
|
|
638
661
|
|
|
639
662
|
/**
|
|
640
663
|
* Builds a `Record` containing all the key-value pairs in the given `UrlParams`
|
|
@@ -661,7 +684,8 @@ export const toString = (input: Input): string => new URLSearchParams(fromInput(
|
|
|
661
684
|
*/
|
|
662
685
|
export const toRecord = (self: UrlParams): Record<string, string | Arr.NonEmptyArray<string>> => {
|
|
663
686
|
const out: Record<string, string | Arr.NonEmptyArray<string>> = {}
|
|
664
|
-
for (const [k,
|
|
687
|
+
for (const [k, v] of self.params) {
|
|
688
|
+
const value = internal.unwrap(v)
|
|
665
689
|
if (!Object.hasOwn(out, k)) {
|
|
666
690
|
InternalRecord.assignProperty(out, k, value)
|
|
667
691
|
} else {
|
|
@@ -690,3 +714,178 @@ export const toRecord = (self: UrlParams): Record<string, string | Arr.NonEmptyA
|
|
|
690
714
|
*/
|
|
691
715
|
export const toReadonlyRecord: (self: UrlParams) => ReadonlyRecord<string, string | Arr.NonEmptyReadonlyArray<string>> =
|
|
692
716
|
toRecord as any
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* Returns the parameter pairs with selected values wrapped in `Redacted`.
|
|
720
|
+
*
|
|
721
|
+
* **Details**
|
|
722
|
+
*
|
|
723
|
+
* Keeps `Redacted` values and wraps values whose names match `isRedactedName`,
|
|
724
|
+
* preserving order and repeated names.
|
|
725
|
+
*
|
|
726
|
+
* @stability unstable
|
|
727
|
+
* @category combinators
|
|
728
|
+
* @since 4.0.0
|
|
729
|
+
*/
|
|
730
|
+
export const redact: {
|
|
731
|
+
/**
|
|
732
|
+
* Returns the parameter pairs with selected values wrapped in `Redacted`.
|
|
733
|
+
*
|
|
734
|
+
* **Details**
|
|
735
|
+
*
|
|
736
|
+
* Keeps `Redacted` values and wraps values whose names match `isRedactedName`,
|
|
737
|
+
* preserving order and repeated names.
|
|
738
|
+
*
|
|
739
|
+
* @stability unstable
|
|
740
|
+
* @category combinators
|
|
741
|
+
* @since 4.0.0
|
|
742
|
+
*/
|
|
743
|
+
(key: string | RegExp | ReadonlyArray<string | RegExp>): (self: UrlParams) => Array<[string, string | Redacted.Redacted<string>]>
|
|
744
|
+
/**
|
|
745
|
+
* Returns the parameter pairs with selected values wrapped in `Redacted`.
|
|
746
|
+
*
|
|
747
|
+
* **Details**
|
|
748
|
+
*
|
|
749
|
+
* Keeps `Redacted` values and wraps values whose names match `isRedactedName`,
|
|
750
|
+
* preserving order and repeated names.
|
|
751
|
+
*
|
|
752
|
+
* @stability unstable
|
|
753
|
+
* @category combinators
|
|
754
|
+
* @since 4.0.0
|
|
755
|
+
*/
|
|
756
|
+
(self: UrlParams, key: string | RegExp | ReadonlyArray<string | RegExp>): Array<[string, string | Redacted.Redacted<string>]>
|
|
757
|
+
} = dual(
|
|
758
|
+
2,
|
|
759
|
+
(
|
|
760
|
+
self: UrlParams,
|
|
761
|
+
key: string | RegExp | ReadonlyArray<string | RegExp>
|
|
762
|
+
): Array<[string, string | Redacted.Redacted<string>]> => {
|
|
763
|
+
const patterns: ReadonlyArray<string | RegExp> = Array.isArray(key) ? key : [key as string | RegExp]
|
|
764
|
+
return self.params.map(([name, value]) => [
|
|
765
|
+
name,
|
|
766
|
+
typeof value === "string" && isRedactedName(name, patterns) ? Redacted.make(value) : value
|
|
767
|
+
])
|
|
768
|
+
}
|
|
769
|
+
)
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* Checks whether a parameter name matches one of the redaction patterns.
|
|
773
|
+
*
|
|
774
|
+
* **Details**
|
|
775
|
+
*
|
|
776
|
+
* String patterns match case-insensitively; regular expressions test the name.
|
|
777
|
+
*
|
|
778
|
+
* @stability unstable
|
|
779
|
+
* @category combinators
|
|
780
|
+
* @since 4.0.0
|
|
781
|
+
*/
|
|
782
|
+
export const isRedactedName: (name: string, patterns: ReadonlyArray<string | RegExp>) => boolean =
|
|
783
|
+
Headers.isRedactedName
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* Redacts URL userinfo and the values of matching query parameters.
|
|
787
|
+
*
|
|
788
|
+
* **Details**
|
|
789
|
+
*
|
|
790
|
+
* Replaces userinfo with `REDACTED:REDACTED` and query values with `REDACTED`
|
|
791
|
+
* when their decoded names match `isRedactedName`. Preserves all other text.
|
|
792
|
+
* When names are omitted, uses the current fiber's `CurrentRedactedNames`,
|
|
793
|
+
* falling back to the defaults outside a fiber.
|
|
794
|
+
*
|
|
795
|
+
* **Example** (Redacting a signed URL)
|
|
796
|
+
*
|
|
797
|
+
* ```ts import.meta.vitest
|
|
798
|
+
* import { UrlParams } from "effect/http"
|
|
799
|
+
*
|
|
800
|
+
* const url = UrlParams.redactUrl("https://bucket.test/file?Signature=abc&size=1")
|
|
801
|
+
* url // => "https://bucket.test/file?Signature=REDACTED&size=1"
|
|
802
|
+
* ```
|
|
803
|
+
*
|
|
804
|
+
* @stability unstable
|
|
805
|
+
* @category combinators
|
|
806
|
+
* @since 4.0.0
|
|
807
|
+
*/
|
|
808
|
+
export const redactUrl = (
|
|
809
|
+
url: string,
|
|
810
|
+
redactedNames: ReadonlyArray<string | RegExp> = currentRedactedNames()
|
|
811
|
+
): string => {
|
|
812
|
+
if (url.includes("@")) url = redactUserinfo(url)
|
|
813
|
+
const queryStart = url.indexOf("?")
|
|
814
|
+
if (queryStart === -1 || redactedNames.length === 0) return url
|
|
815
|
+
const hashStart = url.indexOf("#")
|
|
816
|
+
if (hashStart !== -1 && hashStart < queryStart) return url
|
|
817
|
+
const queryEnd = hashStart === -1 ? url.length : hashStart
|
|
818
|
+
return url.slice(0, queryStart + 1) + redactQuery(url.slice(queryStart + 1, queryEnd), redactedNames) +
|
|
819
|
+
url.slice(queryEnd)
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
const authorityStart = /^(?:(https?|ftp|wss?):[/\\]*|[a-z][a-z\d+.-]*:\/\/|[/\\]{2,})/i
|
|
823
|
+
const specialAuthorityEnd = /[/\\?#]/
|
|
824
|
+
const authorityEnd = /[/?#]/
|
|
825
|
+
|
|
826
|
+
// Normalize only to locate userinfo; offsets preserve the original URL spelling.
|
|
827
|
+
const redactUserinfo = (url: string): string => {
|
|
828
|
+
let normalized = ""
|
|
829
|
+
const offsets: Array<number> = []
|
|
830
|
+
for (let i = 0; i < url.length; i++) {
|
|
831
|
+
const code = url.charCodeAt(i)
|
|
832
|
+
if (code === 9 || code === 10 || code === 13 || (normalized === "" && code <= 32)) continue
|
|
833
|
+
normalized += url[i]
|
|
834
|
+
offsets.push(i)
|
|
835
|
+
}
|
|
836
|
+
const authority = authorityStart.exec(normalized)
|
|
837
|
+
if (authority === null) return url
|
|
838
|
+
const start = authority[0].length
|
|
839
|
+
const special = authority[1] !== undefined || !authority[0].includes(":")
|
|
840
|
+
const rest = normalized.slice(start)
|
|
841
|
+
const end = rest.search(special ? specialAuthorityEnd : authorityEnd)
|
|
842
|
+
const userinfoEnd = (end === -1 ? rest : rest.slice(0, end)).lastIndexOf("@")
|
|
843
|
+
return userinfoEnd === -1
|
|
844
|
+
? url
|
|
845
|
+
: url.slice(0, offsets[start]) + "REDACTED:REDACTED" + url.slice(offsets[start + userinfoEnd])
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
const redactQuery = (query: string, redactedNames: ReadonlyArray<string | RegExp>): string =>
|
|
849
|
+
query.split("&").map((part) => {
|
|
850
|
+
const index = part.indexOf("=")
|
|
851
|
+
return index !== -1 && isRedactedName(decodeQueryKey(part.slice(0, index)), redactedNames)
|
|
852
|
+
? part.slice(0, index + 1) + "REDACTED"
|
|
853
|
+
: part
|
|
854
|
+
}).join("&")
|
|
855
|
+
|
|
856
|
+
const decodeQueryKey = (key: string): string => {
|
|
857
|
+
if (!key.includes("%") && !key.includes("+")) return key
|
|
858
|
+
try {
|
|
859
|
+
return decodeURIComponent(key.replace(/\+/g, " "));
|
|
860
|
+
} catch {
|
|
861
|
+
return key
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
const currentRedactedNames = (): ReadonlyArray<string | RegExp> =>
|
|
866
|
+
Context.get((globalThis as any)[Redactable.currentFiberTypeId]?.context ?? Context.empty(), CurrentRedactedNames)
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* Query parameter names or patterns to redact in inspection, spans and errors.
|
|
870
|
+
*
|
|
871
|
+
* **Details**
|
|
872
|
+
*
|
|
873
|
+
* Defaults include `AWSAccessKeyId`, `Signature`, `sig` and `X-Goog-Signature`.
|
|
874
|
+
* A custom list replaces the defaults. Matching uses `isRedactedName`.
|
|
875
|
+
* Redaction leaves request URLs and parameter values unchanged. `Redacted`
|
|
876
|
+
* values are redacted regardless of this list.
|
|
877
|
+
*
|
|
878
|
+
* @stability unstable
|
|
879
|
+
* @category services
|
|
880
|
+
* @since 4.0.0
|
|
881
|
+
*/
|
|
882
|
+
export const CurrentRedactedNames = Context.Reference<
|
|
883
|
+
ReadonlyArray<string | RegExp>
|
|
884
|
+
>("effect/http/UrlParams/CurrentRedactedNames", {
|
|
885
|
+
defaultValue: () => [
|
|
886
|
+
"AWSAccessKeyId",
|
|
887
|
+
"Signature",
|
|
888
|
+
"sig",
|
|
889
|
+
"X-Goog-Signature"
|
|
890
|
+
]
|
|
891
|
+
})
|
|
@@ -5,6 +5,9 @@ import type * as Headers from "../Headers.ts"
|
|
|
5
5
|
import * as HttpBody from "../HttpBody.ts"
|
|
6
6
|
import type { Compression, CompressionAlgorithm, CompressionOptions } from "../HttpPlatform.ts"
|
|
7
7
|
import * as Response from "../HttpServerResponse.ts"
|
|
8
|
+
import { compressionTransformWeb, singleChunkStream } from "./compressionBody.ts"
|
|
9
|
+
|
|
10
|
+
export { compressionTransformWeb } from "./compressionBody.ts"
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* @internal
|
|
@@ -41,15 +44,6 @@ export const wrapCompression = (impl: Compression): Compression => ({
|
|
|
41
44
|
}
|
|
42
45
|
})
|
|
43
46
|
|
|
44
|
-
/**
|
|
45
|
-
* @internal
|
|
46
|
-
*/
|
|
47
|
-
export const compressionTransformWeb =
|
|
48
|
-
(format: string) => (stream: ReadableStream<Uint8Array>): ReadableStream<Uint8Array> =>
|
|
49
|
-
stream.pipeThrough(
|
|
50
|
-
new CompressionStream(format as CompressionFormat) as unknown as ReadableWritablePair<Uint8Array, Uint8Array>
|
|
51
|
-
)
|
|
52
|
-
|
|
53
47
|
/**
|
|
54
48
|
* @internal
|
|
55
49
|
*/
|
|
@@ -117,14 +111,6 @@ const streamBody = (
|
|
|
117
111
|
HttpBody.stream(Stream.fromReadableStream({ evaluate, onError: identity }), contentType)
|
|
118
112
|
)
|
|
119
113
|
|
|
120
|
-
const singleChunkStream = (data: Uint8Array): ReadableStream<Uint8Array> =>
|
|
121
|
-
new ReadableStream({
|
|
122
|
-
start(controller) {
|
|
123
|
-
controller.enqueue(data)
|
|
124
|
-
controller.close()
|
|
125
|
-
}
|
|
126
|
-
})
|
|
127
|
-
|
|
128
114
|
const rawReadableStream = (raw: unknown): ReadableStream<Uint8Array> | undefined => {
|
|
129
115
|
if (typeof ReadableStream !== "undefined" && raw instanceof ReadableStream) {
|
|
130
116
|
return raw
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as Effect from "../../Effect.ts"
|
|
2
|
+
import { identity } from "../../Function.ts"
|
|
3
|
+
import * as Stream from "../../Stream.ts"
|
|
4
|
+
import * as HttpBody from "../HttpBody.ts"
|
|
5
|
+
import type { CompressionAlgorithm, CompressionOptions } from "../HttpClientRequest.ts"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export const compressionTransformWeb =
|
|
11
|
+
(format: string) => (stream: ReadableStream<Uint8Array>): ReadableStream<Uint8Array> =>
|
|
12
|
+
stream.pipeThrough(
|
|
13
|
+
new CompressionStream(format as CompressionFormat) as unknown as ReadableWritablePair<Uint8Array, Uint8Array>
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export const singleChunkStream = (data: Uint8Array): ReadableStream<Uint8Array> =>
|
|
20
|
+
new ReadableStream({
|
|
21
|
+
start(controller) {
|
|
22
|
+
controller.enqueue(data)
|
|
23
|
+
controller.close()
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export const compressBody = (
|
|
31
|
+
body: HttpBody.HttpBody,
|
|
32
|
+
algorithm: CompressionAlgorithm,
|
|
33
|
+
options?: CompressionOptions | undefined
|
|
34
|
+
): Effect.Effect<HttpBody.HttpBody> => {
|
|
35
|
+
if (body._tag !== "Uint8Array" && body._tag !== "Stream") {
|
|
36
|
+
return Effect.succeed(body)
|
|
37
|
+
}
|
|
38
|
+
if (body.contentLength !== undefined && body.contentLength < (options?.minSize ?? 1024)) {
|
|
39
|
+
return Effect.succeed(body)
|
|
40
|
+
}
|
|
41
|
+
if (body._tag === "Uint8Array") {
|
|
42
|
+
return Effect.map(
|
|
43
|
+
Effect.promise(() =>
|
|
44
|
+
new globalThis.Response(compressionTransformWeb(algorithm)(singleChunkStream(body.body))).arrayBuffer()
|
|
45
|
+
),
|
|
46
|
+
(buffer) => HttpBody.uint8Array(new Uint8Array(buffer), body.contentType)
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
return Effect.succeed(HttpBody.stream(
|
|
50
|
+
Stream.fromReadableStream({
|
|
51
|
+
evaluate: () => compressionTransformWeb(algorithm)(Stream.toReadableStream(body.stream)),
|
|
52
|
+
onError: identity
|
|
53
|
+
}),
|
|
54
|
+
body.contentType
|
|
55
|
+
))
|
|
56
|
+
}
|