@whatwg-node/server 0.9.56-rc-20241119131809-2e65620848fc5eace675992259f052dfa2a4b3f4 → 0.9.57-alpha-20241123125835-498ddbef3a79038cbe04d8cef8c2cc1d83e7573c
Sign up to get free protection for your applications and to get access to all the features.
- package/cjs/createServerAdapter.js +41 -19
- package/cjs/utils.js +36 -10
- package/esm/createServerAdapter.js +42 -20
- package/esm/utils.js +35 -10
- package/package.json +2 -1
- package/typings/types.d.cts +2 -1
- package/typings/types.d.ts +2 -1
- package/typings/utils.d.cts +3 -2
- package/typings/utils.d.ts +3 -2
@@ -3,12 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createServerAdapter = createServerAdapter;
|
4
4
|
const tslib_1 = require("tslib");
|
5
5
|
/* eslint-disable @typescript-eslint/ban-types */
|
6
|
+
const disposablestack_1 = require("@whatwg-node/disposablestack");
|
6
7
|
const DefaultFetchAPI = tslib_1.__importStar(require("@whatwg-node/fetch"));
|
7
8
|
const utils_js_1 = require("./utils.js");
|
8
9
|
const uwebsockets_js_1 = require("./uwebsockets.js");
|
9
|
-
async function handleWaitUntils(waitUntilPromises) {
|
10
|
-
await Promise.allSettled(waitUntilPromises);
|
11
|
-
}
|
12
10
|
// Required for envs like nextjs edge runtime
|
13
11
|
function isRequestAccessible(serverContext) {
|
14
12
|
try {
|
@@ -29,6 +27,36 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
29
27
|
: serverAdapterBaseObject.handle;
|
30
28
|
const onRequestHooks = [];
|
31
29
|
const onResponseHooks = [];
|
30
|
+
const waitUntilPromises = new Set();
|
31
|
+
const disposableStack = new disposablestack_1.AsyncDisposableStack();
|
32
|
+
const signals = new Set();
|
33
|
+
function registerSignal(signal) {
|
34
|
+
signals.add(signal);
|
35
|
+
signal.addEventListener('abort', () => {
|
36
|
+
signals.delete(signal);
|
37
|
+
});
|
38
|
+
}
|
39
|
+
disposableStack.defer(() => {
|
40
|
+
for (const signal of signals) {
|
41
|
+
signal.sendAbort();
|
42
|
+
}
|
43
|
+
});
|
44
|
+
function handleWaitUntils() {
|
45
|
+
return Promise.allSettled(waitUntilPromises).then(() => { }, () => { });
|
46
|
+
}
|
47
|
+
disposableStack.defer(handleWaitUntils);
|
48
|
+
function waitUntil(promiseLike) {
|
49
|
+
// If it is a Node.js environment, we should register the disposable stack to handle process termination events
|
50
|
+
if (globalThis.process) {
|
51
|
+
(0, utils_js_1.ensureDisposableStackRegisteredForTerminateEvents)(disposableStack);
|
52
|
+
}
|
53
|
+
waitUntilPromises.add(promiseLike.then(() => {
|
54
|
+
waitUntilPromises.delete(promiseLike);
|
55
|
+
}, err => {
|
56
|
+
console.error(`Unexpected error while waiting: ${err.message || err}`);
|
57
|
+
waitUntilPromises.delete(promiseLike);
|
58
|
+
}));
|
59
|
+
}
|
32
60
|
if (options?.plugins != null) {
|
33
61
|
for (const plugin of options.plugins) {
|
34
62
|
if (plugin.onRequest) {
|
@@ -109,7 +137,7 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
109
137
|
// TODO: Remove this on the next major version
|
110
138
|
function handleNodeRequest(nodeRequest, ...ctx) {
|
111
139
|
const serverContext = ctx.length > 1 ? (0, utils_js_1.completeAssign)(...ctx) : ctx[0] || {};
|
112
|
-
const request = (0, utils_js_1.normalizeNodeRequest)(nodeRequest, fetchAPI);
|
140
|
+
const request = (0, utils_js_1.normalizeNodeRequest)(nodeRequest, fetchAPI, registerSignal);
|
113
141
|
return handleRequest(request, serverContext);
|
114
142
|
}
|
115
143
|
function handleNodeRequestAndResponse(nodeRequest, nodeResponseOrContainer, ...ctx) {
|
@@ -118,13 +146,10 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
118
146
|
return handleNodeRequest(nodeRequest, ...ctx);
|
119
147
|
}
|
120
148
|
function requestListener(nodeRequest, nodeResponse, ...ctx) {
|
121
|
-
const waitUntilPromises = [];
|
122
149
|
const defaultServerContext = {
|
123
150
|
req: nodeRequest,
|
124
151
|
res: nodeResponse,
|
125
|
-
waitUntil
|
126
|
-
waitUntilPromises.push(cb.catch(err => console.error(err)));
|
127
|
-
},
|
152
|
+
waitUntil,
|
128
153
|
};
|
129
154
|
let response$;
|
130
155
|
try {
|
@@ -149,19 +174,17 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
149
174
|
}
|
150
175
|
}
|
151
176
|
function handleUWS(res, req, ...ctx) {
|
152
|
-
const waitUntilPromises = [];
|
153
177
|
const defaultServerContext = {
|
154
178
|
res,
|
155
179
|
req,
|
156
|
-
waitUntil
|
157
|
-
waitUntilPromises.push(cb.catch(err => console.error(err)));
|
158
|
-
},
|
180
|
+
waitUntil,
|
159
181
|
};
|
160
182
|
const filteredCtxParts = ctx.filter(partCtx => partCtx != null);
|
161
183
|
const serverContext = filteredCtxParts.length > 0
|
162
184
|
? (0, utils_js_1.completeAssign)(defaultServerContext, ...ctx)
|
163
185
|
: defaultServerContext;
|
164
186
|
const signal = new utils_js_1.ServerAdapterRequestAbortSignal();
|
187
|
+
registerSignal(signal);
|
165
188
|
const originalResEnd = res.end.bind(res);
|
166
189
|
let resEnded = false;
|
167
190
|
res.end = function (data) {
|
@@ -222,17 +245,12 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
222
245
|
}
|
223
246
|
function handleRequestWithWaitUntil(request, ...ctx) {
|
224
247
|
const filteredCtxParts = ctx.filter(partCtx => partCtx != null);
|
225
|
-
let waitUntilPromises;
|
226
248
|
const serverContext = filteredCtxParts.length > 1
|
227
249
|
? (0, utils_js_1.completeAssign)({}, ...filteredCtxParts)
|
228
250
|
: (0, utils_js_1.isolateObject)(filteredCtxParts[0], filteredCtxParts[0] == null || filteredCtxParts[0].waitUntil == null
|
229
|
-
?
|
251
|
+
? waitUntil
|
230
252
|
: undefined);
|
231
|
-
|
232
|
-
if (waitUntilPromises?.length) {
|
233
|
-
return handleWaitUntils(waitUntilPromises).then(() => response$);
|
234
|
-
}
|
235
|
-
return response$;
|
253
|
+
return handleRequest(request, serverContext);
|
236
254
|
}
|
237
255
|
const fetchFn = (input, ...maybeCtx) => {
|
238
256
|
if (typeof input === 'string' || 'href' in input) {
|
@@ -285,6 +303,10 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
285
303
|
handleEvent,
|
286
304
|
handleUWS,
|
287
305
|
handle: genericRequestHandler,
|
306
|
+
disposableStack,
|
307
|
+
[disposablestack_1.DisposableSymbols.asyncDispose]() {
|
308
|
+
return disposableStack.disposeAsync();
|
309
|
+
},
|
288
310
|
};
|
289
311
|
const serverAdapter = new Proxy(genericRequestHandler, {
|
290
312
|
// It should have all the attributes of the handler function and the server instance
|
package/cjs/utils.js
CHANGED
@@ -19,6 +19,7 @@ exports.createDeferredPromise = createDeferredPromise;
|
|
19
19
|
exports.handleAbortSignalAndPromiseResponse = handleAbortSignalAndPromiseResponse;
|
20
20
|
exports.getSupportedEncodings = getSupportedEncodings;
|
21
21
|
exports.handleResponseDecompression = handleResponseDecompression;
|
22
|
+
exports.ensureDisposableStackRegisteredForTerminateEvents = ensureDisposableStackRegisteredForTerminateEvents;
|
22
23
|
function isAsyncIterable(body) {
|
23
24
|
return (body != null && typeof body === 'object' && typeof body[Symbol.asyncIterator] === 'function');
|
24
25
|
}
|
@@ -101,7 +102,7 @@ class ServerAdapterRequestAbortSignal extends EventTarget {
|
|
101
102
|
exports.ServerAdapterRequestAbortSignal = ServerAdapterRequestAbortSignal;
|
102
103
|
let bunNodeCompatModeWarned = false;
|
103
104
|
exports.nodeRequestResponseMap = new WeakMap();
|
104
|
-
function normalizeNodeRequest(nodeRequest, fetchAPI) {
|
105
|
+
function normalizeNodeRequest(nodeRequest, fetchAPI, registerSignal) {
|
105
106
|
const rawRequest = nodeRequest.raw || nodeRequest.req || nodeRequest;
|
106
107
|
let fullUrl = buildFullUrl(rawRequest);
|
107
108
|
if (nodeRequest.query) {
|
@@ -127,7 +128,9 @@ function normalizeNodeRequest(nodeRequest, fetchAPI) {
|
|
127
128
|
let sendAbortSignal;
|
128
129
|
// If ponyfilled
|
129
130
|
if (fetchAPI.Request !== globalThis.Request) {
|
130
|
-
|
131
|
+
const newSignal = new ServerAdapterRequestAbortSignal();
|
132
|
+
registerSignal?.(newSignal);
|
133
|
+
signal = newSignal;
|
131
134
|
sendAbortSignal = () => signal.sendAbort();
|
132
135
|
}
|
133
136
|
else {
|
@@ -440,21 +443,17 @@ function handleErrorFromRequestHandler(error, ResponseCtor) {
|
|
440
443
|
status: error.status || 500,
|
441
444
|
});
|
442
445
|
}
|
443
|
-
function isolateObject(originalCtx,
|
446
|
+
function isolateObject(originalCtx, waitUntilFn) {
|
444
447
|
if (originalCtx == null) {
|
445
|
-
if (
|
448
|
+
if (waitUntilFn == null) {
|
446
449
|
return {};
|
447
450
|
}
|
448
451
|
return {
|
449
|
-
waitUntil
|
450
|
-
waitUntilPromises.push(promise.catch(err => console.error(err)));
|
451
|
-
},
|
452
|
+
waitUntil: waitUntilFn,
|
452
453
|
};
|
453
454
|
}
|
454
455
|
return completeAssign(Object.create(originalCtx), {
|
455
|
-
waitUntil
|
456
|
-
waitUntilPromises?.push(promise.catch(err => console.error(err)));
|
457
|
-
},
|
456
|
+
waitUntil: waitUntilFn,
|
458
457
|
}, originalCtx);
|
459
458
|
}
|
460
459
|
function createDeferredPromise() {
|
@@ -548,3 +547,30 @@ function handleResponseDecompression(response, fetchAPI) {
|
|
548
547
|
}
|
549
548
|
return decompressedResponse;
|
550
549
|
}
|
550
|
+
const terminateEvents = ['SIGINT', 'SIGTERM', 'exit'];
|
551
|
+
const disposableStacks = new Set();
|
552
|
+
let eventListenerRegistered = false;
|
553
|
+
function ensureEventListenerForDisposableStacks() {
|
554
|
+
if (eventListenerRegistered) {
|
555
|
+
return;
|
556
|
+
}
|
557
|
+
eventListenerRegistered = true;
|
558
|
+
for (const event of terminateEvents) {
|
559
|
+
globalThis.process.once(event, function terminateHandler() {
|
560
|
+
return Promise.allSettled([...disposableStacks].map(stack => stack.disposeAsync().catch(e => {
|
561
|
+
console.error('Error while disposing:', e);
|
562
|
+
})));
|
563
|
+
});
|
564
|
+
}
|
565
|
+
}
|
566
|
+
function ensureDisposableStackRegisteredForTerminateEvents(disposableStack) {
|
567
|
+
if (globalThis.process) {
|
568
|
+
ensureEventListenerForDisposableStacks();
|
569
|
+
if (!disposableStacks.has(disposableStack)) {
|
570
|
+
disposableStacks.add(disposableStack);
|
571
|
+
disposableStack.defer(() => {
|
572
|
+
disposableStacks.delete(disposableStack);
|
573
|
+
});
|
574
|
+
}
|
575
|
+
}
|
576
|
+
}
|
@@ -1,10 +1,8 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/ban-types */
|
2
|
+
import { AsyncDisposableStack, DisposableSymbols } from '@whatwg-node/disposablestack';
|
2
3
|
import * as DefaultFetchAPI from '@whatwg-node/fetch';
|
3
|
-
import { completeAssign, handleAbortSignalAndPromiseResponse, handleErrorFromRequestHandler, isFetchEvent, isNodeRequest, isolateObject, isPromise, isRequestInit, isServerResponse, iterateAsyncVoid, nodeRequestResponseMap, normalizeNodeRequest, sendNodeResponse, ServerAdapterRequestAbortSignal, } from './utils.js';
|
4
|
+
import { completeAssign, ensureDisposableStackRegisteredForTerminateEvents, handleAbortSignalAndPromiseResponse, handleErrorFromRequestHandler, isFetchEvent, isNodeRequest, isolateObject, isPromise, isRequestInit, isServerResponse, iterateAsyncVoid, nodeRequestResponseMap, normalizeNodeRequest, sendNodeResponse, ServerAdapterRequestAbortSignal, } from './utils.js';
|
4
5
|
import { getRequestFromUWSRequest, isUWSResponse, sendResponseToUwsOpts, } from './uwebsockets.js';
|
5
|
-
async function handleWaitUntils(waitUntilPromises) {
|
6
|
-
await Promise.allSettled(waitUntilPromises);
|
7
|
-
}
|
8
6
|
// Required for envs like nextjs edge runtime
|
9
7
|
function isRequestAccessible(serverContext) {
|
10
8
|
try {
|
@@ -25,6 +23,36 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
25
23
|
: serverAdapterBaseObject.handle;
|
26
24
|
const onRequestHooks = [];
|
27
25
|
const onResponseHooks = [];
|
26
|
+
const waitUntilPromises = new Set();
|
27
|
+
const disposableStack = new AsyncDisposableStack();
|
28
|
+
const signals = new Set();
|
29
|
+
function registerSignal(signal) {
|
30
|
+
signals.add(signal);
|
31
|
+
signal.addEventListener('abort', () => {
|
32
|
+
signals.delete(signal);
|
33
|
+
});
|
34
|
+
}
|
35
|
+
disposableStack.defer(() => {
|
36
|
+
for (const signal of signals) {
|
37
|
+
signal.sendAbort();
|
38
|
+
}
|
39
|
+
});
|
40
|
+
function handleWaitUntils() {
|
41
|
+
return Promise.allSettled(waitUntilPromises).then(() => { }, () => { });
|
42
|
+
}
|
43
|
+
disposableStack.defer(handleWaitUntils);
|
44
|
+
function waitUntil(promiseLike) {
|
45
|
+
// If it is a Node.js environment, we should register the disposable stack to handle process termination events
|
46
|
+
if (globalThis.process) {
|
47
|
+
ensureDisposableStackRegisteredForTerminateEvents(disposableStack);
|
48
|
+
}
|
49
|
+
waitUntilPromises.add(promiseLike.then(() => {
|
50
|
+
waitUntilPromises.delete(promiseLike);
|
51
|
+
}, err => {
|
52
|
+
console.error(`Unexpected error while waiting: ${err.message || err}`);
|
53
|
+
waitUntilPromises.delete(promiseLike);
|
54
|
+
}));
|
55
|
+
}
|
28
56
|
if (options?.plugins != null) {
|
29
57
|
for (const plugin of options.plugins) {
|
30
58
|
if (plugin.onRequest) {
|
@@ -105,7 +133,7 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
105
133
|
// TODO: Remove this on the next major version
|
106
134
|
function handleNodeRequest(nodeRequest, ...ctx) {
|
107
135
|
const serverContext = ctx.length > 1 ? completeAssign(...ctx) : ctx[0] || {};
|
108
|
-
const request = normalizeNodeRequest(nodeRequest, fetchAPI);
|
136
|
+
const request = normalizeNodeRequest(nodeRequest, fetchAPI, registerSignal);
|
109
137
|
return handleRequest(request, serverContext);
|
110
138
|
}
|
111
139
|
function handleNodeRequestAndResponse(nodeRequest, nodeResponseOrContainer, ...ctx) {
|
@@ -114,13 +142,10 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
114
142
|
return handleNodeRequest(nodeRequest, ...ctx);
|
115
143
|
}
|
116
144
|
function requestListener(nodeRequest, nodeResponse, ...ctx) {
|
117
|
-
const waitUntilPromises = [];
|
118
145
|
const defaultServerContext = {
|
119
146
|
req: nodeRequest,
|
120
147
|
res: nodeResponse,
|
121
|
-
waitUntil
|
122
|
-
waitUntilPromises.push(cb.catch(err => console.error(err)));
|
123
|
-
},
|
148
|
+
waitUntil,
|
124
149
|
};
|
125
150
|
let response$;
|
126
151
|
try {
|
@@ -145,19 +170,17 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
145
170
|
}
|
146
171
|
}
|
147
172
|
function handleUWS(res, req, ...ctx) {
|
148
|
-
const waitUntilPromises = [];
|
149
173
|
const defaultServerContext = {
|
150
174
|
res,
|
151
175
|
req,
|
152
|
-
waitUntil
|
153
|
-
waitUntilPromises.push(cb.catch(err => console.error(err)));
|
154
|
-
},
|
176
|
+
waitUntil,
|
155
177
|
};
|
156
178
|
const filteredCtxParts = ctx.filter(partCtx => partCtx != null);
|
157
179
|
const serverContext = filteredCtxParts.length > 0
|
158
180
|
? completeAssign(defaultServerContext, ...ctx)
|
159
181
|
: defaultServerContext;
|
160
182
|
const signal = new ServerAdapterRequestAbortSignal();
|
183
|
+
registerSignal(signal);
|
161
184
|
const originalResEnd = res.end.bind(res);
|
162
185
|
let resEnded = false;
|
163
186
|
res.end = function (data) {
|
@@ -218,17 +241,12 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
218
241
|
}
|
219
242
|
function handleRequestWithWaitUntil(request, ...ctx) {
|
220
243
|
const filteredCtxParts = ctx.filter(partCtx => partCtx != null);
|
221
|
-
let waitUntilPromises;
|
222
244
|
const serverContext = filteredCtxParts.length > 1
|
223
245
|
? completeAssign({}, ...filteredCtxParts)
|
224
246
|
: isolateObject(filteredCtxParts[0], filteredCtxParts[0] == null || filteredCtxParts[0].waitUntil == null
|
225
|
-
?
|
247
|
+
? waitUntil
|
226
248
|
: undefined);
|
227
|
-
|
228
|
-
if (waitUntilPromises?.length) {
|
229
|
-
return handleWaitUntils(waitUntilPromises).then(() => response$);
|
230
|
-
}
|
231
|
-
return response$;
|
249
|
+
return handleRequest(request, serverContext);
|
232
250
|
}
|
233
251
|
const fetchFn = (input, ...maybeCtx) => {
|
234
252
|
if (typeof input === 'string' || 'href' in input) {
|
@@ -281,6 +299,10 @@ function createServerAdapter(serverAdapterBaseObject, options) {
|
|
281
299
|
handleEvent,
|
282
300
|
handleUWS,
|
283
301
|
handle: genericRequestHandler,
|
302
|
+
disposableStack,
|
303
|
+
[DisposableSymbols.asyncDispose]() {
|
304
|
+
return disposableStack.disposeAsync();
|
305
|
+
},
|
284
306
|
};
|
285
307
|
const serverAdapter = new Proxy(genericRequestHandler, {
|
286
308
|
// It should have all the attributes of the handler function and the server instance
|
package/esm/utils.js
CHANGED
@@ -79,7 +79,7 @@ export class ServerAdapterRequestAbortSignal extends EventTarget {
|
|
79
79
|
}
|
80
80
|
let bunNodeCompatModeWarned = false;
|
81
81
|
export const nodeRequestResponseMap = new WeakMap();
|
82
|
-
export function normalizeNodeRequest(nodeRequest, fetchAPI) {
|
82
|
+
export function normalizeNodeRequest(nodeRequest, fetchAPI, registerSignal) {
|
83
83
|
const rawRequest = nodeRequest.raw || nodeRequest.req || nodeRequest;
|
84
84
|
let fullUrl = buildFullUrl(rawRequest);
|
85
85
|
if (nodeRequest.query) {
|
@@ -105,7 +105,9 @@ export function normalizeNodeRequest(nodeRequest, fetchAPI) {
|
|
105
105
|
let sendAbortSignal;
|
106
106
|
// If ponyfilled
|
107
107
|
if (fetchAPI.Request !== globalThis.Request) {
|
108
|
-
|
108
|
+
const newSignal = new ServerAdapterRequestAbortSignal();
|
109
|
+
registerSignal?.(newSignal);
|
110
|
+
signal = newSignal;
|
109
111
|
sendAbortSignal = () => signal.sendAbort();
|
110
112
|
}
|
111
113
|
else {
|
@@ -418,21 +420,17 @@ export function handleErrorFromRequestHandler(error, ResponseCtor) {
|
|
418
420
|
status: error.status || 500,
|
419
421
|
});
|
420
422
|
}
|
421
|
-
export function isolateObject(originalCtx,
|
423
|
+
export function isolateObject(originalCtx, waitUntilFn) {
|
422
424
|
if (originalCtx == null) {
|
423
|
-
if (
|
425
|
+
if (waitUntilFn == null) {
|
424
426
|
return {};
|
425
427
|
}
|
426
428
|
return {
|
427
|
-
waitUntil
|
428
|
-
waitUntilPromises.push(promise.catch(err => console.error(err)));
|
429
|
-
},
|
429
|
+
waitUntil: waitUntilFn,
|
430
430
|
};
|
431
431
|
}
|
432
432
|
return completeAssign(Object.create(originalCtx), {
|
433
|
-
waitUntil
|
434
|
-
waitUntilPromises?.push(promise.catch(err => console.error(err)));
|
435
|
-
},
|
433
|
+
waitUntil: waitUntilFn,
|
436
434
|
}, originalCtx);
|
437
435
|
}
|
438
436
|
export function createDeferredPromise() {
|
@@ -526,3 +524,30 @@ export function handleResponseDecompression(response, fetchAPI) {
|
|
526
524
|
}
|
527
525
|
return decompressedResponse;
|
528
526
|
}
|
527
|
+
const terminateEvents = ['SIGINT', 'SIGTERM', 'exit'];
|
528
|
+
const disposableStacks = new Set();
|
529
|
+
let eventListenerRegistered = false;
|
530
|
+
function ensureEventListenerForDisposableStacks() {
|
531
|
+
if (eventListenerRegistered) {
|
532
|
+
return;
|
533
|
+
}
|
534
|
+
eventListenerRegistered = true;
|
535
|
+
for (const event of terminateEvents) {
|
536
|
+
globalThis.process.once(event, function terminateHandler() {
|
537
|
+
return Promise.allSettled([...disposableStacks].map(stack => stack.disposeAsync().catch(e => {
|
538
|
+
console.error('Error while disposing:', e);
|
539
|
+
})));
|
540
|
+
});
|
541
|
+
}
|
542
|
+
}
|
543
|
+
export function ensureDisposableStackRegisteredForTerminateEvents(disposableStack) {
|
544
|
+
if (globalThis.process) {
|
545
|
+
ensureEventListenerForDisposableStacks();
|
546
|
+
if (!disposableStacks.has(disposableStack)) {
|
547
|
+
disposableStacks.add(disposableStack);
|
548
|
+
disposableStack.defer(() => {
|
549
|
+
disposableStacks.delete(disposableStack);
|
550
|
+
});
|
551
|
+
}
|
552
|
+
}
|
553
|
+
}
|
package/package.json
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
{
|
2
2
|
"name": "@whatwg-node/server",
|
3
|
-
"version": "0.9.
|
3
|
+
"version": "0.9.57-alpha-20241123125835-498ddbef3a79038cbe04d8cef8c2cc1d83e7573c",
|
4
4
|
"description": "Fetch API compliant HTTP Server adapter",
|
5
5
|
"sideEffects": false,
|
6
6
|
"dependencies": {
|
7
|
+
"@whatwg-node/disposablestack": "^0.0.5",
|
7
8
|
"@whatwg-node/fetch": "^0.10.0",
|
8
9
|
"tslib": "^2.6.3"
|
9
10
|
},
|
package/typings/types.d.cts
CHANGED
@@ -13,7 +13,7 @@ export interface ServerAdapterBaseObject<TServerContext, THandleRequest extends
|
|
13
13
|
*/
|
14
14
|
handle: THandleRequest;
|
15
15
|
}
|
16
|
-
export interface ServerAdapterObject<TServerContext> extends EventListenerObject {
|
16
|
+
export interface ServerAdapterObject<TServerContext> extends EventListenerObject, AsyncDisposable {
|
17
17
|
/**
|
18
18
|
* A basic request listener that takes a `Request` with the server context and returns a `Response`.
|
19
19
|
*/
|
@@ -56,6 +56,7 @@ export interface ServerAdapterObject<TServerContext> extends EventListenerObject
|
|
56
56
|
handle(container: {
|
57
57
|
request: Request;
|
58
58
|
} & Partial<TServerContext & ServerAdapterInitialContext>, ...ctx: Partial<TServerContext & ServerAdapterInitialContext>[]): Promise<Response> | Response;
|
59
|
+
disposableStack: AsyncDisposableStack;
|
59
60
|
}
|
60
61
|
export interface RequestLike {
|
61
62
|
url: string;
|
package/typings/types.d.ts
CHANGED
@@ -13,7 +13,7 @@ export interface ServerAdapterBaseObject<TServerContext, THandleRequest extends
|
|
13
13
|
*/
|
14
14
|
handle: THandleRequest;
|
15
15
|
}
|
16
|
-
export interface ServerAdapterObject<TServerContext> extends EventListenerObject {
|
16
|
+
export interface ServerAdapterObject<TServerContext> extends EventListenerObject, AsyncDisposable {
|
17
17
|
/**
|
18
18
|
* A basic request listener that takes a `Request` with the server context and returns a `Response`.
|
19
19
|
*/
|
@@ -56,6 +56,7 @@ export interface ServerAdapterObject<TServerContext> extends EventListenerObject
|
|
56
56
|
handle(container: {
|
57
57
|
request: Request;
|
58
58
|
} & Partial<TServerContext & ServerAdapterInitialContext>, ...ctx: Partial<TServerContext & ServerAdapterInitialContext>[]): Promise<Response> | Response;
|
59
|
+
disposableStack: AsyncDisposableStack;
|
59
60
|
}
|
60
61
|
export interface RequestLike {
|
61
62
|
url: string;
|
package/typings/utils.d.cts
CHANGED
@@ -31,7 +31,7 @@ export declare class ServerAdapterRequestAbortSignal extends EventTarget impleme
|
|
31
31
|
any(signals: Iterable<AbortSignal>): AbortSignal;
|
32
32
|
}
|
33
33
|
export declare const nodeRequestResponseMap: WeakMap<NodeRequest, NodeResponse>;
|
34
|
-
export declare function normalizeNodeRequest(nodeRequest: NodeRequest, fetchAPI: FetchAPI): Request;
|
34
|
+
export declare function normalizeNodeRequest(nodeRequest: NodeRequest, fetchAPI: FetchAPI, registerSignal?: (signal: ServerAdapterRequestAbortSignal) => void): Request;
|
35
35
|
export declare function isReadable(stream: any): stream is Readable;
|
36
36
|
export declare function isNodeRequest(request: any): request is NodeRequest;
|
37
37
|
export declare function isServerResponse(stream: any): stream is NodeResponse;
|
@@ -43,7 +43,7 @@ export declare function completeAssign(...args: any[]): any;
|
|
43
43
|
export declare function isPromise<T>(val: T | Promise<T>): val is Promise<T>;
|
44
44
|
export declare function iterateAsyncVoid<TInput>(iterable: Iterable<TInput>, callback: (input: TInput, stopEarly: () => void) => Promise<void> | void): Promise<void> | void;
|
45
45
|
export declare function handleErrorFromRequestHandler(error: any, ResponseCtor: typeof Response): Response;
|
46
|
-
export declare function isolateObject<TIsolatedObject extends object>(originalCtx: TIsolatedObject,
|
46
|
+
export declare function isolateObject<TIsolatedObject extends object>(originalCtx: TIsolatedObject, waitUntilFn?: (promiseLike: PromiseLike<unknown>) => void): TIsolatedObject;
|
47
47
|
export interface DeferredPromise<T = void> {
|
48
48
|
promise: Promise<T>;
|
49
49
|
resolve: (value: T) => void;
|
@@ -54,3 +54,4 @@ export declare function handleAbortSignalAndPromiseResponse(response$: Promise<R
|
|
54
54
|
export declare const decompressedResponseMap: WeakMap<Response, Response>;
|
55
55
|
export declare function getSupportedEncodings(fetchAPI: FetchAPI): CompressionFormat[];
|
56
56
|
export declare function handleResponseDecompression(response: Response, fetchAPI: FetchAPI): Response;
|
57
|
+
export declare function ensureDisposableStackRegisteredForTerminateEvents(disposableStack: AsyncDisposableStack): void;
|
package/typings/utils.d.ts
CHANGED
@@ -31,7 +31,7 @@ export declare class ServerAdapterRequestAbortSignal extends EventTarget impleme
|
|
31
31
|
any(signals: Iterable<AbortSignal>): AbortSignal;
|
32
32
|
}
|
33
33
|
export declare const nodeRequestResponseMap: WeakMap<NodeRequest, NodeResponse>;
|
34
|
-
export declare function normalizeNodeRequest(nodeRequest: NodeRequest, fetchAPI: FetchAPI): Request;
|
34
|
+
export declare function normalizeNodeRequest(nodeRequest: NodeRequest, fetchAPI: FetchAPI, registerSignal?: (signal: ServerAdapterRequestAbortSignal) => void): Request;
|
35
35
|
export declare function isReadable(stream: any): stream is Readable;
|
36
36
|
export declare function isNodeRequest(request: any): request is NodeRequest;
|
37
37
|
export declare function isServerResponse(stream: any): stream is NodeResponse;
|
@@ -43,7 +43,7 @@ export declare function completeAssign(...args: any[]): any;
|
|
43
43
|
export declare function isPromise<T>(val: T | Promise<T>): val is Promise<T>;
|
44
44
|
export declare function iterateAsyncVoid<TInput>(iterable: Iterable<TInput>, callback: (input: TInput, stopEarly: () => void) => Promise<void> | void): Promise<void> | void;
|
45
45
|
export declare function handleErrorFromRequestHandler(error: any, ResponseCtor: typeof Response): Response;
|
46
|
-
export declare function isolateObject<TIsolatedObject extends object>(originalCtx: TIsolatedObject,
|
46
|
+
export declare function isolateObject<TIsolatedObject extends object>(originalCtx: TIsolatedObject, waitUntilFn?: (promiseLike: PromiseLike<unknown>) => void): TIsolatedObject;
|
47
47
|
export interface DeferredPromise<T = void> {
|
48
48
|
promise: Promise<T>;
|
49
49
|
resolve: (value: T) => void;
|
@@ -54,3 +54,4 @@ export declare function handleAbortSignalAndPromiseResponse(response$: Promise<R
|
|
54
54
|
export declare const decompressedResponseMap: WeakMap<Response, Response>;
|
55
55
|
export declare function getSupportedEncodings(fetchAPI: FetchAPI): CompressionFormat[];
|
56
56
|
export declare function handleResponseDecompression(response: Response, fetchAPI: FetchAPI): Response;
|
57
|
+
export declare function ensureDisposableStackRegisteredForTerminateEvents(disposableStack: AsyncDisposableStack): void;
|