@whatwg-node/server
Advanced tools
Comparing version 0.9.57-alpha-20241123125835-498ddbef3a79038cbe04d8cef8c2cc1d83e7573c to 0.9.57-alpha-20241125145154-b2c748560e2a94065f9a25e55132e073f78bea40
@@ -44,6 +44,11 @@ "use strict"; | ||
}); | ||
function handleWaitUntils() { | ||
return Promise.allSettled(waitUntilPromises).then(() => { }, () => { }); | ||
} | ||
disposableStack.defer(handleWaitUntils); | ||
disposableStack.defer(() => { | ||
if (waitUntilPromises.size > 0) { | ||
return Promise.allSettled(waitUntilPromises).then(() => { | ||
waitUntilPromises.clear(); | ||
}, () => { | ||
waitUntilPromises.clear(); | ||
}); | ||
} | ||
}); | ||
function waitUntil(promiseLike) { | ||
@@ -54,3 +59,4 @@ // If it is a Node.js environment, we should register the disposable stack to handle process termination events | ||
} | ||
waitUntilPromises.add(promiseLike.then(() => { | ||
waitUntilPromises.add(promiseLike); | ||
promiseLike.then(() => { | ||
waitUntilPromises.delete(promiseLike); | ||
@@ -60,12 +66,18 @@ }, err => { | ||
waitUntilPromises.delete(promiseLike); | ||
})); | ||
}); | ||
} | ||
if (options?.plugins != null) { | ||
for (const plugin of options.plugins) { | ||
if (plugin.onRequest) { | ||
onRequestHooks.push(plugin.onRequest); | ||
if (plugin != null) { | ||
if (plugin.onRequest) { | ||
onRequestHooks.push(plugin.onRequest); | ||
} | ||
if (plugin.onResponse) { | ||
onResponseHooks.push(plugin.onResponse); | ||
} | ||
const disposeFn = plugin[disposablestack_1.DisposableSymbols.asyncDispose] || plugin[disposablestack_1.DisposableSymbols.dispose]; | ||
if (disposeFn != null) { | ||
disposableStack.defer(disposeFn); | ||
} | ||
} | ||
if (plugin.onResponse) { | ||
onResponseHooks.push(plugin.onResponse); | ||
} | ||
} | ||
@@ -80,8 +92,9 @@ } | ||
} | ||
let url = new Proxy(EMPTY_OBJECT, { | ||
get(_target, prop, _receiver) { | ||
url = new fetchAPI.URL(request.url, 'http://localhost'); | ||
return Reflect.get(url, prop, url); | ||
}, | ||
}); | ||
let url = request['parsedUrl'] || | ||
new Proxy(EMPTY_OBJECT, { | ||
get(_target, prop, _receiver) { | ||
url = new fetchAPI.URL(request.url, 'http://localhost'); | ||
return Reflect.get(url, prop, url); | ||
}, | ||
}); | ||
const onRequestHooksIteration$ = (0, utils_js_1.iterateAsyncVoid)(onRequestHooks, (onRequestHook, stopEarly) => onRequestHook({ | ||
@@ -312,4 +325,13 @@ request, | ||
[disposablestack_1.DisposableSymbols.asyncDispose]() { | ||
return disposableStack.disposeAsync(); | ||
if (!disposableStack.disposed) { | ||
return disposableStack.disposeAsync(); | ||
} | ||
return (0, uwebsockets_js_1.fakePromise)(undefined); | ||
}, | ||
dispose() { | ||
if (!disposableStack.disposed) { | ||
return disposableStack.disposeAsync(); | ||
} | ||
return (0, uwebsockets_js_1.fakePromise)(undefined); | ||
}, | ||
}; | ||
@@ -316,0 +338,0 @@ const serverAdapter = new Proxy(genericRequestHandler, { |
@@ -50,3 +50,2 @@ "use strict"; | ||
onResponse({ request, response, setResponse, fetchAPI, serverContext }) { | ||
const waitUntil = serverContext.waitUntil?.bind(serverContext) || (() => { }); | ||
// Hack for avoiding to create whatwg-node to create a readable stream until it's needed | ||
@@ -65,4 +64,6 @@ if (response['bodyInit'] || response.body) { | ||
const writer = compressionStream.writable.getWriter(); | ||
waitUntil(writer.write(bufOfRes)); | ||
waitUntil(writer.close()); | ||
const write$ = writer.write(bufOfRes); | ||
serverContext.waitUntil?.(write$); | ||
const close$ = writer.close(); | ||
serverContext.waitUntil?.(close$); | ||
const uint8Arrays$ = (0, utils_js_1.isReadable)(compressionStream.readable['readable']) | ||
@@ -85,3 +86,4 @@ ? collectReadableValues(compressionStream.readable['readable']) | ||
setResponse(compressedResponse); | ||
waitUntil(compressionStream.writable.close()); | ||
const close$ = compressionStream.writable.close(); | ||
serverContext.waitUntil?.(close$); | ||
}); | ||
@@ -88,0 +90,0 @@ } |
@@ -560,5 +560,6 @@ "use strict"; | ||
globalThis.process.once(event, function terminateHandler() { | ||
return Promise.allSettled([...disposableStacks].map(stack => stack.disposeAsync().catch(e => { | ||
console.error('Error while disposing:', e); | ||
}))); | ||
return Promise.allSettled([...disposableStacks].map(stack => !stack.disposed && | ||
stack.disposeAsync().catch(e => { | ||
console.error('Error while disposing:', e); | ||
}))); | ||
}); | ||
@@ -565,0 +566,0 @@ } |
@@ -5,3 +5,3 @@ /* eslint-disable @typescript-eslint/ban-types */ | ||
import { completeAssign, ensureDisposableStackRegisteredForTerminateEvents, handleAbortSignalAndPromiseResponse, handleErrorFromRequestHandler, isFetchEvent, isNodeRequest, isolateObject, isPromise, isRequestInit, isServerResponse, iterateAsyncVoid, nodeRequestResponseMap, normalizeNodeRequest, sendNodeResponse, ServerAdapterRequestAbortSignal, } from './utils.js'; | ||
import { getRequestFromUWSRequest, isUWSResponse, sendResponseToUwsOpts, } from './uwebsockets.js'; | ||
import { fakePromise, getRequestFromUWSRequest, isUWSResponse, sendResponseToUwsOpts, } from './uwebsockets.js'; | ||
// Required for envs like nextjs edge runtime | ||
@@ -41,6 +41,11 @@ function isRequestAccessible(serverContext) { | ||
}); | ||
function handleWaitUntils() { | ||
return Promise.allSettled(waitUntilPromises).then(() => { }, () => { }); | ||
} | ||
disposableStack.defer(handleWaitUntils); | ||
disposableStack.defer(() => { | ||
if (waitUntilPromises.size > 0) { | ||
return Promise.allSettled(waitUntilPromises).then(() => { | ||
waitUntilPromises.clear(); | ||
}, () => { | ||
waitUntilPromises.clear(); | ||
}); | ||
} | ||
}); | ||
function waitUntil(promiseLike) { | ||
@@ -51,3 +56,4 @@ // If it is a Node.js environment, we should register the disposable stack to handle process termination events | ||
} | ||
waitUntilPromises.add(promiseLike.then(() => { | ||
waitUntilPromises.add(promiseLike); | ||
promiseLike.then(() => { | ||
waitUntilPromises.delete(promiseLike); | ||
@@ -57,12 +63,18 @@ }, err => { | ||
waitUntilPromises.delete(promiseLike); | ||
})); | ||
}); | ||
} | ||
if (options?.plugins != null) { | ||
for (const plugin of options.plugins) { | ||
if (plugin.onRequest) { | ||
onRequestHooks.push(plugin.onRequest); | ||
if (plugin != null) { | ||
if (plugin.onRequest) { | ||
onRequestHooks.push(plugin.onRequest); | ||
} | ||
if (plugin.onResponse) { | ||
onResponseHooks.push(plugin.onResponse); | ||
} | ||
const disposeFn = plugin[DisposableSymbols.asyncDispose] || plugin[DisposableSymbols.dispose]; | ||
if (disposeFn != null) { | ||
disposableStack.defer(disposeFn); | ||
} | ||
} | ||
if (plugin.onResponse) { | ||
onResponseHooks.push(plugin.onResponse); | ||
} | ||
} | ||
@@ -77,8 +89,9 @@ } | ||
} | ||
let url = new Proxy(EMPTY_OBJECT, { | ||
get(_target, prop, _receiver) { | ||
url = new fetchAPI.URL(request.url, 'http://localhost'); | ||
return Reflect.get(url, prop, url); | ||
}, | ||
}); | ||
let url = request['parsedUrl'] || | ||
new Proxy(EMPTY_OBJECT, { | ||
get(_target, prop, _receiver) { | ||
url = new fetchAPI.URL(request.url, 'http://localhost'); | ||
return Reflect.get(url, prop, url); | ||
}, | ||
}); | ||
const onRequestHooksIteration$ = iterateAsyncVoid(onRequestHooks, (onRequestHook, stopEarly) => onRequestHook({ | ||
@@ -309,4 +322,13 @@ request, | ||
[DisposableSymbols.asyncDispose]() { | ||
return disposableStack.disposeAsync(); | ||
if (!disposableStack.disposed) { | ||
return disposableStack.disposeAsync(); | ||
} | ||
return fakePromise(undefined); | ||
}, | ||
dispose() { | ||
if (!disposableStack.disposed) { | ||
return disposableStack.disposeAsync(); | ||
} | ||
return fakePromise(undefined); | ||
}, | ||
}; | ||
@@ -313,0 +335,0 @@ const serverAdapter = new Proxy(genericRequestHandler, { |
@@ -47,3 +47,2 @@ import { decompressedResponseMap, getSupportedEncodings, isAsyncIterable, isReadable, } from '../utils.js'; | ||
onResponse({ request, response, setResponse, fetchAPI, serverContext }) { | ||
const waitUntil = serverContext.waitUntil?.bind(serverContext) || (() => { }); | ||
// Hack for avoiding to create whatwg-node to create a readable stream until it's needed | ||
@@ -62,4 +61,6 @@ if (response['bodyInit'] || response.body) { | ||
const writer = compressionStream.writable.getWriter(); | ||
waitUntil(writer.write(bufOfRes)); | ||
waitUntil(writer.close()); | ||
const write$ = writer.write(bufOfRes); | ||
serverContext.waitUntil?.(write$); | ||
const close$ = writer.close(); | ||
serverContext.waitUntil?.(close$); | ||
const uint8Arrays$ = isReadable(compressionStream.readable['readable']) | ||
@@ -82,3 +83,4 @@ ? collectReadableValues(compressionStream.readable['readable']) | ||
setResponse(compressedResponse); | ||
waitUntil(compressionStream.writable.close()); | ||
const close$ = compressionStream.writable.close(); | ||
serverContext.waitUntil?.(close$); | ||
}); | ||
@@ -85,0 +87,0 @@ } |
@@ -537,5 +537,6 @@ export function isAsyncIterable(body) { | ||
globalThis.process.once(event, function terminateHandler() { | ||
return Promise.allSettled([...disposableStacks].map(stack => stack.disposeAsync().catch(e => { | ||
console.error('Error while disposing:', e); | ||
}))); | ||
return Promise.allSettled([...disposableStacks].map(stack => !stack.disposed && | ||
stack.disposeAsync().catch(e => { | ||
console.error('Error while disposing:', e); | ||
}))); | ||
}); | ||
@@ -542,0 +543,0 @@ } |
{ | ||
"name": "@whatwg-node/server", | ||
"version": "0.9.57-alpha-20241123125835-498ddbef3a79038cbe04d8cef8c2cc1d83e7573c", | ||
"version": "0.9.57-alpha-20241125145154-b2c748560e2a94065f9a25e55132e073f78bea40", | ||
"description": "Fetch API compliant HTTP Server adapter", | ||
@@ -5,0 +5,0 @@ "sideEffects": false, |
import { FetchAPI, ServerAdapterRequestHandler, type ServerAdapterInitialContext } from '../types.js'; | ||
export interface ServerAdapterPlugin<TServerContext = {}> { | ||
export type ServerAdapterPlugin<TServerContext = {}> = { | ||
onRequest?: OnRequestHook<TServerContext & ServerAdapterInitialContext>; | ||
onResponse?: OnResponseHook<TServerContext & ServerAdapterInitialContext>; | ||
} | ||
[Symbol.dispose]?: () => void; | ||
[Symbol.asyncDispose]?: () => PromiseLike<void> | void; | ||
} | undefined; | ||
export type OnRequestHook<TServerContext> = (payload: OnRequestEventPayload<TServerContext>) => Promise<void> | void; | ||
@@ -7,0 +9,0 @@ export interface OnRequestEventPayload<TServerContext> { |
@@ -60,2 +60,3 @@ import type { RequestListener } from 'http'; | ||
disposableStack: AsyncDisposableStack; | ||
dispose(): Promise<void> | void; | ||
} | ||
@@ -62,0 +63,0 @@ export interface RequestLike { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
154377
3294