@effect/platform-node-shared 0.29.3 → 0.30.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/NodeClusterRunnerSocket/package.json +6 -0
- package/NodeClusterShardManagerSocket/package.json +6 -0
- package/NodeClusterSocketCommon/package.json +6 -0
- package/NodeSocketServer/package.json +6 -0
- package/dist/cjs/NodeClusterRunnerSocket.js +49 -0
- package/dist/cjs/NodeClusterRunnerSocket.js.map +1 -0
- package/dist/cjs/NodeClusterShardManagerSocket.js +38 -0
- package/dist/cjs/NodeClusterShardManagerSocket.js.map +1 -0
- package/dist/cjs/NodeClusterSocketCommon.js +34 -0
- package/dist/cjs/NodeClusterSocketCommon.js.map +1 -0
- package/dist/cjs/NodeSocket.js +2 -1
- package/dist/cjs/NodeSocket.js.map +1 -1
- package/dist/cjs/NodeSocketServer.js +149 -0
- package/dist/cjs/NodeSocketServer.js.map +1 -0
- package/dist/dts/NodeClusterRunnerSocket.d.ts +24 -0
- package/dist/dts/NodeClusterRunnerSocket.d.ts.map +1 -0
- package/dist/dts/NodeClusterShardManagerSocket.d.ts +22 -0
- package/dist/dts/NodeClusterShardManagerSocket.d.ts.map +1 -0
- package/dist/dts/NodeClusterSocketCommon.d.ts +12 -0
- package/dist/dts/NodeClusterSocketCommon.d.ts.map +1 -0
- package/dist/dts/NodeSocket.d.ts.map +1 -1
- package/dist/dts/NodeSocketServer.d.ts +44 -0
- package/dist/dts/NodeSocketServer.d.ts.map +1 -0
- package/dist/esm/NodeClusterRunnerSocket.js +39 -0
- package/dist/esm/NodeClusterRunnerSocket.js.map +1 -0
- package/dist/esm/NodeClusterShardManagerSocket.js +28 -0
- package/dist/esm/NodeClusterShardManagerSocket.js.map +1 -0
- package/dist/esm/NodeClusterSocketCommon.js +25 -0
- package/dist/esm/NodeClusterSocketCommon.js.map +1 -0
- package/dist/esm/NodeSocket.js +2 -1
- package/dist/esm/NodeSocket.js.map +1 -1
- package/dist/esm/NodeSocketServer.js +137 -0
- package/dist/esm/NodeSocketServer.js.map +1 -0
- package/package.json +40 -4
- package/src/NodeClusterRunnerSocket.ts +78 -0
- package/src/NodeClusterShardManagerSocket.ts +54 -0
- package/src/NodeClusterSocketCommon.ts +35 -0
- package/src/NodeSocket.ts +47 -48
- package/src/NodeSocketServer.ts +225 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Socket from "@effect/platform/Socket"
|
|
5
|
+
import * as SocketServer from "@effect/platform/SocketServer"
|
|
6
|
+
import type { Cause } from "effect/Cause"
|
|
7
|
+
import * as Context from "effect/Context"
|
|
8
|
+
import * as Effect from "effect/Effect"
|
|
9
|
+
import * as Exit from "effect/Exit"
|
|
10
|
+
import * as FiberRef from "effect/FiberRef"
|
|
11
|
+
import * as FiberSet from "effect/FiberSet"
|
|
12
|
+
import { pipe } from "effect/Function"
|
|
13
|
+
import * as Layer from "effect/Layer"
|
|
14
|
+
import * as Scope from "effect/Scope"
|
|
15
|
+
import type * as Http from "node:http"
|
|
16
|
+
import * as Net from "node:net"
|
|
17
|
+
import * as WS from "ws"
|
|
18
|
+
import * as NodeSocket from "./NodeSocket.js"
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @since 1.0.0
|
|
22
|
+
* @category tags
|
|
23
|
+
*/
|
|
24
|
+
export class IncomingMessage extends Context.Tag("@effect/platform-node-shared/NodeSocketServer/IncomingMessage")<
|
|
25
|
+
IncomingMessage,
|
|
26
|
+
Http.IncomingMessage
|
|
27
|
+
>() {}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @since 1.0.0
|
|
31
|
+
* @category constructors
|
|
32
|
+
*/
|
|
33
|
+
export const make = Effect.fnUntraced(function*(
|
|
34
|
+
options: Net.ServerOpts & Net.ListenOptions
|
|
35
|
+
) {
|
|
36
|
+
const server = yield* Effect.acquireRelease(
|
|
37
|
+
Effect.sync(() => Net.createServer(options)),
|
|
38
|
+
(server) =>
|
|
39
|
+
Effect.async<void>((resume) => {
|
|
40
|
+
server.close(() => resume(Effect.void))
|
|
41
|
+
})
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
yield* Effect.async<void, SocketServer.SocketServerError>((resume) => {
|
|
45
|
+
server.once("error", (cause) => {
|
|
46
|
+
resume(Effect.fail(
|
|
47
|
+
new SocketServer.SocketServerError({
|
|
48
|
+
reason: "Open",
|
|
49
|
+
cause
|
|
50
|
+
})
|
|
51
|
+
))
|
|
52
|
+
})
|
|
53
|
+
server.listen(options, () => {
|
|
54
|
+
resume(Effect.void)
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const run = Effect.fnUntraced(function*<R, E, _>(handler: (socket: Socket.Socket) => Effect.Effect<_, E, R>) {
|
|
59
|
+
const scope = yield* Scope.make()
|
|
60
|
+
const fiberSet = yield* FiberSet.make().pipe(
|
|
61
|
+
Scope.extend(scope)
|
|
62
|
+
)
|
|
63
|
+
const run = yield* FiberSet.runtime(fiberSet)<R>()
|
|
64
|
+
function onConnection(conn: Net.Socket) {
|
|
65
|
+
pipe(
|
|
66
|
+
NodeSocket.fromDuplex(
|
|
67
|
+
Effect.acquireRelease(
|
|
68
|
+
Effect.succeed(conn),
|
|
69
|
+
(conn) =>
|
|
70
|
+
Effect.sync(() => {
|
|
71
|
+
if (conn.closed === false) {
|
|
72
|
+
conn.destroySoon()
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
)
|
|
76
|
+
),
|
|
77
|
+
Effect.flatMap(handler),
|
|
78
|
+
Effect.catchAllCause(reportUnhandledError),
|
|
79
|
+
Effect.provideService(NodeSocket.NetSocket, conn),
|
|
80
|
+
run
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
return yield* Effect.async<never>((_resume) => {
|
|
84
|
+
server.on("connection", onConnection)
|
|
85
|
+
return Effect.sync(() => {
|
|
86
|
+
server.off("connection", onConnection)
|
|
87
|
+
})
|
|
88
|
+
}).pipe(
|
|
89
|
+
Effect.ensuring(Scope.close(scope, Exit.void))
|
|
90
|
+
)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const address = server.address()!
|
|
94
|
+
return SocketServer.SocketServer.of({
|
|
95
|
+
address: typeof address === "string" ?
|
|
96
|
+
{
|
|
97
|
+
_tag: "UnixAddress",
|
|
98
|
+
path: address
|
|
99
|
+
} :
|
|
100
|
+
{
|
|
101
|
+
_tag: "TcpAddress",
|
|
102
|
+
hostname: address.address,
|
|
103
|
+
port: address.port
|
|
104
|
+
},
|
|
105
|
+
run
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @since 1.0.0
|
|
111
|
+
* @category layers
|
|
112
|
+
*/
|
|
113
|
+
export const layer = (
|
|
114
|
+
options: Net.ServerOpts & Net.ListenOptions
|
|
115
|
+
): Layer.Layer<SocketServer.SocketServer, SocketServer.SocketServerError> =>
|
|
116
|
+
Layer.scoped(
|
|
117
|
+
SocketServer.SocketServer,
|
|
118
|
+
make(options)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @since 1.0.0
|
|
123
|
+
* @category constructors
|
|
124
|
+
*/
|
|
125
|
+
export const makeWebSocket: (
|
|
126
|
+
options: WS.ServerOptions<typeof WS.WebSocket, typeof Http.IncomingMessage>
|
|
127
|
+
) => Effect.Effect<
|
|
128
|
+
SocketServer.SocketServer["Type"],
|
|
129
|
+
SocketServer.SocketServerError,
|
|
130
|
+
Scope.Scope
|
|
131
|
+
> = Effect.fnUntraced(function*(
|
|
132
|
+
options: WS.ServerOptions
|
|
133
|
+
) {
|
|
134
|
+
const server = yield* Effect.acquireRelease(
|
|
135
|
+
Effect.sync(() => new WS.WebSocketServer(options)),
|
|
136
|
+
(server) =>
|
|
137
|
+
Effect.async<void>((resume) => {
|
|
138
|
+
server.close(() => resume(Effect.void))
|
|
139
|
+
})
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
yield* Effect.async<void, SocketServer.SocketServerError>((resume) => {
|
|
143
|
+
server.once("error", (error) => {
|
|
144
|
+
resume(Effect.fail(
|
|
145
|
+
new SocketServer.SocketServerError({
|
|
146
|
+
reason: "Open",
|
|
147
|
+
cause: error
|
|
148
|
+
})
|
|
149
|
+
))
|
|
150
|
+
})
|
|
151
|
+
server.once("listening", () => {
|
|
152
|
+
resume(Effect.void)
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
const run = Effect.fnUntraced(function*<R, E, _>(handler: (socket: Socket.Socket) => Effect.Effect<_, E, R>) {
|
|
157
|
+
const scope = yield* Scope.make()
|
|
158
|
+
const fiberSet = yield* FiberSet.make().pipe(
|
|
159
|
+
Scope.extend(scope)
|
|
160
|
+
)
|
|
161
|
+
const run = yield* FiberSet.runtime(fiberSet)<R>()
|
|
162
|
+
function onConnection(conn: Net.Socket, req: Http.IncomingMessage) {
|
|
163
|
+
pipe(
|
|
164
|
+
Socket.fromWebSocket(
|
|
165
|
+
Effect.acquireRelease(
|
|
166
|
+
Effect.succeed(conn as unknown as globalThis.WebSocket),
|
|
167
|
+
(conn) =>
|
|
168
|
+
Effect.sync(() => {
|
|
169
|
+
conn.close()
|
|
170
|
+
})
|
|
171
|
+
)
|
|
172
|
+
),
|
|
173
|
+
Effect.flatMap(handler),
|
|
174
|
+
Effect.catchAllCause(reportUnhandledError),
|
|
175
|
+
Effect.provideService(Socket.WebSocket, conn as any),
|
|
176
|
+
Effect.provideService(IncomingMessage, req),
|
|
177
|
+
run
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
return yield* Effect.async<never>((_resume) => {
|
|
181
|
+
server.on("connection", onConnection)
|
|
182
|
+
return Effect.sync(() => {
|
|
183
|
+
server.off("connection", onConnection)
|
|
184
|
+
})
|
|
185
|
+
}).pipe(
|
|
186
|
+
Effect.ensuring(Scope.close(scope, Exit.void))
|
|
187
|
+
)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
const address = server.address()!
|
|
191
|
+
return SocketServer.SocketServer.of({
|
|
192
|
+
address: typeof address === "string" ?
|
|
193
|
+
{
|
|
194
|
+
_tag: "UnixAddress",
|
|
195
|
+
path: address
|
|
196
|
+
} :
|
|
197
|
+
{
|
|
198
|
+
_tag: "TcpAddress",
|
|
199
|
+
hostname: address.address,
|
|
200
|
+
port: address.port
|
|
201
|
+
},
|
|
202
|
+
run
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @since 1.0.0
|
|
208
|
+
* @category layers
|
|
209
|
+
*/
|
|
210
|
+
export const layerWebSocket = (
|
|
211
|
+
options: WS.ServerOptions
|
|
212
|
+
): Layer.Layer<SocketServer.SocketServer, SocketServer.SocketServerError> =>
|
|
213
|
+
Layer.scoped(
|
|
214
|
+
SocketServer.SocketServer,
|
|
215
|
+
makeWebSocket(options)
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
const reportUnhandledError = <E>(cause: Cause<E>) =>
|
|
219
|
+
Effect.withFiberRuntime<void>((fiber) => {
|
|
220
|
+
const unhandledLogLevel = fiber.getFiberRef(FiberRef.unhandledErrorLogLevel)
|
|
221
|
+
if (unhandledLogLevel._tag === "Some") {
|
|
222
|
+
return Effect.logWithLevel(unhandledLogLevel.value, cause, "Unhandled error in SocketServer")
|
|
223
|
+
}
|
|
224
|
+
return Effect.void
|
|
225
|
+
})
|