@web-widget/node 3.0.0-beta.0 → 3.0.0-beta.3
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/node.js +95 -49
- package/package.json +2 -2
package/dist/node.js
CHANGED
|
@@ -25,10 +25,7 @@ import {
|
|
|
25
25
|
import primitives2 from "@edge-runtime/primitives";
|
|
26
26
|
|
|
27
27
|
// src/incoming-request.ts
|
|
28
|
-
import {
|
|
29
|
-
buildToHeaders,
|
|
30
|
-
buildToReadableStream
|
|
31
|
-
} from "@edge-runtime/node-utils";
|
|
28
|
+
import { buildToHeaders } from "@edge-runtime/node-utils";
|
|
32
29
|
function isHttp2PseudoHeader(name) {
|
|
33
30
|
return name.startsWith(":");
|
|
34
31
|
}
|
|
@@ -76,6 +73,32 @@ function computeRequestOrigin(headers, defaultOrigin) {
|
|
|
76
73
|
}
|
|
77
74
|
return `${protocol}://${authority}`;
|
|
78
75
|
}
|
|
76
|
+
function buildToReadableStream(dependencies2) {
|
|
77
|
+
const { ReadableStream: ReadableStreamCtor, Uint8Array: Uint8ArrayCtor } = dependencies2;
|
|
78
|
+
return function toReadableStream(stream) {
|
|
79
|
+
return new ReadableStreamCtor({
|
|
80
|
+
start(controller) {
|
|
81
|
+
const onData = (chunk) => {
|
|
82
|
+
controller.enqueue(new Uint8ArrayCtor(chunk));
|
|
83
|
+
if (controller.desiredSize !== null && controller.desiredSize <= 0) {
|
|
84
|
+
stream.pause();
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const onEnd = () => controller.close();
|
|
88
|
+
const onError = (err) => controller.error(err);
|
|
89
|
+
stream.on("data", onData);
|
|
90
|
+
stream.on("end", onEnd);
|
|
91
|
+
stream.on("error", onError);
|
|
92
|
+
},
|
|
93
|
+
pull() {
|
|
94
|
+
stream.resume();
|
|
95
|
+
},
|
|
96
|
+
cancel() {
|
|
97
|
+
stream.destroy();
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
}
|
|
79
102
|
function buildToRequestWithHttp2Compat(dependencies2) {
|
|
80
103
|
const toHeaders = buildToHeaders(dependencies2);
|
|
81
104
|
const toReadableStream = buildToReadableStream(dependencies2);
|
|
@@ -147,8 +170,8 @@ function toMiddleware(webHandler, options) {
|
|
|
147
170
|
const toRequest = buildToRequestWithHttp2Compat(dependencies);
|
|
148
171
|
const toFetchEvent = buildToFetchEvent(dependencies);
|
|
149
172
|
return async function middleware(incomingMessage, serverResponse, next) {
|
|
173
|
+
const request = toRequest(incomingMessage, options);
|
|
150
174
|
try {
|
|
151
|
-
const request = toRequest(incomingMessage, options);
|
|
152
175
|
const env = process.env;
|
|
153
176
|
const event = toFetchEvent(request);
|
|
154
177
|
const webResponse = await webHandler(request, env, event);
|
|
@@ -157,24 +180,16 @@ function toMiddleware(webHandler, options) {
|
|
|
157
180
|
await next();
|
|
158
181
|
}
|
|
159
182
|
} catch (error) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
setHttp1StatusMessage(serverResponse, "Internal Server Error");
|
|
165
|
-
serverResponse.setHeader("content-type", "text/plain; charset=utf-8");
|
|
166
|
-
serverResponse.end(
|
|
167
|
-
error instanceof Error ? error.message : "Internal Server Error"
|
|
168
|
-
);
|
|
169
|
-
responded = true;
|
|
170
|
-
} catch {
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
if (responded) {
|
|
183
|
+
if (sendServerError(
|
|
184
|
+
serverResponse,
|
|
185
|
+
error instanceof Error ? error.message : void 0
|
|
186
|
+
)) {
|
|
174
187
|
next();
|
|
175
188
|
} else {
|
|
176
189
|
next(error);
|
|
177
190
|
}
|
|
191
|
+
} finally {
|
|
192
|
+
cancelRequestBody(request);
|
|
178
193
|
}
|
|
179
194
|
};
|
|
180
195
|
}
|
|
@@ -206,23 +221,49 @@ async function toServerResponse(webResponse, serverResponse) {
|
|
|
206
221
|
await writeReadableStreamToWritable(webResponse.body, serverResponse);
|
|
207
222
|
}
|
|
208
223
|
async function writeReadableStreamToWritable(stream, writable) {
|
|
209
|
-
|
|
210
|
-
|
|
224
|
+
if (stream.locked) {
|
|
225
|
+
throw new TypeError("ReadableStream is locked.");
|
|
226
|
+
}
|
|
227
|
+
const reader = stream.getReader();
|
|
228
|
+
const flushable = writable;
|
|
229
|
+
const onAbort = () => {
|
|
230
|
+
reader.cancel().catch(() => {
|
|
231
|
+
});
|
|
232
|
+
};
|
|
233
|
+
writable.once("close", onAbort);
|
|
234
|
+
writable.once("error", onAbort);
|
|
211
235
|
try {
|
|
212
|
-
while (
|
|
213
|
-
|
|
236
|
+
while (!writable.destroyed) {
|
|
237
|
+
const { done, value } = await reader.read();
|
|
214
238
|
if (done) {
|
|
215
|
-
writable.end();
|
|
239
|
+
if (!writable.destroyed) writable.end();
|
|
216
240
|
break;
|
|
217
241
|
}
|
|
218
|
-
writable.write(value)
|
|
242
|
+
if (writable.write(value) === false) {
|
|
243
|
+
await new Promise((resolve) => {
|
|
244
|
+
if (writable.destroyed) {
|
|
245
|
+
resolve();
|
|
246
|
+
} else {
|
|
247
|
+
writable.once("drain", resolve);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
219
251
|
if (typeof flushable.flush === "function") {
|
|
220
252
|
flushable.flush();
|
|
221
253
|
}
|
|
222
254
|
}
|
|
223
255
|
} catch (error) {
|
|
224
|
-
writable.
|
|
225
|
-
|
|
256
|
+
if (!writable.destroyed) {
|
|
257
|
+
writable.destroy(error instanceof Error ? error : void 0);
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
260
|
+
} finally {
|
|
261
|
+
writable.removeListener("close", onAbort);
|
|
262
|
+
writable.removeListener("error", onAbort);
|
|
263
|
+
try {
|
|
264
|
+
reader.releaseLock();
|
|
265
|
+
} catch {
|
|
266
|
+
}
|
|
226
267
|
}
|
|
227
268
|
}
|
|
228
269
|
function checkWritable(serverResponse) {
|
|
@@ -232,6 +273,27 @@ function checkWritable(serverResponse) {
|
|
|
232
273
|
if (!socket) return true;
|
|
233
274
|
return socket.writable;
|
|
234
275
|
}
|
|
276
|
+
function sendServerError(serverResponse, message) {
|
|
277
|
+
if (!checkWritable(serverResponse) || serverResponse.headersSent) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
serverResponse.statusCode = 500;
|
|
282
|
+
setHttp1StatusMessage(serverResponse, "Internal Server Error");
|
|
283
|
+
serverResponse.setHeader("content-type", "text/plain; charset=utf-8");
|
|
284
|
+
serverResponse.end(message || "Internal Server Error");
|
|
285
|
+
return true;
|
|
286
|
+
} catch {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function cancelRequestBody(request) {
|
|
291
|
+
const body = request.body;
|
|
292
|
+
if (body && !body.locked) {
|
|
293
|
+
body.cancel().catch(() => {
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
235
297
|
function buildToNodeHandler(dependencies2, options) {
|
|
236
298
|
const toRequest = buildToRequestWithHttp2Compat(dependencies2);
|
|
237
299
|
const toFetchEvent = buildToFetchEvent(dependencies2);
|
|
@@ -241,30 +303,14 @@ function buildToNodeHandler(dependencies2, options) {
|
|
|
241
303
|
const env = process.env;
|
|
242
304
|
const event = toFetchEvent(request);
|
|
243
305
|
const maybePromise = webHandler(request, env, event);
|
|
306
|
+
const respond = (response) => toServerResponse(response, serverResponse).finally(
|
|
307
|
+
() => cancelRequestBody(request)
|
|
308
|
+
);
|
|
309
|
+
const fail = () => sendServerError(serverResponse);
|
|
244
310
|
if (maybePromise instanceof Promise) {
|
|
245
|
-
maybePromise.then(
|
|
246
|
-
if (checkWritable(serverResponse) && !serverResponse.headersSent) {
|
|
247
|
-
serverResponse.statusCode = 500;
|
|
248
|
-
setHttp1StatusMessage(serverResponse, "Internal Server Error");
|
|
249
|
-
serverResponse.setHeader(
|
|
250
|
-
"content-type",
|
|
251
|
-
"text/plain; charset=utf-8"
|
|
252
|
-
);
|
|
253
|
-
serverResponse.end("Internal Server Error");
|
|
254
|
-
}
|
|
255
|
-
});
|
|
311
|
+
maybePromise.then(respond).catch(fail);
|
|
256
312
|
} else {
|
|
257
|
-
|
|
258
|
-
if (checkWritable(serverResponse) && !serverResponse.headersSent) {
|
|
259
|
-
serverResponse.statusCode = 500;
|
|
260
|
-
setHttp1StatusMessage(serverResponse, "Internal Server Error");
|
|
261
|
-
serverResponse.setHeader(
|
|
262
|
-
"content-type",
|
|
263
|
-
"text/plain; charset=utf-8"
|
|
264
|
-
);
|
|
265
|
-
serverResponse.end("Internal Server Error");
|
|
266
|
-
}
|
|
267
|
-
});
|
|
313
|
+
respond(maybePromise).catch(fail);
|
|
268
314
|
}
|
|
269
315
|
};
|
|
270
316
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@web-widget/node",
|
|
3
3
|
"description": "Node.js adapter",
|
|
4
|
-
"version": "3.0.0-beta.
|
|
4
|
+
"version": "3.0.0-beta.3",
|
|
5
5
|
"homepage": "https://github.com/web-widget/web-widget#readme",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@types/node": "^22.2.0",
|
|
21
21
|
"tsup": "^8.3.4",
|
|
22
|
-
"typescript": "^5.
|
|
22
|
+
"typescript": "^5.9.3"
|
|
23
23
|
},
|
|
24
24
|
"engines": {
|
|
25
25
|
"node": ">=18"
|