@effect/platform-node 4.0.0-beta.8 → 4.0.0-beta.80
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/Mime.d.ts +9 -3
- package/dist/Mime.d.ts.map +1 -1
- package/dist/Mime.js +9 -3
- package/dist/Mime.js.map +1 -1
- package/dist/NodeChildProcessSpawner.d.ts +1 -1
- package/dist/NodeChildProcessSpawner.js +1 -1
- package/dist/NodeClusterHttp.d.ts +25 -7
- package/dist/NodeClusterHttp.d.ts.map +1 -1
- package/dist/NodeClusterHttp.js +20 -10
- package/dist/NodeClusterHttp.js.map +1 -1
- package/dist/NodeClusterSocket.d.ts +37 -11
- package/dist/NodeClusterSocket.d.ts.map +1 -1
- package/dist/NodeClusterSocket.js +37 -11
- package/dist/NodeClusterSocket.js.map +1 -1
- package/dist/NodeCrypto.d.ts +10 -0
- package/dist/NodeCrypto.d.ts.map +1 -0
- package/dist/NodeCrypto.js +22 -0
- package/dist/NodeCrypto.js.map +1 -0
- package/dist/NodeFileSystem.d.ts +4 -2
- package/dist/NodeFileSystem.d.ts.map +1 -1
- package/dist/NodeFileSystem.js +12 -3
- package/dist/NodeFileSystem.js.map +1 -1
- package/dist/NodeHttpClient.d.ts +98 -29
- package/dist/NodeHttpClient.d.ts.map +1 -1
- package/dist/NodeHttpClient.js +120 -33
- package/dist/NodeHttpClient.js.map +1 -1
- package/dist/NodeHttpIncomingMessage.d.ts +36 -9
- package/dist/NodeHttpIncomingMessage.d.ts.map +1 -1
- package/dist/NodeHttpIncomingMessage.js +40 -8
- package/dist/NodeHttpIncomingMessage.js.map +1 -1
- package/dist/NodeHttpPlatform.d.ts +10 -4
- package/dist/NodeHttpPlatform.d.ts.map +1 -1
- package/dist/NodeHttpPlatform.js +20 -7
- package/dist/NodeHttpPlatform.js.map +1 -1
- package/dist/NodeHttpServer.d.ts +59 -19
- package/dist/NodeHttpServer.d.ts.map +1 -1
- package/dist/NodeHttpServer.js +102 -52
- package/dist/NodeHttpServer.js.map +1 -1
- package/dist/NodeHttpServerRequest.d.ts +18 -5
- package/dist/NodeHttpServerRequest.d.ts.map +1 -1
- package/dist/NodeHttpServerRequest.js +11 -4
- package/dist/NodeHttpServerRequest.js.map +1 -1
- package/dist/NodeMultipart.d.ts +24 -4
- package/dist/NodeMultipart.d.ts.map +1 -1
- package/dist/NodeMultipart.js +24 -4
- package/dist/NodeMultipart.js.map +1 -1
- package/dist/NodePath.d.ts +15 -6
- package/dist/NodePath.d.ts.map +1 -1
- package/dist/NodePath.js +23 -7
- package/dist/NodePath.js.map +1 -1
- package/dist/NodeRedis.d.ts +27 -9
- package/dist/NodeRedis.d.ts.map +1 -1
- package/dist/NodeRedis.js +30 -12
- package/dist/NodeRedis.js.map +1 -1
- package/dist/NodeRuntime.d.ts +27 -36
- package/dist/NodeRuntime.d.ts.map +1 -1
- package/dist/NodeRuntime.js +17 -13
- package/dist/NodeRuntime.js.map +1 -1
- package/dist/NodeServices.d.ts +19 -5
- package/dist/NodeServices.d.ts.map +1 -1
- package/dist/NodeServices.js +7 -3
- package/dist/NodeServices.js.map +1 -1
- package/dist/NodeSink.d.ts +2 -2
- package/dist/NodeSink.js +2 -2
- package/dist/NodeSocket.d.ts +18 -3
- package/dist/NodeSocket.d.ts.map +1 -1
- package/dist/NodeSocket.js +27 -4
- package/dist/NodeSocket.js.map +1 -1
- package/dist/NodeSocketServer.d.ts +2 -2
- package/dist/NodeSocketServer.js +2 -2
- package/dist/NodeStdio.d.ts +5 -2
- package/dist/NodeStdio.d.ts.map +1 -1
- package/dist/NodeStdio.js +13 -3
- package/dist/NodeStdio.js.map +1 -1
- package/dist/NodeStream.d.ts +2 -2
- package/dist/NodeStream.js +2 -2
- package/dist/NodeTerminal.d.ts +8 -2
- package/dist/NodeTerminal.d.ts.map +1 -1
- package/dist/NodeTerminal.js +15 -3
- package/dist/NodeTerminal.js.map +1 -1
- package/dist/NodeWorker.d.ts +9 -2
- package/dist/NodeWorker.d.ts.map +1 -1
- package/dist/NodeWorker.js +22 -6
- package/dist/NodeWorker.js.map +1 -1
- package/dist/NodeWorkerRunner.d.ts +5 -1
- package/dist/NodeWorkerRunner.d.ts.map +1 -1
- package/dist/NodeWorkerRunner.js +18 -5
- package/dist/NodeWorkerRunner.js.map +1 -1
- package/dist/Undici.d.ts +18 -5
- package/dist/Undici.d.ts.map +1 -1
- package/dist/Undici.js +18 -5
- package/dist/Undici.js.map +1 -1
- package/dist/index.d.ts +28 -26
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -26
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/src/Mime.ts +10 -3
- package/src/NodeChildProcessSpawner.ts +1 -1
- package/src/NodeClusterHttp.ts +30 -11
- package/src/NodeClusterSocket.ts +37 -11
- package/src/NodeCrypto.ts +24 -0
- package/src/NodeFileSystem.ts +12 -3
- package/src/NodeHttpClient.ts +128 -38
- package/src/NodeHttpIncomingMessage.ts +48 -12
- package/src/NodeHttpPlatform.ts +21 -6
- package/src/NodeHttpServer.ts +124 -56
- package/src/NodeHttpServerRequest.ts +18 -5
- package/src/NodeMultipart.ts +24 -4
- package/src/NodePath.ts +23 -7
- package/src/NodeRedis.ts +32 -14
- package/src/NodeRuntime.ts +35 -37
- package/src/NodeServices.ts +21 -5
- package/src/NodeSink.ts +2 -2
- package/src/NodeSocket.ts +32 -4
- package/src/NodeSocketServer.ts +2 -2
- package/src/NodeStdio.ts +13 -3
- package/src/NodeStream.ts +2 -2
- package/src/NodeTerminal.ts +15 -3
- package/src/NodeWorker.ts +22 -6
- package/src/NodeWorkerRunner.ts +18 -5
- package/src/Undici.ts +18 -5
- package/src/index.ts +29 -26
package/src/NodeHttpServer.ts
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Node.js implementation of the Effect `HttpServer`.
|
|
3
|
+
*
|
|
4
|
+
* This module adapts a supplied Node `http.Server` into Effect's
|
|
5
|
+
* platform-independent HTTP server service. It starts the server with Node
|
|
6
|
+
* `listen` options, converts `request` events into `HttpServerRequest` values,
|
|
7
|
+
* writes `HttpServerResponse` bodies through Node's `ServerResponse`, and
|
|
8
|
+
* handles `upgrade` events by exposing the upgraded socket through
|
|
9
|
+
* `HttpServerRequest.upgrade`. It also exports request and upgrade handler
|
|
10
|
+
* constructors plus layers for the server alone, HTTP support services, the
|
|
11
|
+
* combined server, configurable options, and tests.
|
|
12
|
+
*
|
|
13
|
+
* @since 4.0.0
|
|
3
14
|
*/
|
|
4
15
|
import * as Cause from "effect/Cause"
|
|
5
16
|
import * as Config from "effect/Config"
|
|
17
|
+
import * as Context from "effect/Context"
|
|
18
|
+
import * as Duration from "effect/Duration"
|
|
6
19
|
import * as Effect from "effect/Effect"
|
|
7
20
|
import * as Fiber from "effect/Fiber"
|
|
8
21
|
import type * as FileSystem from "effect/FileSystem"
|
|
9
22
|
import { flow, type LazyArg } from "effect/Function"
|
|
10
23
|
import * as Latch from "effect/Latch"
|
|
11
24
|
import * as Layer from "effect/Layer"
|
|
25
|
+
import type * as Option from "effect/Option"
|
|
12
26
|
import type * as Path from "effect/Path"
|
|
13
27
|
import type * as Record from "effect/Record"
|
|
14
28
|
import * as Scope from "effect/Scope"
|
|
15
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
16
29
|
import * as Stream from "effect/Stream"
|
|
17
30
|
import * as Cookies from "effect/unstable/http/Cookies"
|
|
18
31
|
import * as Etag from "effect/unstable/http/Etag"
|
|
@@ -27,7 +40,7 @@ import type * as HttpPlatform from "effect/unstable/http/HttpPlatform"
|
|
|
27
40
|
import * as HttpServer from "effect/unstable/http/HttpServer"
|
|
28
41
|
import {
|
|
29
42
|
causeResponse,
|
|
30
|
-
|
|
43
|
+
ClientAbort,
|
|
31
44
|
HttpServerError,
|
|
32
45
|
RequestParseError,
|
|
33
46
|
ResponseError,
|
|
@@ -50,30 +63,44 @@ import * as NodeServices from "./NodeServices.ts"
|
|
|
50
63
|
import { NodeWS } from "./NodeSocket.ts"
|
|
51
64
|
|
|
52
65
|
/**
|
|
53
|
-
*
|
|
66
|
+
* Creates a scoped `HttpServer` from a Node `http.Server`, starts listening
|
|
67
|
+
* with the supplied options, registers request and upgrade handling, and closes
|
|
68
|
+
* the server during scope finalization with optional graceful-shutdown control.
|
|
69
|
+
*
|
|
54
70
|
* @category constructors
|
|
71
|
+
* @since 4.0.0
|
|
55
72
|
*/
|
|
56
73
|
export const make = Effect.fnUntraced(function*(
|
|
57
74
|
evaluate: LazyArg<Http.Server>,
|
|
58
|
-
options: Net.ListenOptions
|
|
75
|
+
options: Net.ListenOptions & {
|
|
76
|
+
readonly disablePreemptiveShutdown?: boolean | undefined
|
|
77
|
+
readonly gracefulShutdownTimeout?: Duration.Input | undefined
|
|
78
|
+
}
|
|
59
79
|
) {
|
|
60
80
|
const scope = yield* Effect.scope
|
|
61
81
|
const server = evaluate()
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
82
|
+
|
|
83
|
+
const shutdown = yield* Effect.callback<void>((resume) => {
|
|
84
|
+
if (!server.listening) {
|
|
85
|
+
return resume(Effect.void)
|
|
86
|
+
}
|
|
87
|
+
server.close((error) => {
|
|
88
|
+
if (error) {
|
|
89
|
+
resume(Effect.die(error))
|
|
90
|
+
} else {
|
|
91
|
+
resume(Effect.void)
|
|
67
92
|
}
|
|
68
|
-
server.close((error) => {
|
|
69
|
-
if (error) {
|
|
70
|
-
resume(Effect.die(error))
|
|
71
|
-
} else {
|
|
72
|
-
resume(Effect.void)
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
93
|
})
|
|
76
|
-
)
|
|
94
|
+
}).pipe(Effect.cached)
|
|
95
|
+
|
|
96
|
+
const preemptiveShutdown = options.disablePreemptiveShutdown ?
|
|
97
|
+
Effect.void :
|
|
98
|
+
Effect.timeoutOrElse(shutdown, {
|
|
99
|
+
duration: options.gracefulShutdownTimeout ?? Duration.seconds(20),
|
|
100
|
+
orElse: () => Effect.void
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
yield* Scope.addFinalizer(scope, shutdown)
|
|
77
104
|
|
|
78
105
|
yield* Effect.callback<void, ServeError>((resume) => {
|
|
79
106
|
function onError(cause: Error) {
|
|
@@ -111,7 +138,8 @@ export const make = Effect.fnUntraced(function*(
|
|
|
111
138
|
port: address.port
|
|
112
139
|
},
|
|
113
140
|
serve: Effect.fnUntraced(function*(httpApp, middleware) {
|
|
114
|
-
const
|
|
141
|
+
const serveScope = yield* Effect.scope
|
|
142
|
+
const scope = Scope.forkUnsafe(serveScope, "parallel")
|
|
115
143
|
const handler = yield* (makeHandler(httpApp, {
|
|
116
144
|
middleware: middleware as any,
|
|
117
145
|
scope
|
|
@@ -120,12 +148,11 @@ export const make = Effect.fnUntraced(function*(
|
|
|
120
148
|
middleware: middleware as any,
|
|
121
149
|
scope
|
|
122
150
|
})
|
|
123
|
-
yield*
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
)
|
|
151
|
+
yield* Scope.addFinalizerExit(serveScope, () => {
|
|
152
|
+
server.off("request", handler)
|
|
153
|
+
server.off("upgrade", upgradeHandler)
|
|
154
|
+
return preemptiveShutdown
|
|
155
|
+
})
|
|
129
156
|
server.on("request", handler)
|
|
130
157
|
server.on("upgrade", upgradeHandler)
|
|
131
158
|
})
|
|
@@ -133,8 +160,12 @@ export const make = Effect.fnUntraced(function*(
|
|
|
133
160
|
})
|
|
134
161
|
|
|
135
162
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
163
|
+
* Creates a Node `request` event handler for an Effect HTTP application,
|
|
164
|
+
* injecting a `HttpServerRequest` and interrupting the request fiber if the
|
|
165
|
+
* client closes the response before it finishes.
|
|
166
|
+
*
|
|
167
|
+
* @category handlers
|
|
168
|
+
* @since 4.0.0
|
|
138
169
|
*/
|
|
139
170
|
export const makeHandler = <
|
|
140
171
|
R,
|
|
@@ -152,26 +183,31 @@ export const makeHandler = <
|
|
|
152
183
|
Exclude<Effect.Services<App>, HttpServerRequest | Scope.Scope>
|
|
153
184
|
> => {
|
|
154
185
|
const handled = HttpEffect.toHandled(httpEffect, handleResponse, options.middleware as any)
|
|
155
|
-
return Effect.
|
|
156
|
-
|
|
186
|
+
return Effect.withFiber((parent) => {
|
|
187
|
+
const services = parent.context
|
|
188
|
+
return Effect.succeed(function handler(
|
|
157
189
|
nodeRequest: Http.IncomingMessage,
|
|
158
190
|
nodeResponse: Http.ServerResponse
|
|
159
191
|
) {
|
|
160
192
|
const map = new Map(services.mapUnsafe)
|
|
161
193
|
map.set(HttpServerRequest.key, new ServerRequestImpl(nodeRequest, nodeResponse))
|
|
162
|
-
const fiber = Fiber.runIn(Effect.runForkWith(
|
|
194
|
+
const fiber = Fiber.runIn(Effect.runForkWith(Context.makeUnsafe<any>(map))(handled), options.scope)
|
|
163
195
|
nodeResponse.on("close", () => {
|
|
164
196
|
if (!nodeResponse.writableEnded) {
|
|
165
|
-
fiber.interruptUnsafe(
|
|
197
|
+
fiber.interruptUnsafe(parent.id, ClientAbort.annotation)
|
|
166
198
|
}
|
|
167
199
|
})
|
|
168
|
-
}
|
|
200
|
+
})
|
|
169
201
|
})
|
|
170
202
|
}
|
|
171
203
|
|
|
172
204
|
/**
|
|
173
|
-
*
|
|
174
|
-
*
|
|
205
|
+
* Creates a Node `upgrade` event handler for an Effect HTTP application,
|
|
206
|
+
* exposing the upgraded WebSocket as the request's `upgrade` effect and
|
|
207
|
+
* interrupting the request fiber when the socket closes early.
|
|
208
|
+
*
|
|
209
|
+
* @category handlers
|
|
210
|
+
* @since 4.0.0
|
|
175
211
|
*/
|
|
176
212
|
export const makeUpgradeHandler = <
|
|
177
213
|
R,
|
|
@@ -190,8 +226,13 @@ export const makeUpgradeHandler = <
|
|
|
190
226
|
Exclude<Effect.Services<App>, HttpServerRequest | Scope.Scope>
|
|
191
227
|
> => {
|
|
192
228
|
const handledApp = HttpEffect.toHandled(httpEffect, handleResponse, options.middleware as any)
|
|
193
|
-
return Effect.
|
|
194
|
-
|
|
229
|
+
return Effect.withFiber((parent) => {
|
|
230
|
+
const services = parent.context
|
|
231
|
+
return Effect.succeed(function handler(
|
|
232
|
+
nodeRequest: Http.IncomingMessage,
|
|
233
|
+
socket: Duplex,
|
|
234
|
+
head: Buffer
|
|
235
|
+
) {
|
|
195
236
|
let nodeResponse_: Http.ServerResponse | undefined = undefined
|
|
196
237
|
const nodeResponse = () => {
|
|
197
238
|
if (nodeResponse_ === undefined) {
|
|
@@ -217,13 +258,14 @@ export const makeUpgradeHandler = <
|
|
|
217
258
|
))
|
|
218
259
|
const map = new Map(services.mapUnsafe)
|
|
219
260
|
map.set(HttpServerRequest.key, new ServerRequestImpl(nodeRequest, nodeResponse, upgradeEffect))
|
|
220
|
-
const fiber = Fiber.runIn(Effect.runForkWith(
|
|
261
|
+
const fiber = Fiber.runIn(Effect.runForkWith(Context.makeUnsafe<any>(map))(handledApp), options.scope)
|
|
221
262
|
socket.on("close", () => {
|
|
222
263
|
if (!socket.writableEnded) {
|
|
223
|
-
fiber.interruptUnsafe(
|
|
264
|
+
fiber.interruptUnsafe(parent.id, ClientAbort.annotation)
|
|
224
265
|
}
|
|
225
266
|
})
|
|
226
|
-
})
|
|
267
|
+
})
|
|
268
|
+
})
|
|
227
269
|
}
|
|
228
270
|
|
|
229
271
|
class ServerRequestImpl extends NodeHttpIncomingMessage<HttpServerError> implements HttpServerRequest {
|
|
@@ -239,7 +281,7 @@ class ServerRequestImpl extends NodeHttpIncomingMessage<HttpServerError> impleme
|
|
|
239
281
|
upgradeEffect?: Effect.Effect<Socket.Socket, HttpServerError>,
|
|
240
282
|
url = source.url!,
|
|
241
283
|
headersOverride?: Headers.Headers,
|
|
242
|
-
remoteAddressOverride?: string
|
|
284
|
+
remoteAddressOverride?: Option.Option<string>
|
|
243
285
|
) {
|
|
244
286
|
super(source, (cause) =>
|
|
245
287
|
new HttpServerError({
|
|
@@ -271,7 +313,7 @@ class ServerRequestImpl extends NodeHttpIncomingMessage<HttpServerError> impleme
|
|
|
271
313
|
options: {
|
|
272
314
|
readonly url?: string | undefined
|
|
273
315
|
readonly headers?: Headers.Headers | undefined
|
|
274
|
-
readonly remoteAddress?: string | undefined
|
|
316
|
+
readonly remoteAddress?: Option.Option<string> | undefined
|
|
275
317
|
}
|
|
276
318
|
) {
|
|
277
319
|
return new ServerRequestImpl(
|
|
@@ -280,7 +322,7 @@ class ServerRequestImpl extends NodeHttpIncomingMessage<HttpServerError> impleme
|
|
|
280
322
|
this.upgradeEffect,
|
|
281
323
|
options.url ?? this.url,
|
|
282
324
|
options.headers ?? this.headersOverride,
|
|
283
|
-
options.remoteAddress
|
|
325
|
+
"remoteAddress" in options ? options.remoteAddress : this.remoteAddressOverride
|
|
284
326
|
)
|
|
285
327
|
}
|
|
286
328
|
|
|
@@ -347,17 +389,26 @@ class ServerRequestImpl extends NodeHttpIncomingMessage<HttpServerError> impleme
|
|
|
347
389
|
}
|
|
348
390
|
|
|
349
391
|
/**
|
|
350
|
-
*
|
|
351
|
-
*
|
|
392
|
+
* Provides an `HttpServer` by creating and managing a scoped Node
|
|
393
|
+
* `http.Server` with the supplied listen and shutdown options.
|
|
394
|
+
*
|
|
395
|
+
* @category layers
|
|
396
|
+
* @since 4.0.0
|
|
352
397
|
*/
|
|
353
398
|
export const layerServer: (
|
|
354
399
|
evaluate: LazyArg<Http.Server<typeof Http.IncomingMessage, typeof Http.ServerResponse>>,
|
|
355
|
-
options: Net.ListenOptions
|
|
400
|
+
options: Net.ListenOptions & {
|
|
401
|
+
readonly disablePreemptiveShutdown?: boolean | undefined
|
|
402
|
+
readonly gracefulShutdownTimeout?: Duration.Input | undefined
|
|
403
|
+
}
|
|
356
404
|
) => Layer.Layer<HttpServer.HttpServer, ServeError> = flow(make, Layer.effect(HttpServer.HttpServer))
|
|
357
405
|
|
|
358
406
|
/**
|
|
359
|
-
*
|
|
360
|
-
*
|
|
407
|
+
* Provides the Node HTTP support services used by `NodeHttpServer`, including
|
|
408
|
+
* the HTTP platform, ETag generator, and core Node platform services.
|
|
409
|
+
*
|
|
410
|
+
* @category layers
|
|
411
|
+
* @since 4.0.0
|
|
361
412
|
*/
|
|
362
413
|
export const layerHttpServices: Layer.Layer<
|
|
363
414
|
NodeServices.NodeServices | HttpPlatform.HttpPlatform | Etag.Generator
|
|
@@ -368,12 +419,18 @@ export const layerHttpServices: Layer.Layer<
|
|
|
368
419
|
)
|
|
369
420
|
|
|
370
421
|
/**
|
|
371
|
-
*
|
|
372
|
-
*
|
|
422
|
+
* Provides a Node `HttpServer` together with the Node HTTP platform, ETag, and
|
|
423
|
+
* core platform services required to serve requests.
|
|
424
|
+
*
|
|
425
|
+
* @category layers
|
|
426
|
+
* @since 4.0.0
|
|
373
427
|
*/
|
|
374
428
|
export const layer = (
|
|
375
429
|
evaluate: LazyArg<Http.Server>,
|
|
376
|
-
options: Net.ListenOptions
|
|
430
|
+
options: Net.ListenOptions & {
|
|
431
|
+
readonly disablePreemptiveShutdown?: boolean | undefined
|
|
432
|
+
readonly gracefulShutdownTimeout?: Duration.Input | undefined
|
|
433
|
+
}
|
|
377
434
|
): Layer.Layer<
|
|
378
435
|
HttpServer.HttpServer | NodeServices.NodeServices | HttpPlatform.HttpPlatform | Etag.Generator,
|
|
379
436
|
ServeError
|
|
@@ -384,26 +441,37 @@ export const layer = (
|
|
|
384
441
|
)
|
|
385
442
|
|
|
386
443
|
/**
|
|
387
|
-
*
|
|
388
|
-
*
|
|
444
|
+
* Provides a Node `HttpServer` and HTTP support services, reading the listen
|
|
445
|
+
* and shutdown options from a `Config` value.
|
|
446
|
+
*
|
|
447
|
+
* @category layers
|
|
448
|
+
* @since 4.0.0
|
|
389
449
|
*/
|
|
390
450
|
export const layerConfig = (
|
|
391
451
|
evaluate: LazyArg<Http.Server>,
|
|
392
|
-
options: Config.Wrap<
|
|
452
|
+
options: Config.Wrap<
|
|
453
|
+
Net.ListenOptions & {
|
|
454
|
+
readonly disablePreemptiveShutdown?: boolean | undefined
|
|
455
|
+
readonly gracefulShutdownTimeout?: Duration.Input | undefined
|
|
456
|
+
}
|
|
457
|
+
>
|
|
393
458
|
): Layer.Layer<
|
|
394
459
|
HttpServer.HttpServer | FileSystem.FileSystem | Path.Path | HttpPlatform.HttpPlatform | Etag.Generator,
|
|
395
460
|
ServeError | Config.ConfigError
|
|
396
461
|
> =>
|
|
397
462
|
Layer.mergeAll(
|
|
398
463
|
Layer.effect(HttpServer.HttpServer)(
|
|
399
|
-
Effect.flatMap(Config.unwrap(options)
|
|
464
|
+
Effect.flatMap(Config.unwrap(options), (options) => make(evaluate, options))
|
|
400
465
|
),
|
|
401
466
|
layerHttpServices
|
|
402
467
|
)
|
|
403
468
|
|
|
404
469
|
/**
|
|
405
|
-
*
|
|
406
|
-
*
|
|
470
|
+
* Provides a test HTTP server listening on an ephemeral port together with a
|
|
471
|
+
* Fetch-backed `HttpClient` configured for server integration tests.
|
|
472
|
+
*
|
|
473
|
+
* @category testing
|
|
474
|
+
* @since 4.0.0
|
|
407
475
|
*/
|
|
408
476
|
export const layerTest: Layer.Layer<
|
|
409
477
|
| HttpServer.HttpServer
|
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Accessors for the Node.js objects behind an Effect HTTP server request.
|
|
3
|
+
*
|
|
4
|
+
* `toIncomingMessage` returns the underlying Node `http.IncomingMessage`.
|
|
5
|
+
* `toServerResponse` returns the underlying Node `http.ServerResponse`,
|
|
6
|
+
* evaluating the stored response thunk when the response was created lazily.
|
|
7
|
+
*
|
|
8
|
+
* @since 4.0.0
|
|
3
9
|
*/
|
|
4
10
|
import type { HttpServerRequest } from "effect/unstable/http/HttpServerRequest"
|
|
5
11
|
import type * as Http from "node:http"
|
|
6
12
|
|
|
7
13
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
14
|
+
* Returns the underlying Node `IncomingMessage` for a platform Node
|
|
15
|
+
* `HttpServerRequest`.
|
|
16
|
+
*
|
|
17
|
+
* @category accessors
|
|
18
|
+
* @since 4.0.0
|
|
10
19
|
*/
|
|
11
20
|
export const toIncomingMessage = (self: HttpServerRequest): Http.IncomingMessage => self.source as any
|
|
12
21
|
|
|
13
22
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
23
|
+
* Returns the underlying Node `ServerResponse` for a platform Node
|
|
24
|
+
* `HttpServerRequest`, evaluating the stored response thunk when the response
|
|
25
|
+
* was created lazily.
|
|
26
|
+
*
|
|
27
|
+
* @category accessors
|
|
28
|
+
* @since 4.0.0
|
|
16
29
|
*/
|
|
17
30
|
export const toServerResponse = (self: HttpServerRequest): Http.ServerResponse => {
|
|
18
31
|
const res = (self as any).response
|
package/src/NodeMultipart.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Node.js multipart parsing for HTTP `multipart/form-data` request bodies.
|
|
3
|
+
*
|
|
4
|
+
* `NodeMultipart` adapts a Node `Readable` plus incoming HTTP headers into
|
|
5
|
+
* Effect's shared multipart model. It can expose form parts as a stream or
|
|
6
|
+
* collect a complete persisted form by writing file uploads to scoped temporary
|
|
7
|
+
* files through the current `FileSystem` and `Path` services. `fileToReadable`
|
|
8
|
+
* returns the underlying Node readable stream for file parts produced by this
|
|
9
|
+
* parser.
|
|
10
|
+
*
|
|
11
|
+
* @since 4.0.0
|
|
3
12
|
*/
|
|
4
13
|
import * as Effect from "effect/Effect"
|
|
5
14
|
import type * as FileSystem from "effect/FileSystem"
|
|
@@ -16,8 +25,12 @@ import * as NodeStreamP from "node:stream/promises"
|
|
|
16
25
|
import * as NodeStream from "./NodeStream.ts"
|
|
17
26
|
|
|
18
27
|
/**
|
|
19
|
-
*
|
|
28
|
+
* Parses multipart data from a Node readable request body and headers into a
|
|
29
|
+
* stream of `Multipart.Part` values, converting parser failures to
|
|
30
|
+
* `MultipartError`.
|
|
31
|
+
*
|
|
20
32
|
* @category constructors
|
|
33
|
+
* @since 4.0.0
|
|
21
34
|
*/
|
|
22
35
|
export const stream = (
|
|
23
36
|
source: Readable,
|
|
@@ -39,8 +52,11 @@ export const stream = (
|
|
|
39
52
|
)
|
|
40
53
|
|
|
41
54
|
/**
|
|
42
|
-
*
|
|
55
|
+
* Parses multipart data from a Node readable request body and persists file
|
|
56
|
+
* parts using the current `FileSystem`, `Path`, and `Scope` services.
|
|
57
|
+
*
|
|
43
58
|
* @category constructors
|
|
59
|
+
* @since 4.0.0
|
|
44
60
|
*/
|
|
45
61
|
export const persisted = (
|
|
46
62
|
source: Readable,
|
|
@@ -57,7 +73,11 @@ export const persisted = (
|
|
|
57
73
|
}))
|
|
58
74
|
|
|
59
75
|
/**
|
|
60
|
-
*
|
|
76
|
+
* Returns the underlying Node readable stream for a multipart file produced by
|
|
77
|
+
* the Node multipart parser.
|
|
78
|
+
*
|
|
79
|
+
* @category converting
|
|
80
|
+
* @since 4.0.0
|
|
61
81
|
*/
|
|
62
82
|
export const fileToReadable = (file: Multipart.File): Readable => (file as FileImpl).file
|
|
63
83
|
|
package/src/NodePath.ts
CHANGED
|
@@ -1,24 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Node.js layers for Effect's `Path` service.
|
|
3
|
+
*
|
|
4
|
+
* This module provides the default, POSIX, and Windows variants of the
|
|
5
|
+
* platform-independent `Path` service by reusing the shared Node path
|
|
6
|
+
* implementation. The provided path services include Node file URL conversion
|
|
7
|
+
* behavior.
|
|
8
|
+
*
|
|
9
|
+
* @since 4.0.0
|
|
3
10
|
*/
|
|
4
11
|
import * as NodePath from "@effect/platform-node-shared/NodePath"
|
|
5
12
|
import type * as Layer from "effect/Layer"
|
|
6
13
|
import type { Path } from "effect/Path"
|
|
7
14
|
|
|
8
15
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
16
|
+
* Provides the default Node `Path` service using the platform's `node:path`
|
|
17
|
+
* implementation.
|
|
18
|
+
*
|
|
19
|
+
* @category layers
|
|
20
|
+
* @since 4.0.0
|
|
11
21
|
*/
|
|
12
22
|
export const layer: Layer.Layer<Path> = NodePath.layer
|
|
13
23
|
|
|
14
24
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
25
|
+
* Provides the `Path` service using Node's POSIX path implementation,
|
|
26
|
+
* regardless of the host platform.
|
|
27
|
+
*
|
|
28
|
+
* @category layers
|
|
29
|
+
* @since 4.0.0
|
|
17
30
|
*/
|
|
18
31
|
export const layerPosix: Layer.Layer<Path> = NodePath.layerPosix
|
|
19
32
|
|
|
20
33
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
34
|
+
* Provides the `Path` service using Node's Windows path implementation,
|
|
35
|
+
* regardless of the host platform.
|
|
36
|
+
*
|
|
37
|
+
* @category layers
|
|
38
|
+
* @since 4.0.0
|
|
23
39
|
*/
|
|
24
40
|
export const layerWin32: Layer.Layer<Path> = NodePath.layerWin32
|
package/src/NodeRedis.ts
CHANGED
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Node.js Redis integration backed by `ioredis`.
|
|
3
|
+
*
|
|
4
|
+
* This module creates a scoped `ioredis` client and exposes it in two forms:
|
|
5
|
+
* the generic `Redis` service and the {@link NodeRedis} service for direct
|
|
6
|
+
* access to the underlying client. `layer` accepts ioredis options directly,
|
|
7
|
+
* while `layerConfig` reads them from Effect config. Both layers close the
|
|
8
|
+
* client when the layer scope ends.
|
|
9
|
+
*
|
|
10
|
+
* @since 4.0.0
|
|
3
11
|
*/
|
|
4
12
|
import * as Config from "effect/Config"
|
|
13
|
+
import * as Context from "effect/Context"
|
|
5
14
|
import * as Effect from "effect/Effect"
|
|
6
15
|
import * as Fn from "effect/Function"
|
|
7
16
|
import * as Layer from "effect/Layer"
|
|
8
17
|
import * as Scope from "effect/Scope"
|
|
9
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
10
18
|
import * as Redis from "effect/unstable/persistence/Redis"
|
|
11
19
|
import * as IoRedis from "ioredis"
|
|
12
20
|
|
|
13
21
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
22
|
+
* Service tag for the Node Redis integration, exposing the underlying
|
|
23
|
+
* `ioredis` client and a `use` helper that maps client failures to
|
|
24
|
+
* `RedisError`.
|
|
25
|
+
*
|
|
26
|
+
* @category services
|
|
27
|
+
* @since 4.0.0
|
|
16
28
|
*/
|
|
17
|
-
export class NodeRedis extends
|
|
29
|
+
export class NodeRedis extends Context.Service<NodeRedis, {
|
|
18
30
|
readonly client: IoRedis.Redis
|
|
19
31
|
readonly use: <A>(f: (client: IoRedis.Redis) => Promise<A>) => Effect.Effect<A, Redis.RedisError>
|
|
20
32
|
}>()("@effect/platform-node/NodeRedis") {}
|
|
@@ -45,30 +57,36 @@ const make = Effect.fnUntraced(function*(
|
|
|
45
57
|
use
|
|
46
58
|
})
|
|
47
59
|
|
|
48
|
-
return
|
|
49
|
-
|
|
60
|
+
return Context.make(NodeRedis, nodeRedis).pipe(
|
|
61
|
+
Context.add(Redis.Redis, redis)
|
|
50
62
|
)
|
|
51
63
|
})
|
|
52
64
|
|
|
53
65
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
66
|
+
* Provides `Redis` and `NodeRedis` services backed by an `ioredis` client
|
|
67
|
+
* created with the supplied options and closed when the layer scope ends.
|
|
68
|
+
*
|
|
69
|
+
* @category layers
|
|
70
|
+
* @since 4.0.0
|
|
56
71
|
*/
|
|
57
72
|
export const layer = (
|
|
58
73
|
options?: IoRedis.RedisOptions | undefined
|
|
59
|
-
): Layer.Layer<Redis.Redis | NodeRedis> => Layer.
|
|
74
|
+
): Layer.Layer<Redis.Redis | NodeRedis> => Layer.effectContext(make(options))
|
|
60
75
|
|
|
61
76
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
77
|
+
* Provides `Redis` and `NodeRedis` services from `Config`-backed ioredis
|
|
78
|
+
* options, closing the client when the layer scope ends.
|
|
79
|
+
*
|
|
80
|
+
* @category layers
|
|
81
|
+
* @since 4.0.0
|
|
64
82
|
*/
|
|
65
83
|
export const layerConfig: (
|
|
66
84
|
options: Config.Wrap<IoRedis.RedisOptions>
|
|
67
85
|
) => Layer.Layer<Redis.Redis | NodeRedis, Config.ConfigError> = (
|
|
68
86
|
options: Config.Wrap<IoRedis.RedisOptions>
|
|
69
87
|
): Layer.Layer<Redis.Redis | NodeRedis, Config.ConfigError> =>
|
|
70
|
-
Layer.
|
|
71
|
-
Config.unwrap(options).
|
|
88
|
+
Layer.effectContext(
|
|
89
|
+
Config.unwrap(options).pipe(
|
|
72
90
|
Effect.flatMap(make)
|
|
73
91
|
)
|
|
74
92
|
)
|
package/src/NodeRuntime.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Node.js process runner for Effect programs.
|
|
3
|
+
*
|
|
4
|
+
* This module exports `runMain`, which runs one Effect as the main process
|
|
5
|
+
* fiber in Node.js. It reuses the shared Node runtime runner, including its
|
|
6
|
+
* error reporting, `SIGINT` / `SIGTERM` interruption, and optional teardown
|
|
7
|
+
* behavior.
|
|
8
|
+
*
|
|
9
|
+
* @since 4.0.0
|
|
3
10
|
*/
|
|
4
11
|
import * as NodeRuntime from "@effect/platform-node-shared/NodeRuntime"
|
|
5
12
|
import type { Effect } from "effect/Effect"
|
|
@@ -8,6 +15,12 @@ import type * as Runtime from "effect/Runtime"
|
|
|
8
15
|
/**
|
|
9
16
|
* Helps you run a main effect with built-in error handling, logging, and signal management.
|
|
10
17
|
*
|
|
18
|
+
* **When to use**
|
|
19
|
+
*
|
|
20
|
+
* Use to run a Node.js application's main Effect with structured error
|
|
21
|
+
* handling, log management, interrupt support, or advanced teardown
|
|
22
|
+
* capabilities.
|
|
23
|
+
*
|
|
11
24
|
* **Details**
|
|
12
25
|
*
|
|
13
26
|
* This function launches an Effect as the main entry point, setting exit codes
|
|
@@ -16,26 +29,23 @@ import type * as Runtime from "effect/Runtime"
|
|
|
16
29
|
* behaviors can be turned off. You can also provide custom teardown logic to
|
|
17
30
|
* finalize resources or produce different exit codes.
|
|
18
31
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* An optional object that can include:
|
|
32
|
+
* The optional configuration object can include:
|
|
22
33
|
* - `disableErrorReporting`: Turn off automatic error logging.
|
|
23
|
-
* - `disablePrettyLogger`: Avoid adding the pretty logger.
|
|
24
34
|
* - `teardown`: Provide custom finalization logic.
|
|
25
35
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* Use this function to run an Effect as your application’s main program, especially
|
|
29
|
-
* when you need structured error handling, log management, interrupt support,
|
|
30
|
-
* or advanced teardown capabilities.
|
|
31
|
-
*
|
|
32
|
-
* @since 1.0.0
|
|
33
|
-
* @category Run main
|
|
36
|
+
* @category running
|
|
37
|
+
* @since 4.0.0
|
|
34
38
|
*/
|
|
35
39
|
export const runMain: {
|
|
36
40
|
/**
|
|
37
41
|
* Helps you run a main effect with built-in error handling, logging, and signal management.
|
|
38
42
|
*
|
|
43
|
+
* **When to use**
|
|
44
|
+
*
|
|
45
|
+
* Use to run a Node.js application's main Effect with structured error
|
|
46
|
+
* handling, log management, interrupt support, or advanced teardown
|
|
47
|
+
* capabilities.
|
|
48
|
+
*
|
|
39
49
|
* **Details**
|
|
40
50
|
*
|
|
41
51
|
* This function launches an Effect as the main entry point, setting exit codes
|
|
@@ -44,21 +54,12 @@ export const runMain: {
|
|
|
44
54
|
* behaviors can be turned off. You can also provide custom teardown logic to
|
|
45
55
|
* finalize resources or produce different exit codes.
|
|
46
56
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* An optional object that can include:
|
|
57
|
+
* The optional configuration object can include:
|
|
50
58
|
* - `disableErrorReporting`: Turn off automatic error logging.
|
|
51
|
-
* - `disablePrettyLogger`: Avoid adding the pretty logger.
|
|
52
59
|
* - `teardown`: Provide custom finalization logic.
|
|
53
60
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* Use this function to run an Effect as your application’s main program, especially
|
|
57
|
-
* when you need structured error handling, log management, interrupt support,
|
|
58
|
-
* or advanced teardown capabilities.
|
|
59
|
-
*
|
|
60
|
-
* @since 1.0.0
|
|
61
|
-
* @category Run main
|
|
61
|
+
* @category running
|
|
62
|
+
* @since 4.0.0
|
|
62
63
|
*/
|
|
63
64
|
(
|
|
64
65
|
options?: {
|
|
@@ -69,6 +70,12 @@ export const runMain: {
|
|
|
69
70
|
/**
|
|
70
71
|
* Helps you run a main effect with built-in error handling, logging, and signal management.
|
|
71
72
|
*
|
|
73
|
+
* **When to use**
|
|
74
|
+
*
|
|
75
|
+
* Use to run a Node.js application's main Effect with structured error
|
|
76
|
+
* handling, log management, interrupt support, or advanced teardown
|
|
77
|
+
* capabilities.
|
|
78
|
+
*
|
|
72
79
|
* **Details**
|
|
73
80
|
*
|
|
74
81
|
* This function launches an Effect as the main entry point, setting exit codes
|
|
@@ -77,21 +84,12 @@ export const runMain: {
|
|
|
77
84
|
* behaviors can be turned off. You can also provide custom teardown logic to
|
|
78
85
|
* finalize resources or produce different exit codes.
|
|
79
86
|
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* An optional object that can include:
|
|
87
|
+
* The optional configuration object can include:
|
|
83
88
|
* - `disableErrorReporting`: Turn off automatic error logging.
|
|
84
|
-
* - `disablePrettyLogger`: Avoid adding the pretty logger.
|
|
85
89
|
* - `teardown`: Provide custom finalization logic.
|
|
86
90
|
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* Use this function to run an Effect as your application’s main program, especially
|
|
90
|
-
* when you need structured error handling, log management, interrupt support,
|
|
91
|
-
* or advanced teardown capabilities.
|
|
92
|
-
*
|
|
93
|
-
* @since 1.0.0
|
|
94
|
-
* @category Run main
|
|
91
|
+
* @category running
|
|
92
|
+
* @since 4.0.0
|
|
95
93
|
*/
|
|
96
94
|
<E, A>(
|
|
97
95
|
effect: Effect<A, E>,
|