alink-cli 0.7.2 → 0.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -6
- package/bin/agentlink-account.js +133 -0
- package/bin/agentlink.js +95 -12
- package/dist/Config-Bj2ZPCsP.mjs +1221 -0
- package/dist/Config-Bj2ZPCsP.mjs.map +1 -0
- package/dist/NodeHttpServer-BGJlR_Kf.mjs +826 -0
- package/dist/NodeHttpServer-BGJlR_Kf.mjs.map +1 -0
- package/dist/NodeServices-DDZTiw5K.mjs +1984 -0
- package/dist/NodeServices-DDZTiw5K.mjs.map +1 -0
- package/dist/NodeSocket-08w4osAf.mjs +11198 -0
- package/dist/NodeSocket-08w4osAf.mjs.map +1 -0
- package/dist/NodeSqliteClient-Byu521pt.mjs +578 -0
- package/dist/NodeSqliteClient-Byu521pt.mjs.map +1 -0
- package/dist/Schema-B3i-HrZQ.mjs +40423 -0
- package/dist/Schema-B3i-HrZQ.mjs.map +1 -0
- package/dist/SqlClient-DcM69ZvI.mjs +1554 -0
- package/dist/SqlClient-DcM69ZvI.mjs.map +1 -0
- package/dist/bin.mjs +47577 -26766
- package/dist/bin.mjs.map +1 -1
- package/package.json +4 -3
- package/dist/NodeSqliteClient-BUlNQAY0.mjs +0 -191
- package/dist/NodeSqliteClient-BUlNQAY0.mjs.map +0 -1
|
@@ -0,0 +1,826 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { $t as parseHeader, Ct as setHeader, E as toHandled, H as toPersisted, J as fromWebSocket, Mt as TypeId, N as TypeId$2, Nt as inspect, Qt as isEmpty, R as MultipartError, St as setBody, U as decodeField, V as makeConfig, W as make$5, _n as fromInput$1, a as layer$3, at as ResponseError, bt as removeHeader, c as make$6, cn as fromRecordUnsafe, ct as causeResponse, dt as HttpPlatform, fn as raw, ft as make$4, hn as uint8Array, i as RequestInit, in as layerWeak, it as RequestParseError, j as HttpServerRequest, jt as MaxBodySize, ln as merge, n as import_websocket_server, nt as ClientAbort, o as HttpServer, pn as stream$1, r as Mime_default, rn as layer$2, rt as HttpServerError, s as layerTestClient, sn as fromInput, st as ServeError, tn as toSetCookieHeaders, vt as raw$1, z as TypeId$1 } from "./NodeSocket-08w4osAf.mjs";
|
|
4
|
+
import { $c as combine, $i as makeUnsafe, Aa as cached, Cs as void_, Do as matchCauseEffect, Dr as map$1, Es as withFiber, Fr as orDie, Ga as die, Kr as runForEachArray, Qa as flatMap, Qu as add, Sa as andThen, Sc as forkUnsafe, So as map, Tc as provide$1, Xa as failCause, Xo as scope, Ya as fail, Yo as runSync, _f as pipe, aa as runIn, as as suspend, cs as tapCause, dc as provideMerge, el as die$1, fc as succeed$1, gs as try_, hd as fromNullishOr, hf as flow, hs as tryPromise, ja as callback, lc as mergeAll, lu as seconds, ms as timeoutOrElse, ni as unwrap, no as fnUntraced, ns as succeed, os as sync, po as interruptible, qo as runForkWith, rc as effect, sc as fresh, uc as provide, va as acquireRelease, vc as addFinalizer, yc as addFinalizerExit, zd as Class } from "./Schema-B3i-HrZQ.mjs";
|
|
5
|
+
import { c as layer$4, d as pipeThroughDuplex, f as toArrayBuffer, m as toUint8Array, n as layer$5, p as toString, u as fromReadable } from "./NodeServices-DDZTiw5K.mjs";
|
|
6
|
+
import { h as unwrap$1 } from "./Config-Bj2ZPCsP.mjs";
|
|
7
|
+
import { Duplex, Readable } from "node:stream";
|
|
8
|
+
import * as Fs from "node:fs";
|
|
9
|
+
import * as Http from "node:http";
|
|
10
|
+
import * as NodeStreamP from "node:stream/promises";
|
|
11
|
+
import { pipeline } from "node:stream/promises";
|
|
12
|
+
import * as Zlib from "node:zlib";
|
|
13
|
+
//#region ../../node_modules/.pnpm/@effect+platform-node@4.0.0-beta.103_bufferutil@4.1.0_effect@4.0.0-beta.103_patch_hash=_7eec308fcf6351488fccaf9a0edac255/node_modules/@effect/platform-node/dist/NodeHttpIncomingMessage.js
|
|
14
|
+
/**
|
|
15
|
+
* Adapter base for exposing Node `http.IncomingMessage` values as Effect HTTP
|
|
16
|
+
* incoming messages.
|
|
17
|
+
*
|
|
18
|
+
* Server requests and Node client responses both arrive as Node readable
|
|
19
|
+
* streams with raw header objects, socket metadata, and one-shot body
|
|
20
|
+
* consumption. This module's `NodeHttpIncomingMessage` class keeps the original
|
|
21
|
+
* Node message available while presenting Effect's `HttpIncomingMessage` shape:
|
|
22
|
+
* typed headers, remote address lookup, stream access, and text, JSON,
|
|
23
|
+
* URL-encoded, and array-buffer body readers.
|
|
24
|
+
*
|
|
25
|
+
* @since 4.0.0
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Adapts a Node `IncomingMessage` to Effect HTTP incoming messages.
|
|
29
|
+
*
|
|
30
|
+
* **When to use**
|
|
31
|
+
*
|
|
32
|
+
* Use to implement Node HTTP request or response adapters that expose the
|
|
33
|
+
* Effect HTTP incoming-message interface.
|
|
34
|
+
*
|
|
35
|
+
* **Details**
|
|
36
|
+
*
|
|
37
|
+
* The adapter exposes headers, remote address, stream access, and cached body
|
|
38
|
+
* decoders. Subclasses provide the error mapping for unknown Node errors.
|
|
39
|
+
*
|
|
40
|
+
* @category constructors
|
|
41
|
+
* @since 4.0.0
|
|
42
|
+
*/
|
|
43
|
+
var NodeHttpIncomingMessage = class extends Class {
|
|
44
|
+
/**
|
|
45
|
+
* Marks this value as an HTTP incoming message for runtime guards.
|
|
46
|
+
*
|
|
47
|
+
* @since 4.0.0
|
|
48
|
+
*/
|
|
49
|
+
[TypeId];
|
|
50
|
+
source;
|
|
51
|
+
onError;
|
|
52
|
+
remoteAddressOverride;
|
|
53
|
+
constructor(source, onError, remoteAddressOverride) {
|
|
54
|
+
super();
|
|
55
|
+
this[TypeId] = TypeId;
|
|
56
|
+
this.source = source;
|
|
57
|
+
this.onError = onError;
|
|
58
|
+
this.remoteAddressOverride = remoteAddressOverride;
|
|
59
|
+
}
|
|
60
|
+
get headers() {
|
|
61
|
+
return fromInput(this.source.headers);
|
|
62
|
+
}
|
|
63
|
+
get remoteAddress() {
|
|
64
|
+
return this.remoteAddressOverride ?? fromNullishOr(this.source.socket.remoteAddress);
|
|
65
|
+
}
|
|
66
|
+
textEffect;
|
|
67
|
+
get text() {
|
|
68
|
+
if (this.textEffect) return this.textEffect;
|
|
69
|
+
this.textEffect = runSync(cached(flatMap(MaxBodySize, (maxBodySize) => toString(() => this.source, {
|
|
70
|
+
onError: this.onError,
|
|
71
|
+
maxBytes: maxBodySize
|
|
72
|
+
}))));
|
|
73
|
+
this.arrayBufferEffect = map(this.textEffect, (_) => new TextEncoder().encode(_).buffer);
|
|
74
|
+
return this.textEffect;
|
|
75
|
+
}
|
|
76
|
+
get textUnsafe() {
|
|
77
|
+
return runSync(this.text);
|
|
78
|
+
}
|
|
79
|
+
get json() {
|
|
80
|
+
return flatMap(this.text, (text) => try_({
|
|
81
|
+
try: () => text === "" ? null : JSON.parse(text),
|
|
82
|
+
catch: this.onError
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
get jsonUnsafe() {
|
|
86
|
+
return runSync(this.json);
|
|
87
|
+
}
|
|
88
|
+
get urlParamsBody() {
|
|
89
|
+
return flatMap(this.text, (_) => try_({
|
|
90
|
+
try: () => fromInput$1(new URLSearchParams(_)),
|
|
91
|
+
catch: this.onError
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
get stream() {
|
|
95
|
+
return fromReadable({
|
|
96
|
+
evaluate: () => this.source,
|
|
97
|
+
onError: this.onError
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
arrayBufferEffect;
|
|
101
|
+
get arrayBuffer() {
|
|
102
|
+
if (this.arrayBufferEffect) return this.arrayBufferEffect;
|
|
103
|
+
this.arrayBufferEffect = withFiber((fiber) => toArrayBuffer(() => this.source, {
|
|
104
|
+
onError: this.onError,
|
|
105
|
+
maxBytes: fiber.getRef(MaxBodySize)
|
|
106
|
+
})).pipe(cached, runSync);
|
|
107
|
+
this.textEffect = map(this.arrayBufferEffect, (_) => new TextDecoder().decode(_));
|
|
108
|
+
return this.arrayBufferEffect;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region ../../node_modules/.pnpm/@effect+platform-node-shared@4.0.0-beta.103_bufferutil@4.1.0_effect@4.0.0-beta.103_patc_c414c3b6e1e822e230993f828f7aeb31/node_modules/@effect/platform-node-shared/dist/NodeHttpCompression.js
|
|
113
|
+
/**
|
|
114
|
+
* HTTP response compression backed by `node:zlib`, shared by the Node.js, Bun,
|
|
115
|
+
* and Deno platforms.
|
|
116
|
+
*
|
|
117
|
+
* Byte-array bodies are compressed in one shot with the asynchronous
|
|
118
|
+
* `node:zlib` APIs, preserving an exact `Content-Length`. Streaming bodies go
|
|
119
|
+
* through `node:zlib` transform streams that flush each input chunk.
|
|
120
|
+
*
|
|
121
|
+
* @since 4.0.0
|
|
122
|
+
*/
|
|
123
|
+
/**
|
|
124
|
+
* The compression algorithms supported by the runtime's `node:zlib`. `zstd`
|
|
125
|
+
* requires Node.js 22.15 or newer.
|
|
126
|
+
*
|
|
127
|
+
* @category constants
|
|
128
|
+
* @since 4.0.0
|
|
129
|
+
*/
|
|
130
|
+
const algorithms = /*#__PURE__*/ new Set(typeof Zlib.zstdCompress === "function" ? [
|
|
131
|
+
"gzip",
|
|
132
|
+
"deflate",
|
|
133
|
+
"br",
|
|
134
|
+
"zstd"
|
|
135
|
+
] : [
|
|
136
|
+
"gzip",
|
|
137
|
+
"deflate",
|
|
138
|
+
"br"
|
|
139
|
+
]);
|
|
140
|
+
const brotliParams = (level, sizeHint) => {
|
|
141
|
+
const params = {};
|
|
142
|
+
if (level !== void 0) params[Zlib.constants.BROTLI_PARAM_QUALITY] = level;
|
|
143
|
+
if (sizeHint !== void 0) params[Zlib.constants.BROTLI_PARAM_SIZE_HINT] = sizeHint;
|
|
144
|
+
return { params };
|
|
145
|
+
};
|
|
146
|
+
const zstdParams = (level) => level === void 0 || level === 3 ? void 0 : { params: { [Zlib.constants.ZSTD_c_compressionLevel]: level } };
|
|
147
|
+
const compress = (data, algorithm, options) => callback((resume) => {
|
|
148
|
+
const complete = (error, result) => resume(error === null ? succeed(result) : die(error));
|
|
149
|
+
switch (algorithm) {
|
|
150
|
+
case "gzip":
|
|
151
|
+
Zlib.gzip(data, { level: options?.level }, complete);
|
|
152
|
+
break;
|
|
153
|
+
case "deflate":
|
|
154
|
+
Zlib.deflate(data, { level: options?.level }, complete);
|
|
155
|
+
break;
|
|
156
|
+
case "br":
|
|
157
|
+
Zlib.brotliCompress(data, brotliParams(options?.level, data.byteLength), complete);
|
|
158
|
+
break;
|
|
159
|
+
case "zstd": {
|
|
160
|
+
const params = zstdParams(options?.level);
|
|
161
|
+
if (params === void 0) Zlib.zstdCompress(data, complete);
|
|
162
|
+
else Zlib.zstdCompress(data, params, complete);
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
/**
|
|
168
|
+
* Creates a `Compression` that compresses byte-array bodies in one shot with
|
|
169
|
+
* the asynchronous `node:zlib` APIs, setting the exact `Content-Length` of the
|
|
170
|
+
* compressed body. All other bodies are delegated to `fallback`.
|
|
171
|
+
*
|
|
172
|
+
* @category constructors
|
|
173
|
+
* @since 4.0.0
|
|
174
|
+
*/
|
|
175
|
+
const make$3 = (fallback) => ({
|
|
176
|
+
algorithms: fallback.algorithms,
|
|
177
|
+
compressResponse(response, algorithm, options) {
|
|
178
|
+
const body = response.body;
|
|
179
|
+
if (body._tag !== "Uint8Array") return fallback.compressResponse(response, algorithm, options);
|
|
180
|
+
return map(compress(body.body, algorithm, options), (result) => setHeader(setBody(response, uint8Array(result, body.contentType)), "content-length", result.byteLength.toString()));
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
/**
|
|
184
|
+
* Creates a `node:zlib` compression transform stream that flushes each input
|
|
185
|
+
* chunk, for streaming response bodies.
|
|
186
|
+
*
|
|
187
|
+
* @category constructors
|
|
188
|
+
* @since 4.0.0
|
|
189
|
+
*/
|
|
190
|
+
const compressTransform = (algorithm, options) => {
|
|
191
|
+
switch (algorithm) {
|
|
192
|
+
case "gzip": return Zlib.createGzip({
|
|
193
|
+
level: options?.level,
|
|
194
|
+
flush: Zlib.constants.Z_SYNC_FLUSH
|
|
195
|
+
});
|
|
196
|
+
case "deflate": return Zlib.createDeflate({
|
|
197
|
+
level: options?.level,
|
|
198
|
+
flush: Zlib.constants.Z_SYNC_FLUSH
|
|
199
|
+
});
|
|
200
|
+
case "br": return Zlib.createBrotliCompress({
|
|
201
|
+
...brotliParams(options?.level),
|
|
202
|
+
flush: Zlib.constants.BROTLI_OPERATION_FLUSH
|
|
203
|
+
});
|
|
204
|
+
case "zstd": return Zlib.createZstdCompress({
|
|
205
|
+
...zstdParams(options?.level),
|
|
206
|
+
flush: Zlib.constants.ZSTD_e_flush
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region ../../node_modules/.pnpm/@effect+platform-node@4.0.0-beta.103_bufferutil@4.1.0_effect@4.0.0-beta.103_patch_hash=_7eec308fcf6351488fccaf9a0edac255/node_modules/@effect/platform-node/dist/NodeHttpPlatform.js
|
|
212
|
+
/**
|
|
213
|
+
* Node.js implementation of the Effect HTTP platform service.
|
|
214
|
+
*
|
|
215
|
+
* This module connects the portable `HttpPlatform` file response helpers to
|
|
216
|
+
* Node runtime primitives. It serves local files through Node readable streams,
|
|
217
|
+
* supports byte ranges, converts Web `File` values to readable streams, and
|
|
218
|
+
* fills in content type and content length headers when needed.
|
|
219
|
+
*
|
|
220
|
+
* @since 4.0.0
|
|
221
|
+
*/
|
|
222
|
+
const compressedBody = (response, body) => removeHeader(setBody(response, body), "content-length");
|
|
223
|
+
/**
|
|
224
|
+
* Creates the Node `HttpPlatform`, serving file responses from Node readable
|
|
225
|
+
* streams and adding MIME type and content-length headers when needed.
|
|
226
|
+
*
|
|
227
|
+
* @category constructors
|
|
228
|
+
* @since 4.0.0
|
|
229
|
+
*/
|
|
230
|
+
const make$2 = /*#__PURE__*/ make$4({
|
|
231
|
+
platform: "node",
|
|
232
|
+
compression: /* @__PURE__ */ make$3({
|
|
233
|
+
algorithms,
|
|
234
|
+
compressResponse(response, algorithm, options) {
|
|
235
|
+
const body = response.body;
|
|
236
|
+
switch (body._tag) {
|
|
237
|
+
case "Stream": return succeed(compressedBody(response, stream$1(pipeThroughDuplex(body.stream, { evaluate: () => compressTransform(algorithm, options) }), body.contentType)));
|
|
238
|
+
case "Raw": {
|
|
239
|
+
const readable = body.body instanceof Readable ? body.body : Readable.fromWeb(new Response(body.body).body);
|
|
240
|
+
const transform = compressTransform(algorithm, options);
|
|
241
|
+
readable.on("error", (cause) => transform.destroy(cause));
|
|
242
|
+
transform.on("error", (cause) => readable.destroy(cause));
|
|
243
|
+
transform.on("close", () => readable.destroy());
|
|
244
|
+
return succeed(compressedBody(response, raw(readable.pipe(transform), { contentType: body.contentType })));
|
|
245
|
+
}
|
|
246
|
+
default: return succeed(response);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}),
|
|
250
|
+
fileResponse(path, status, statusText, headers, start, end, contentLength) {
|
|
251
|
+
return raw$1(contentLength === 0 ? Readable.from([]) : Fs.createReadStream(path, {
|
|
252
|
+
start,
|
|
253
|
+
end: end === void 0 ? void 0 : end - 1
|
|
254
|
+
}), {
|
|
255
|
+
headers: {
|
|
256
|
+
...headers,
|
|
257
|
+
"content-type": headers["content-type"] ?? Mime_default.getType(path) ?? "application/octet-stream",
|
|
258
|
+
"content-length": contentLength.toString()
|
|
259
|
+
},
|
|
260
|
+
status,
|
|
261
|
+
statusText
|
|
262
|
+
});
|
|
263
|
+
},
|
|
264
|
+
fileWebResponse(file, status, statusText, headers, _options) {
|
|
265
|
+
return raw$1(Readable.fromWeb(file.stream()), {
|
|
266
|
+
headers: merge(headers, fromRecordUnsafe({
|
|
267
|
+
"content-type": headers["content-type"] ?? Mime_default.getType(file.name) ?? "application/octet-stream",
|
|
268
|
+
"content-length": file.size.toString()
|
|
269
|
+
})),
|
|
270
|
+
status,
|
|
271
|
+
statusText
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
/**
|
|
276
|
+
* Provides the Node `HttpPlatform` together with the filesystem and ETag
|
|
277
|
+
* services it needs for file responses.
|
|
278
|
+
*
|
|
279
|
+
* @category layers
|
|
280
|
+
* @since 4.0.0
|
|
281
|
+
*/
|
|
282
|
+
const layer$1 = /*#__PURE__*/ pipe(/*#__PURE__*/ effect(HttpPlatform)(make$2), /*#__PURE__*/ provide(layer$4), /*#__PURE__*/ provide(layer$2));
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region ../../node_modules/.pnpm/multipasta@0.2.8/node_modules/multipasta/dist/esm/node.js
|
|
285
|
+
var MultipastaStream = class extends Duplex {
|
|
286
|
+
_parser;
|
|
287
|
+
_canWrite = true;
|
|
288
|
+
_writeCallback;
|
|
289
|
+
constructor(config) {
|
|
290
|
+
super({ readableObjectMode: true });
|
|
291
|
+
let currentError;
|
|
292
|
+
let currentFile;
|
|
293
|
+
this._parser = make$5({
|
|
294
|
+
...config,
|
|
295
|
+
onField: (info, value) => {
|
|
296
|
+
if (currentError !== void 0) return;
|
|
297
|
+
const field = {
|
|
298
|
+
_tag: "Field",
|
|
299
|
+
info,
|
|
300
|
+
value
|
|
301
|
+
};
|
|
302
|
+
this.push(field);
|
|
303
|
+
this.emit("field", field);
|
|
304
|
+
},
|
|
305
|
+
onFile: (info) => {
|
|
306
|
+
if (currentError !== void 0) return (_) => {};
|
|
307
|
+
const file = new FileStream(info, this);
|
|
308
|
+
currentFile = file;
|
|
309
|
+
this.push(file);
|
|
310
|
+
this.emit("file", file);
|
|
311
|
+
return (chunk) => {
|
|
312
|
+
this._canWrite = file.push(chunk);
|
|
313
|
+
if (chunk === null && !this._canWrite) {
|
|
314
|
+
currentFile = void 0;
|
|
315
|
+
this._resume();
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
},
|
|
319
|
+
onError: (error) => {
|
|
320
|
+
this.emit("error", error);
|
|
321
|
+
currentFile?.emit("error", error);
|
|
322
|
+
currentError = error;
|
|
323
|
+
},
|
|
324
|
+
onDone: () => {
|
|
325
|
+
this.push(null);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
_resume() {
|
|
330
|
+
this._canWrite = true;
|
|
331
|
+
if (this._writeCallback !== void 0) {
|
|
332
|
+
const callback = this._writeCallback;
|
|
333
|
+
this._writeCallback = void 0;
|
|
334
|
+
callback();
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
_read(_size) {}
|
|
338
|
+
_write(chunk, encoding, callback) {
|
|
339
|
+
this._parser.write(chunk instanceof Uint8Array ? chunk : Buffer.from(chunk, encoding));
|
|
340
|
+
if (this._canWrite) callback();
|
|
341
|
+
else this._writeCallback = callback;
|
|
342
|
+
}
|
|
343
|
+
_final(callback) {
|
|
344
|
+
this._parser.end();
|
|
345
|
+
callback();
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
const make$1 = (config) => new MultipastaStream(config);
|
|
349
|
+
var FileStream = class extends Readable {
|
|
350
|
+
info;
|
|
351
|
+
_parent;
|
|
352
|
+
_tag = "File";
|
|
353
|
+
filename;
|
|
354
|
+
constructor(info, _parent) {
|
|
355
|
+
super();
|
|
356
|
+
this.info = info;
|
|
357
|
+
this._parent = _parent;
|
|
358
|
+
this.filename = info.filename;
|
|
359
|
+
}
|
|
360
|
+
_read(_size) {
|
|
361
|
+
if (this._parent._canWrite === false) this._parent._resume();
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
//#endregion
|
|
365
|
+
//#region ../../node_modules/.pnpm/@effect+platform-node@4.0.0-beta.103_bufferutil@4.1.0_effect@4.0.0-beta.103_patch_hash=_7eec308fcf6351488fccaf9a0edac255/node_modules/@effect/platform-node/dist/NodeMultipart.js
|
|
366
|
+
/**
|
|
367
|
+
* Node.js multipart parsing for HTTP `multipart/form-data` request bodies.
|
|
368
|
+
*
|
|
369
|
+
* `NodeMultipart` adapts a Node `Readable` plus incoming HTTP headers into
|
|
370
|
+
* Effect's shared multipart model. It can expose form parts as a stream or
|
|
371
|
+
* collect a complete persisted form by writing file uploads to scoped temporary
|
|
372
|
+
* files through the current `FileSystem` and `Path` services. `fileToReadable`
|
|
373
|
+
* returns the underlying Node readable stream for file parts produced by this
|
|
374
|
+
* parser.
|
|
375
|
+
*
|
|
376
|
+
* @since 4.0.0
|
|
377
|
+
*/
|
|
378
|
+
/**
|
|
379
|
+
* Parses multipart data from a Node readable request body and headers into a
|
|
380
|
+
* stream of `Multipart.Part` values, converting parser failures to
|
|
381
|
+
* `MultipartError`.
|
|
382
|
+
*
|
|
383
|
+
* @category constructors
|
|
384
|
+
* @since 4.0.0
|
|
385
|
+
*/
|
|
386
|
+
const stream = (source, headers) => makeConfig(headers).pipe(map((config) => fromReadable({
|
|
387
|
+
evaluate() {
|
|
388
|
+
const parser = make$1(config);
|
|
389
|
+
source.pipe(parser);
|
|
390
|
+
return parser;
|
|
391
|
+
},
|
|
392
|
+
onError: (error) => convertError(error)
|
|
393
|
+
})), unwrap, map$1(convertPart));
|
|
394
|
+
/**
|
|
395
|
+
* Parses multipart data from a Node readable request body and persists file
|
|
396
|
+
* parts using the current `FileSystem`, `Path`, and `Scope` services.
|
|
397
|
+
*
|
|
398
|
+
* @category constructors
|
|
399
|
+
* @since 4.0.0
|
|
400
|
+
*/
|
|
401
|
+
const persisted = (source, headers) => toPersisted(stream(source, headers), (path, file) => tryPromise({
|
|
402
|
+
try: (signal) => NodeStreamP.pipeline(file.file, Fs.createWriteStream(path), { signal }),
|
|
403
|
+
catch: (cause) => MultipartError.fromReason("InternalError", cause)
|
|
404
|
+
}));
|
|
405
|
+
const convertPart = (part) => part._tag === "Field" ? new FieldImpl(part.info, part.value) : new FileImpl(part);
|
|
406
|
+
var PartBase = class extends Class {
|
|
407
|
+
[TypeId$1];
|
|
408
|
+
constructor() {
|
|
409
|
+
super();
|
|
410
|
+
this[TypeId$1] = TypeId$1;
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
var FieldImpl = class extends PartBase {
|
|
414
|
+
_tag = "Field";
|
|
415
|
+
key;
|
|
416
|
+
contentType;
|
|
417
|
+
value;
|
|
418
|
+
constructor(info, value) {
|
|
419
|
+
super();
|
|
420
|
+
this.key = info.name;
|
|
421
|
+
this.contentType = info.contentType;
|
|
422
|
+
this.value = decodeField(info, value);
|
|
423
|
+
}
|
|
424
|
+
toJSON() {
|
|
425
|
+
return {
|
|
426
|
+
_id: "@effect/platform/Multipart/Part",
|
|
427
|
+
_tag: "Field",
|
|
428
|
+
key: this.key,
|
|
429
|
+
value: this.value,
|
|
430
|
+
contentType: this.contentType
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
var FileImpl = class extends PartBase {
|
|
435
|
+
_tag = "File";
|
|
436
|
+
key;
|
|
437
|
+
name;
|
|
438
|
+
contentType;
|
|
439
|
+
content;
|
|
440
|
+
contentEffect;
|
|
441
|
+
file;
|
|
442
|
+
constructor(file) {
|
|
443
|
+
super();
|
|
444
|
+
this.file = file;
|
|
445
|
+
this.key = file.info.name;
|
|
446
|
+
this.name = file.filename ?? file.info.name;
|
|
447
|
+
this.contentType = file.info.contentType;
|
|
448
|
+
this.content = fromReadable({
|
|
449
|
+
evaluate: () => file,
|
|
450
|
+
onError: (cause) => MultipartError.fromReason("InternalError", cause)
|
|
451
|
+
});
|
|
452
|
+
this.contentEffect = toUint8Array(() => file, { onError: (cause) => MultipartError.fromReason("InternalError", cause) });
|
|
453
|
+
}
|
|
454
|
+
toJSON() {
|
|
455
|
+
return {
|
|
456
|
+
_id: "@effect/platform/Multipart/Part",
|
|
457
|
+
_tag: "File",
|
|
458
|
+
key: this.key,
|
|
459
|
+
name: this.name,
|
|
460
|
+
contentType: this.contentType
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
function convertError(cause) {
|
|
465
|
+
switch (cause._tag) {
|
|
466
|
+
case "ReachedLimit": switch (cause.limit) {
|
|
467
|
+
case "MaxParts": return MultipartError.fromReason("TooManyParts", cause);
|
|
468
|
+
case "MaxFieldSize": return MultipartError.fromReason("FieldTooLarge", cause);
|
|
469
|
+
case "MaxPartSize": return MultipartError.fromReason("FileTooLarge", cause);
|
|
470
|
+
case "MaxTotalSize": return MultipartError.fromReason("BodyTooLarge", cause);
|
|
471
|
+
}
|
|
472
|
+
default: return MultipartError.fromReason("Parse", cause);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
//#endregion
|
|
476
|
+
//#region ../../node_modules/.pnpm/@effect+platform-node@4.0.0-beta.103_bufferutil@4.1.0_effect@4.0.0-beta.103_patch_hash=_7eec308fcf6351488fccaf9a0edac255/node_modules/@effect/platform-node/dist/NodeHttpServer.js
|
|
477
|
+
/**
|
|
478
|
+
* Node.js implementation of the Effect `HttpServer`.
|
|
479
|
+
*
|
|
480
|
+
* This module adapts a supplied Node `http.Server` into Effect's
|
|
481
|
+
* platform-independent HTTP server service. It starts the server with Node
|
|
482
|
+
* `listen` options, converts `request` events into `HttpServerRequest` values,
|
|
483
|
+
* writes `HttpServerResponse` bodies through Node's `ServerResponse`, and
|
|
484
|
+
* handles `upgrade` events by exposing the upgraded socket through
|
|
485
|
+
* `HttpServerRequest.upgrade`. It also exports request and upgrade handler
|
|
486
|
+
* constructors plus layers for the server alone, HTTP support services, the
|
|
487
|
+
* combined server, configurable options, and tests.
|
|
488
|
+
*
|
|
489
|
+
* @since 4.0.0
|
|
490
|
+
*/
|
|
491
|
+
/**
|
|
492
|
+
* Creates a scoped `HttpServer` from a Node `http.Server`, starts listening
|
|
493
|
+
* with the supplied options, registers request and upgrade handling, and closes
|
|
494
|
+
* the server during scope finalization with optional graceful-shutdown control.
|
|
495
|
+
*
|
|
496
|
+
* @category constructors
|
|
497
|
+
* @since 4.0.0
|
|
498
|
+
*/
|
|
499
|
+
const make = /*#__PURE__*/ fnUntraced(function* (evaluate, options) {
|
|
500
|
+
const scope$2 = yield* scope;
|
|
501
|
+
const server = evaluate();
|
|
502
|
+
const shutdown = yield* callback((resume) => {
|
|
503
|
+
if (!server.listening) return resume(void_);
|
|
504
|
+
server.close((error) => {
|
|
505
|
+
if (error) resume(die(error));
|
|
506
|
+
else resume(void_);
|
|
507
|
+
});
|
|
508
|
+
}).pipe(cached);
|
|
509
|
+
const preemptiveShutdown = options.disablePreemptiveShutdown ? void_ : timeoutOrElse(shutdown, {
|
|
510
|
+
duration: options.gracefulShutdownTimeout ?? seconds(20),
|
|
511
|
+
orElse: () => void_
|
|
512
|
+
});
|
|
513
|
+
yield* addFinalizer(scope$2, shutdown);
|
|
514
|
+
yield* callback((resume) => {
|
|
515
|
+
function onError(cause) {
|
|
516
|
+
resume(fail(new ServeError({ cause })));
|
|
517
|
+
}
|
|
518
|
+
server.on("error", onError);
|
|
519
|
+
server.listen(options, () => {
|
|
520
|
+
server.off("error", onError);
|
|
521
|
+
resume(void_);
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
const address = server.address();
|
|
525
|
+
const wss = yield* acquireRelease(sync(() => new import_websocket_server.default({
|
|
526
|
+
...options.websocket,
|
|
527
|
+
noServer: true
|
|
528
|
+
})), (wss) => callback((resume) => {
|
|
529
|
+
wss.close(() => resume(void_));
|
|
530
|
+
})).pipe(provide$1(scope$2), cached);
|
|
531
|
+
return make$6({
|
|
532
|
+
address: typeof address === "string" ? {
|
|
533
|
+
_tag: "UnixAddress",
|
|
534
|
+
path: address
|
|
535
|
+
} : {
|
|
536
|
+
_tag: "TcpAddress",
|
|
537
|
+
hostname: address.address === "::" ? "0.0.0.0" : address.address,
|
|
538
|
+
port: address.port
|
|
539
|
+
},
|
|
540
|
+
serve: fnUntraced(function* (httpApp, middleware) {
|
|
541
|
+
const serveScope = yield* scope;
|
|
542
|
+
const scope$1 = forkUnsafe(serveScope, "parallel");
|
|
543
|
+
const handler = yield* makeHandler(httpApp, {
|
|
544
|
+
middleware,
|
|
545
|
+
scope: scope$1
|
|
546
|
+
});
|
|
547
|
+
const upgradeHandler = yield* makeUpgradeHandler(wss, httpApp, {
|
|
548
|
+
middleware,
|
|
549
|
+
scope: scope$1
|
|
550
|
+
});
|
|
551
|
+
yield* addFinalizerExit(serveScope, () => {
|
|
552
|
+
server.off("request", handler);
|
|
553
|
+
server.off("upgrade", upgradeHandler);
|
|
554
|
+
return preemptiveShutdown;
|
|
555
|
+
});
|
|
556
|
+
server.on("request", handler);
|
|
557
|
+
server.on("upgrade", upgradeHandler);
|
|
558
|
+
})
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
/**
|
|
562
|
+
* Creates a Node `request` event handler for an Effect HTTP application,
|
|
563
|
+
* injecting a `HttpServerRequest` and interrupting the request fiber if the
|
|
564
|
+
* client closes the response before it finishes.
|
|
565
|
+
*
|
|
566
|
+
* @category handlers
|
|
567
|
+
* @since 4.0.0
|
|
568
|
+
*/
|
|
569
|
+
const makeHandler = (httpEffect, options) => {
|
|
570
|
+
const handled = toHandled(httpEffect, handleResponse, options.middleware);
|
|
571
|
+
return withFiber((parent) => {
|
|
572
|
+
const services = parent.context;
|
|
573
|
+
return succeed(function handler(nodeRequest, nodeResponse) {
|
|
574
|
+
const fiber = runIn(runForkWith(add(services, HttpServerRequest, new ServerRequestImpl(nodeRequest, nodeResponse)))(handled), options.scope);
|
|
575
|
+
nodeResponse.on("close", () => {
|
|
576
|
+
if (!nodeResponse.writableEnded) fiber.interruptUnsafe(parent.id, ClientAbort.annotation);
|
|
577
|
+
});
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
};
|
|
581
|
+
/**
|
|
582
|
+
* Creates a Node `upgrade` event handler for an Effect HTTP application,
|
|
583
|
+
* exposing the upgraded WebSocket as the request's `upgrade` effect and
|
|
584
|
+
* interrupting the request fiber when the socket closes early.
|
|
585
|
+
*
|
|
586
|
+
* @category handlers
|
|
587
|
+
* @since 4.0.0
|
|
588
|
+
*/
|
|
589
|
+
const makeUpgradeHandler = (lazyWss, httpEffect, options) => {
|
|
590
|
+
const handledApp = toHandled(httpEffect, handleResponse, options.middleware);
|
|
591
|
+
return withFiber((parent) => {
|
|
592
|
+
const services = parent.context;
|
|
593
|
+
return succeed(function handler(nodeRequest, socket, head) {
|
|
594
|
+
let nodeResponse_ = void 0;
|
|
595
|
+
const nodeResponse = () => {
|
|
596
|
+
if (nodeResponse_ === void 0) {
|
|
597
|
+
nodeResponse_ = new Http.ServerResponse(nodeRequest);
|
|
598
|
+
nodeResponse_.assignSocket(socket);
|
|
599
|
+
nodeResponse_.on("finish", () => {
|
|
600
|
+
socket.end();
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
return nodeResponse_;
|
|
604
|
+
};
|
|
605
|
+
const upgradeEffect = fromWebSocket(flatMap(lazyWss, (wss) => acquireRelease(callback((resume) => wss.handleUpgrade(nodeRequest, socket, head, (ws) => {
|
|
606
|
+
resume(succeed(ws));
|
|
607
|
+
})), (ws) => sync(() => ws.close()))));
|
|
608
|
+
const fiber = runIn(runForkWith(add(services, HttpServerRequest, new ServerRequestImpl(nodeRequest, nodeResponse, upgradeEffect)))(handledApp), options.scope);
|
|
609
|
+
socket.on("close", () => {
|
|
610
|
+
if (!socket.writableEnded) fiber.interruptUnsafe(parent.id, ClientAbort.annotation);
|
|
611
|
+
});
|
|
612
|
+
});
|
|
613
|
+
});
|
|
614
|
+
};
|
|
615
|
+
var ServerRequestImpl = class ServerRequestImpl extends NodeHttpIncomingMessage {
|
|
616
|
+
[TypeId$2];
|
|
617
|
+
response;
|
|
618
|
+
upgradeEffect;
|
|
619
|
+
url;
|
|
620
|
+
headersOverride;
|
|
621
|
+
constructor(source, response, upgradeEffect, url = source.url, headersOverride, remoteAddressOverride) {
|
|
622
|
+
super(source, (cause) => new HttpServerError({ reason: new RequestParseError({
|
|
623
|
+
request: this,
|
|
624
|
+
cause
|
|
625
|
+
}) }), remoteAddressOverride);
|
|
626
|
+
this[TypeId$2] = TypeId$2;
|
|
627
|
+
this.response = response;
|
|
628
|
+
this.upgradeEffect = upgradeEffect;
|
|
629
|
+
this.url = url;
|
|
630
|
+
this.headersOverride = headersOverride;
|
|
631
|
+
}
|
|
632
|
+
cachedCookies;
|
|
633
|
+
get cookies() {
|
|
634
|
+
if (this.cachedCookies) return this.cachedCookies;
|
|
635
|
+
return this.cachedCookies = parseHeader(this.headers.cookie ?? "");
|
|
636
|
+
}
|
|
637
|
+
get resolvedResponse() {
|
|
638
|
+
return typeof this.response === "function" ? this.response() : this.response;
|
|
639
|
+
}
|
|
640
|
+
modify(options) {
|
|
641
|
+
return new ServerRequestImpl(this.source, this.response, this.upgradeEffect, options.url ?? this.url, options.headers ?? this.headersOverride, "remoteAddress" in options ? options.remoteAddress : this.remoteAddressOverride);
|
|
642
|
+
}
|
|
643
|
+
get originalUrl() {
|
|
644
|
+
return this.source.url;
|
|
645
|
+
}
|
|
646
|
+
cachedMethod;
|
|
647
|
+
get method() {
|
|
648
|
+
return this.cachedMethod ??= this.source.method.toUpperCase();
|
|
649
|
+
}
|
|
650
|
+
get headers() {
|
|
651
|
+
this.headersOverride ??= this.source.headers;
|
|
652
|
+
return this.headersOverride;
|
|
653
|
+
}
|
|
654
|
+
multipartEffect;
|
|
655
|
+
get multipart() {
|
|
656
|
+
if (this.multipartEffect) return this.multipartEffect;
|
|
657
|
+
this.multipartEffect = runSync(cached(persisted(this.source, this.source.headers)));
|
|
658
|
+
return this.multipartEffect;
|
|
659
|
+
}
|
|
660
|
+
get multipartStream() {
|
|
661
|
+
return stream(this.source, this.source.headers);
|
|
662
|
+
}
|
|
663
|
+
get upgrade() {
|
|
664
|
+
return this.upgradeEffect ?? fail(new HttpServerError({ reason: new RequestParseError({
|
|
665
|
+
request: this,
|
|
666
|
+
description: "not an upgradeable ServerRequest"
|
|
667
|
+
}) }));
|
|
668
|
+
}
|
|
669
|
+
toString() {
|
|
670
|
+
return `ServerRequest(${this.method} ${this.url})`;
|
|
671
|
+
}
|
|
672
|
+
toJSON() {
|
|
673
|
+
return inspect(this, {
|
|
674
|
+
_id: "HttpServerRequest",
|
|
675
|
+
method: this.method,
|
|
676
|
+
url: this.originalUrl
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
/**
|
|
681
|
+
* Provides an `HttpServer` by creating and managing a scoped Node
|
|
682
|
+
* `http.Server` with the supplied listen and shutdown options.
|
|
683
|
+
*
|
|
684
|
+
* @category layers
|
|
685
|
+
* @since 4.0.0
|
|
686
|
+
*/
|
|
687
|
+
const layerServer = /*#__PURE__*/ flow(make, /*#__PURE__*/ effect(HttpServer));
|
|
688
|
+
/**
|
|
689
|
+
* Provides the Node HTTP support services used by `NodeHttpServer`, including
|
|
690
|
+
* the HTTP platform, ETag generator, and core Node platform services.
|
|
691
|
+
*
|
|
692
|
+
* @category layers
|
|
693
|
+
* @since 4.0.0
|
|
694
|
+
*/
|
|
695
|
+
const layerHttpServices = /*#__PURE__*/ mergeAll(layer$1, layerWeak, layer$5);
|
|
696
|
+
/**
|
|
697
|
+
* Provides a Node `HttpServer` together with the Node HTTP platform, ETag, and
|
|
698
|
+
* core platform services required to serve requests.
|
|
699
|
+
*
|
|
700
|
+
* @category layers
|
|
701
|
+
* @since 4.0.0
|
|
702
|
+
*/
|
|
703
|
+
const layer = (evaluate, options) => mergeAll(layerServer(evaluate, options), layerHttpServices);
|
|
704
|
+
/**
|
|
705
|
+
* Provides a Node `HttpServer` together with the Node HTTP platform, ETag,
|
|
706
|
+
* and core Node platform services, reading the listen and shutdown options from
|
|
707
|
+
* a `Config` value.
|
|
708
|
+
*
|
|
709
|
+
* @category layers
|
|
710
|
+
* @since 4.0.0
|
|
711
|
+
*/
|
|
712
|
+
const layerConfig = (evaluate, options) => mergeAll(effect(HttpServer)(flatMap(unwrap$1(options), (options) => make(evaluate, options))), layerHttpServices);
|
|
713
|
+
/**
|
|
714
|
+
* Provides a test HTTP server listening on an ephemeral port together with a
|
|
715
|
+
* Fetch-backed `HttpClient` configured for server integration tests.
|
|
716
|
+
*
|
|
717
|
+
* @category testing
|
|
718
|
+
* @since 4.0.0
|
|
719
|
+
*/
|
|
720
|
+
const layerTest = /*#__PURE__*/ layerTestClient.pipe(/*#__PURE__*/ provide(/*#__PURE__*/ fresh(layer$3).pipe(/*#__PURE__*/ provide(/*#__PURE__*/ succeed$1(RequestInit)({ keepalive: false })))), /*#__PURE__*/ provideMerge(/*#__PURE__*/ layer(Http.createServer, { port: 0 })));
|
|
721
|
+
const handleResponse = (request, response) => {
|
|
722
|
+
const nodeResponse = request.resolvedResponse;
|
|
723
|
+
if (nodeResponse.writableEnded) return void_;
|
|
724
|
+
let headers = response.headers;
|
|
725
|
+
if (!isEmpty(response.cookies)) {
|
|
726
|
+
headers = { ...headers };
|
|
727
|
+
const toSet = toSetCookieHeaders(response.cookies);
|
|
728
|
+
if (headers["set-cookie"] !== void 0) toSet.push(headers["set-cookie"]);
|
|
729
|
+
headers["set-cookie"] = toSet;
|
|
730
|
+
}
|
|
731
|
+
if (request.method === "HEAD") {
|
|
732
|
+
nodeResponse.writeHead(response.status, headers);
|
|
733
|
+
return andThen(cancelResponseBody(response.body), callback((resume) => {
|
|
734
|
+
let completed = false;
|
|
735
|
+
const done = () => {
|
|
736
|
+
if (completed) return;
|
|
737
|
+
completed = true;
|
|
738
|
+
nodeResponse.off("close", done);
|
|
739
|
+
resume(void_);
|
|
740
|
+
};
|
|
741
|
+
nodeResponse.once("close", done);
|
|
742
|
+
nodeResponse.end(done);
|
|
743
|
+
}));
|
|
744
|
+
}
|
|
745
|
+
const body = response.body;
|
|
746
|
+
switch (body._tag) {
|
|
747
|
+
case "Empty":
|
|
748
|
+
nodeResponse.writeHead(response.status, headers);
|
|
749
|
+
nodeResponse.end();
|
|
750
|
+
return void_;
|
|
751
|
+
case "Raw":
|
|
752
|
+
nodeResponse.writeHead(response.status, headers);
|
|
753
|
+
if (typeof body.body === "object" && body.body !== null && "pipe" in body.body && typeof body.body.pipe === "function") return tryPromise({
|
|
754
|
+
try: (signal) => pipeline(body.body, nodeResponse, {
|
|
755
|
+
signal,
|
|
756
|
+
end: true
|
|
757
|
+
}),
|
|
758
|
+
catch: (cause) => new HttpServerError({ reason: new ResponseError({
|
|
759
|
+
request,
|
|
760
|
+
response,
|
|
761
|
+
description: "Error writing raw response",
|
|
762
|
+
cause
|
|
763
|
+
}) })
|
|
764
|
+
}).pipe(interruptible, tapCause(handleCause(nodeResponse, response)));
|
|
765
|
+
return callback((resume) => {
|
|
766
|
+
nodeResponse.end(body.body, () => resume(void_));
|
|
767
|
+
});
|
|
768
|
+
case "Uint8Array":
|
|
769
|
+
nodeResponse.writeHead(response.status, headers);
|
|
770
|
+
if (body.body.length < 1024 * 1024) {
|
|
771
|
+
nodeResponse.end(body.body);
|
|
772
|
+
return void_;
|
|
773
|
+
}
|
|
774
|
+
return callback((resume) => {
|
|
775
|
+
nodeResponse.end(body.body, () => resume(void_));
|
|
776
|
+
});
|
|
777
|
+
case "FormData": return suspend(() => {
|
|
778
|
+
const r = new globalThis.Response(body.formData);
|
|
779
|
+
nodeResponse.writeHead(response.status, {
|
|
780
|
+
...headers,
|
|
781
|
+
...Object.fromEntries(r.headers)
|
|
782
|
+
});
|
|
783
|
+
return callback((resume, signal) => {
|
|
784
|
+
Readable.fromWeb(r.body, { signal }).pipe(nodeResponse).on("error", (cause) => {
|
|
785
|
+
resume(fail(new HttpServerError({ reason: new ResponseError({
|
|
786
|
+
request,
|
|
787
|
+
response,
|
|
788
|
+
description: "Error writing FormData response",
|
|
789
|
+
cause
|
|
790
|
+
}) })));
|
|
791
|
+
}).once("finish", () => {
|
|
792
|
+
resume(void_);
|
|
793
|
+
});
|
|
794
|
+
}).pipe(interruptible, tapCause(handleCause(nodeResponse, response)));
|
|
795
|
+
});
|
|
796
|
+
case "Stream": {
|
|
797
|
+
nodeResponse.writeHead(response.status, headers);
|
|
798
|
+
const drainLatch = makeUnsafe();
|
|
799
|
+
nodeResponse.on("drain", () => drainLatch.openUnsafe());
|
|
800
|
+
return body.stream.pipe(orDie, runForEachArray((array) => {
|
|
801
|
+
const chunk = array.length > 1 ? Buffer.concat(array) : array[0];
|
|
802
|
+
if (nodeResponse.write(chunk)) return void_;
|
|
803
|
+
drainLatch.closeUnsafe();
|
|
804
|
+
return drainLatch.await;
|
|
805
|
+
}), interruptible, matchCauseEffect({
|
|
806
|
+
onSuccess: () => sync(() => nodeResponse.end()),
|
|
807
|
+
onFailure: handleCause(nodeResponse, response)
|
|
808
|
+
}));
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
const cancelResponseBody = (body) => {
|
|
813
|
+
const stream = body._tag === "Raw" ? body.body : void 0;
|
|
814
|
+
if (stream instanceof Readable) return sync(() => stream.destroy());
|
|
815
|
+
return void_;
|
|
816
|
+
};
|
|
817
|
+
const handleCause = (nodeResponse, originalResponse) => (originalCause) => flatMap(causeResponse(originalCause), ([response, cause]) => {
|
|
818
|
+
const headersSent = nodeResponse.headersSent;
|
|
819
|
+
if (!headersSent) nodeResponse.writeHead(response.status);
|
|
820
|
+
if (!nodeResponse.writableEnded) nodeResponse.end();
|
|
821
|
+
return failCause(headersSent ? combine(originalCause, die$1(originalResponse)) : cause);
|
|
822
|
+
});
|
|
823
|
+
//#endregion
|
|
824
|
+
export { layer, layerConfig, layerHttpServices, layerServer, layerTest, make, makeHandler, makeUpgradeHandler };
|
|
825
|
+
|
|
826
|
+
//# sourceMappingURL=NodeHttpServer-BGJlR_Kf.mjs.map
|