@effect/platform 0.31.1 → 0.32.0
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/dist/cjs/Http/App.js +43 -1
- package/dist/cjs/Http/App.js.map +1 -1
- package/dist/cjs/Http/Client.js +16 -1
- package/dist/cjs/Http/Client.js.map +1 -1
- package/dist/cjs/Http/IncomingMessage.js +3 -3
- package/dist/cjs/Http/IncomingMessage.js.map +1 -1
- package/dist/cjs/Http/ServerRequest.js +6 -1
- package/dist/cjs/Http/ServerRequest.js.map +1 -1
- package/dist/cjs/Http/ServerResponse.js +6 -1
- package/dist/cjs/Http/ServerResponse.js.map +1 -1
- package/dist/cjs/internal/http/client.js +10 -3
- package/dist/cjs/internal/http/client.js.map +1 -1
- package/dist/cjs/internal/http/router.js +2 -1
- package/dist/cjs/internal/http/router.js.map +1 -1
- package/dist/cjs/internal/http/serverRequest.js +112 -1
- package/dist/cjs/internal/http/serverRequest.js.map +1 -1
- package/dist/cjs/internal/http/serverResponse.js +49 -1
- package/dist/cjs/internal/http/serverResponse.js.map +1 -1
- package/dist/cjs/internal/worker.js +1 -1
- package/dist/cjs/internal/worker.js.map +1 -1
- package/dist/dts/Http/App.d.ts +22 -2
- package/dist/dts/Http/App.d.ts.map +1 -1
- package/dist/dts/Http/Client.d.ts +28 -0
- package/dist/dts/Http/Client.d.ts.map +1 -1
- package/dist/dts/Http/ServerRequest.d.ts +5 -0
- package/dist/dts/Http/ServerRequest.d.ts.map +1 -1
- package/dist/dts/Http/ServerResponse.d.ts +5 -0
- package/dist/dts/Http/ServerResponse.d.ts.map +1 -1
- package/dist/dts/Terminal.d.ts +1 -1
- package/dist/dts/internal/http/router.d.ts.map +1 -1
- package/dist/esm/Http/App.js +40 -0
- package/dist/esm/Http/App.js.map +1 -1
- package/dist/esm/Http/Client.js +15 -0
- package/dist/esm/Http/Client.js.map +1 -1
- package/dist/esm/Http/IncomingMessage.js +3 -3
- package/dist/esm/Http/IncomingMessage.js.map +1 -1
- package/dist/esm/Http/ServerRequest.js +5 -0
- package/dist/esm/Http/ServerRequest.js.map +1 -1
- package/dist/esm/Http/ServerResponse.js +5 -0
- package/dist/esm/Http/ServerResponse.js.map +1 -1
- package/dist/esm/internal/http/client.js +9 -2
- package/dist/esm/internal/http/client.js.map +1 -1
- package/dist/esm/internal/http/router.js +2 -1
- package/dist/esm/internal/http/router.js.map +1 -1
- package/dist/esm/internal/http/serverRequest.js +110 -0
- package/dist/esm/internal/http/serverRequest.js.map +1 -1
- package/dist/esm/internal/http/serverResponse.js +47 -0
- package/dist/esm/internal/http/serverResponse.js.map +1 -1
- package/dist/esm/internal/worker.js +1 -1
- package/dist/esm/internal/worker.js.map +1 -1
- package/package.json +3 -3
- package/src/Http/App.ts +50 -2
- package/src/Http/Client.ts +39 -0
- package/src/Http/IncomingMessage.ts +3 -3
- package/src/Http/ServerRequest.ts +6 -0
- package/src/Http/ServerResponse.ts +6 -0
- package/src/internal/http/client.ts +194 -85
- package/src/internal/http/router.ts +2 -1
- package/src/internal/http/serverRequest.ts +159 -0
- package/src/internal/http/serverResponse.ts +44 -1
- package/src/internal/worker.ts +1 -8
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import type * as Schema from "@effect/schema/Schema"
|
|
2
2
|
import * as Context from "effect/Context"
|
|
3
3
|
import * as Effect from "effect/Effect"
|
|
4
|
+
import * as Option from "effect/Option"
|
|
5
|
+
import type * as Scope from "effect/Scope"
|
|
6
|
+
import * as Stream from "effect/Stream"
|
|
7
|
+
import type * as FileSystem from "../../FileSystem.js"
|
|
4
8
|
import * as FormData from "../../Http/FormData.js"
|
|
9
|
+
import * as Headers from "../../Http/Headers.js"
|
|
5
10
|
import * as IncomingMessage from "../../Http/IncomingMessage.js"
|
|
11
|
+
import type { Method } from "../../Http/Method.js"
|
|
6
12
|
import * as Error from "../../Http/ServerError.js"
|
|
7
13
|
import type * as ServerRequest from "../../Http/ServerRequest.js"
|
|
14
|
+
import * as UrlParams from "../../Http/UrlParams.js"
|
|
15
|
+
import type * as Path from "../../Path.js"
|
|
8
16
|
|
|
9
17
|
/** @internal */
|
|
10
18
|
export const TypeId: ServerRequest.TypeId = Symbol.for("@effect/platform/Http/ServerRequest") as ServerRequest.TypeId
|
|
@@ -63,3 +71,154 @@ export const schemaFormDataJson = <I, A>(schema: Schema.Schema<I, A>) => {
|
|
|
63
71
|
)
|
|
64
72
|
))
|
|
65
73
|
}
|
|
74
|
+
|
|
75
|
+
/** @internal */
|
|
76
|
+
export const fromWeb = (request: globalThis.Request): ServerRequest.ServerRequest =>
|
|
77
|
+
new ServerRequestImpl(request, request.url)
|
|
78
|
+
|
|
79
|
+
class ServerRequestImpl implements ServerRequest.ServerRequest {
|
|
80
|
+
readonly [TypeId]: ServerRequest.TypeId
|
|
81
|
+
readonly [IncomingMessage.TypeId]: IncomingMessage.TypeId
|
|
82
|
+
constructor(
|
|
83
|
+
readonly source: Request,
|
|
84
|
+
readonly url: string,
|
|
85
|
+
public headersOverride?: Headers.Headers,
|
|
86
|
+
private remoteAddressOverride?: string
|
|
87
|
+
) {
|
|
88
|
+
this[TypeId] = TypeId
|
|
89
|
+
this[IncomingMessage.TypeId] = IncomingMessage.TypeId
|
|
90
|
+
}
|
|
91
|
+
modify(
|
|
92
|
+
options: {
|
|
93
|
+
readonly url?: string | undefined
|
|
94
|
+
readonly headers?: Headers.Headers | undefined
|
|
95
|
+
readonly remoteAddress?: string | undefined
|
|
96
|
+
}
|
|
97
|
+
) {
|
|
98
|
+
return new ServerRequestImpl(
|
|
99
|
+
this.source,
|
|
100
|
+
options.url ?? this.url,
|
|
101
|
+
options.headers ?? this.headersOverride,
|
|
102
|
+
options.remoteAddress ?? this.remoteAddressOverride
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
get method(): Method {
|
|
106
|
+
return this.source.method.toUpperCase() as Method
|
|
107
|
+
}
|
|
108
|
+
get originalUrl() {
|
|
109
|
+
return this.source.url
|
|
110
|
+
}
|
|
111
|
+
get remoteAddress(): Option.Option<string> {
|
|
112
|
+
return this.remoteAddressOverride ? Option.some(this.remoteAddressOverride) : Option.none()
|
|
113
|
+
}
|
|
114
|
+
get headers(): Headers.Headers {
|
|
115
|
+
this.headersOverride ??= Headers.fromInput(this.source.headers)
|
|
116
|
+
return this.headersOverride
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
get stream(): Stream.Stream<never, Error.RequestError, Uint8Array> {
|
|
120
|
+
return this.source.body
|
|
121
|
+
? Stream.fromReadableStream(() => this.source.body as any, (_) =>
|
|
122
|
+
Error.RequestError({
|
|
123
|
+
request: this,
|
|
124
|
+
reason: "Decode",
|
|
125
|
+
error: _
|
|
126
|
+
}))
|
|
127
|
+
: Stream.fail(Error.RequestError({
|
|
128
|
+
request: this,
|
|
129
|
+
reason: "Decode",
|
|
130
|
+
error: "can not create stream from empty body"
|
|
131
|
+
}))
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private textEffect: Effect.Effect<never, Error.RequestError, string> | undefined
|
|
135
|
+
get text(): Effect.Effect<never, Error.RequestError, string> {
|
|
136
|
+
if (this.textEffect) {
|
|
137
|
+
return this.textEffect
|
|
138
|
+
}
|
|
139
|
+
this.textEffect = Effect.runSync(Effect.cached(
|
|
140
|
+
Effect.tryPromise({
|
|
141
|
+
try: () => this.source.text(),
|
|
142
|
+
catch: (error) =>
|
|
143
|
+
Error.RequestError({
|
|
144
|
+
request: this,
|
|
145
|
+
reason: "Decode",
|
|
146
|
+
error
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
))
|
|
150
|
+
return this.textEffect
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
get json(): Effect.Effect<never, Error.RequestError, unknown> {
|
|
154
|
+
return Effect.tryMap(this.text, {
|
|
155
|
+
try: (_) => JSON.parse(_) as unknown,
|
|
156
|
+
catch: (error) =>
|
|
157
|
+
Error.RequestError({
|
|
158
|
+
request: this,
|
|
159
|
+
reason: "Decode",
|
|
160
|
+
error
|
|
161
|
+
})
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
get urlParamsBody(): Effect.Effect<never, Error.RequestError, UrlParams.UrlParams> {
|
|
166
|
+
return Effect.flatMap(this.text, (_) =>
|
|
167
|
+
Effect.try({
|
|
168
|
+
try: () => UrlParams.fromInput(new URLSearchParams(_)),
|
|
169
|
+
catch: (error) =>
|
|
170
|
+
Error.RequestError({
|
|
171
|
+
request: this,
|
|
172
|
+
reason: "Decode",
|
|
173
|
+
error
|
|
174
|
+
})
|
|
175
|
+
}))
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private formDataEffect:
|
|
179
|
+
| Effect.Effect<
|
|
180
|
+
Scope.Scope | FileSystem.FileSystem | Path.Path,
|
|
181
|
+
FormData.FormDataError,
|
|
182
|
+
FormData.PersistedFormData
|
|
183
|
+
>
|
|
184
|
+
| undefined
|
|
185
|
+
get formData(): Effect.Effect<
|
|
186
|
+
Scope.Scope | FileSystem.FileSystem | Path.Path,
|
|
187
|
+
FormData.FormDataError,
|
|
188
|
+
FormData.PersistedFormData
|
|
189
|
+
> {
|
|
190
|
+
if (this.formDataEffect) {
|
|
191
|
+
return this.formDataEffect
|
|
192
|
+
}
|
|
193
|
+
this.formDataEffect = Effect.runSync(Effect.cached(
|
|
194
|
+
FormData.formData(this.formDataStream)
|
|
195
|
+
))
|
|
196
|
+
return this.formDataEffect
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
get formDataStream(): Stream.Stream<never, FormData.FormDataError, FormData.Part> {
|
|
200
|
+
return Stream.pipeThroughChannel(
|
|
201
|
+
Stream.mapError(this.stream, (error) => FormData.FormDataError("InternalError", error)),
|
|
202
|
+
FormData.makeChannel(this.headers)
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private arrayBufferEffect: Effect.Effect<never, Error.RequestError, ArrayBuffer> | undefined
|
|
207
|
+
get arrayBuffer(): Effect.Effect<never, Error.RequestError, ArrayBuffer> {
|
|
208
|
+
if (this.arrayBuffer) {
|
|
209
|
+
return this.arrayBuffer
|
|
210
|
+
}
|
|
211
|
+
this.arrayBufferEffect = Effect.runSync(Effect.cached(
|
|
212
|
+
Effect.tryPromise({
|
|
213
|
+
try: () => this.source.arrayBuffer(),
|
|
214
|
+
catch: (error) =>
|
|
215
|
+
Error.RequestError({
|
|
216
|
+
request: this,
|
|
217
|
+
reason: "Decode",
|
|
218
|
+
error
|
|
219
|
+
})
|
|
220
|
+
})
|
|
221
|
+
))
|
|
222
|
+
return this.arrayBufferEffect
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -2,7 +2,7 @@ import type * as Schema from "@effect/schema/Schema"
|
|
|
2
2
|
import * as Effect from "effect/Effect"
|
|
3
3
|
import * as Effectable from "effect/Effectable"
|
|
4
4
|
import { dual } from "effect/Function"
|
|
5
|
-
import
|
|
5
|
+
import * as Stream from "effect/Stream"
|
|
6
6
|
import type * as PlatformError from "../../Error.js"
|
|
7
7
|
import type * as FileSystem from "../../FileSystem.js"
|
|
8
8
|
import type * as Body from "../../Http/Body.js"
|
|
@@ -259,3 +259,46 @@ export const setBody = dual<
|
|
|
259
259
|
body
|
|
260
260
|
)
|
|
261
261
|
})
|
|
262
|
+
|
|
263
|
+
/** @internal */
|
|
264
|
+
export const toWeb = (response: ServerResponse.ServerResponse, withoutBody = false): Response => {
|
|
265
|
+
if (withoutBody) {
|
|
266
|
+
return new Response(undefined, {
|
|
267
|
+
status: response.status,
|
|
268
|
+
statusText: response.statusText,
|
|
269
|
+
headers: response.headers
|
|
270
|
+
})
|
|
271
|
+
}
|
|
272
|
+
const body = response.body
|
|
273
|
+
switch (body._tag) {
|
|
274
|
+
case "Empty": {
|
|
275
|
+
return new Response(undefined, {
|
|
276
|
+
status: response.status,
|
|
277
|
+
statusText: response.statusText,
|
|
278
|
+
headers: response.headers
|
|
279
|
+
})
|
|
280
|
+
}
|
|
281
|
+
case "Uint8Array":
|
|
282
|
+
case "Raw": {
|
|
283
|
+
return new Response(body.body as any, {
|
|
284
|
+
status: response.status,
|
|
285
|
+
statusText: response.statusText,
|
|
286
|
+
headers: response.headers
|
|
287
|
+
})
|
|
288
|
+
}
|
|
289
|
+
case "FormData": {
|
|
290
|
+
return new Response(body.formData as any, {
|
|
291
|
+
status: response.status,
|
|
292
|
+
statusText: response.statusText,
|
|
293
|
+
headers: response.headers
|
|
294
|
+
})
|
|
295
|
+
}
|
|
296
|
+
case "Stream": {
|
|
297
|
+
return new Response(Stream.toReadableStream(body.stream), {
|
|
298
|
+
status: response.status,
|
|
299
|
+
statusText: response.statusText,
|
|
300
|
+
headers: response.headers
|
|
301
|
+
})
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
package/src/internal/worker.ts
CHANGED
|
@@ -283,11 +283,4 @@ export const makePoolLayer = <W>(managerLayer: Layer.Layer<never, never, Worker.
|
|
|
283
283
|
<Tag, I, E, O>(
|
|
284
284
|
tag: Context.Tag<Tag, Worker.WorkerPool<I, E, O>>,
|
|
285
285
|
options: Worker.WorkerPool.Options<I, W>
|
|
286
|
-
) =>
|
|
287
|
-
Layer.provide(
|
|
288
|
-
managerLayer,
|
|
289
|
-
Layer.scoped(
|
|
290
|
-
tag,
|
|
291
|
-
makePool<W>()(options)
|
|
292
|
-
)
|
|
293
|
-
)
|
|
286
|
+
) => Layer.scoped(tag, makePool<W>()(options)).pipe(Layer.provide(managerLayer))
|