🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@fluojs/http

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fluojs/http - npm Package Compare versions

Comparing version
1.0.0-beta.10
to
1.0.0-beta.11
+25
dist/context/request-context-node-store.d.ts
import type { RequestContextStore } from './request-context-store.js';
type AsyncLocalStorageConstructor = new () => RequestContextStore;
type NodeAsyncHooksModule = {
AsyncLocalStorage?: AsyncLocalStorageConstructor;
};
type AsyncLocalStorageResolutionHost = {
AsyncLocalStorage?: AsyncLocalStorageConstructor;
process?: {
getBuiltinModule?(id: 'node:async_hooks'): NodeAsyncHooksModule;
versions?: {
node?: string;
};
};
};
type NodeAsyncHooksLoader = () => Promise<NodeAsyncHooksModule>;
/**
* Resolves the host `AsyncLocalStorage` constructor without eagerly importing Node built-ins.
*
* @param host Host global-like object to inspect for async-context support.
* @param loadNodeAsyncHooks Lazy loader for Node's `node:async_hooks` module.
* @returns The resolved `AsyncLocalStorage` constructor, or `undefined` when unavailable.
*/
export declare function resolveAsyncLocalStorageConstructor(host?: AsyncLocalStorageResolutionHost, loadNodeAsyncHooks?: NodeAsyncHooksLoader): Promise<AsyncLocalStorageConstructor | undefined>;
export {};
//# sourceMappingURL=request-context-node-store.d.ts.map
{"version":3,"file":"request-context-node-store.d.ts","sourceRoot":"","sources":["../../src/context/request-context-node-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,KAAK,4BAA4B,GAAG,UAAU,mBAAmB,CAAC;AAElE,KAAK,oBAAoB,GAAG;IAC1B,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;CAClD,CAAC;AAEF,KAAK,+BAA+B,GAAG;IACrC,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;IACjD,OAAO,CAAC,EAAE;QACR,gBAAgB,CAAC,CAAC,EAAE,EAAE,kBAAkB,GAAG,oBAAoB,CAAC;QAChE,QAAQ,CAAC,EAAE;YACT,IAAI,CAAC,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAC;CACH,CAAC;AAEF,KAAK,oBAAoB,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAEhE;;;;;;GAMG;AACH,wBAAsB,mCAAmC,CACvD,IAAI,GAAE,+BAA4C,EAClD,kBAAkB,GAAE,oBAA2C,GAC9D,OAAO,CAAC,4BAA4B,GAAG,SAAS,CAAC,CAsBnD"}
/**
* Resolves the host `AsyncLocalStorage` constructor without eagerly importing Node built-ins.
*
* @param host Host global-like object to inspect for async-context support.
* @param loadNodeAsyncHooks Lazy loader for Node's `node:async_hooks` module.
* @returns The resolved `AsyncLocalStorage` constructor, or `undefined` when unavailable.
*/
export async function resolveAsyncLocalStorageConstructor(host = globalThis, loadNodeAsyncHooks = importNodeAsyncHooks) {
if (typeof host.AsyncLocalStorage === 'function') {
return host.AsyncLocalStorage;
}
const builtinAsyncLocalStorage = host.process?.getBuiltinModule?.('node:async_hooks').AsyncLocalStorage;
if (typeof builtinAsyncLocalStorage === 'function') {
return builtinAsyncLocalStorage;
}
if (!isNodeHost(host)) {
return undefined;
}
try {
const nodeAsyncHooks = await loadNodeAsyncHooks();
return nodeAsyncHooks.AsyncLocalStorage;
} catch {
return undefined;
}
}
function isNodeHost(host) {
return typeof host.process?.versions?.node === 'string';
}
function importNodeAsyncHooks() {
const nodeAsyncHooksSpecifier = `node:${'async_hooks'}`;
return import(nodeAsyncHooksSpecifier);
}
import type { RequestContextStore } from './request-context-store.js';
/**
* Creates the synchronous fallback request-context store used when no async-context primitive exists.
*
* @returns A stack-backed request-context store scoped to synchronous callback frames.
*/
export declare function createStackRequestContextStore(): RequestContextStore;
//# sourceMappingURL=request-context-stack-store.d.ts.map
{"version":3,"file":"request-context-stack-store.d.ts","sourceRoot":"","sources":["../../src/context/request-context-stack-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,8BAA8B,IAAI,mBAAmB,CAmBpE"}
/**
* Creates the synchronous fallback request-context store used when no async-context primitive exists.
*
* @returns A stack-backed request-context store scoped to synchronous callback frames.
*/
export function createStackRequestContextStore() {
const stack = [];
return {
getStore() {
return stack.at(-1);
},
run(context, callback) {
stack.push(context);
try {
return callback();
} catch (error) {
throw error;
} finally {
removeStackContext(stack, context);
}
}
};
}
function removeStackContext(stack, context) {
const index = stack.lastIndexOf(context);
if (index >= 0) {
stack.splice(index, 1);
}
}
import type { RequestContext } from '../types.js';
/** Store abstraction shared by host async-context implementations and the synchronous fallback. */
export type RequestContextStore = {
getStore(): RequestContext | undefined;
run<T>(context: RequestContext, callback: () => T): T;
};
//# sourceMappingURL=request-context-store.d.ts.map
{"version":3,"file":"request-context-store.d.ts","sourceRoot":"","sources":["../../src/context/request-context-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,mGAAmG;AACnG,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,IAAI,cAAc,GAAG,SAAS,CAAC;IACvC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;CACvD,CAAC"}
+7
-3
import type { ContextKey, RequestContext } from '../types.js';
/**
* Runs a callback inside the request-scoped AsyncLocalStorage context.
* Runs a callback inside the request-scoped async context.
*
* Hosts with `AsyncLocalStorage` preserve the context across awaited work. Hosts without an async
* context primitive use a stack fallback that keeps the context only for the synchronous callback
* frame and clears it before awaited continuations resume.
*
* @param context Request context snapshot to bind to the current async execution chain.

@@ -24,5 +28,5 @@ * @param callback Callback executed with `context` available through request-context helpers.

/**
* Creates a defensive clone of a request context for AsyncLocalStorage storage.
* Creates a defensive clone of a request context for async-context storage.
*
* @param context Request context to clone before storing in AsyncLocalStorage.
* @param context Request context to clone before storing in the active async-context store.
* @returns A shallow clone with copied metadata map to avoid cross-request mutation.

@@ -29,0 +33,0 @@ */

@@ -1,1 +0,1 @@

{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/context/request-context.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAI9D;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAEtF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,cAAc,GAAG,SAAS,CAErE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAUrD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAK5E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAKtE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAE7F;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAE9F"}
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/context/request-context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAO9D;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAEtF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,cAAc,GAAG,SAAS,CAErE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAUrD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAK5E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAKtE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAE7F;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAE9F"}

@@ -1,8 +0,13 @@

import { AsyncLocalStorage } from 'node:async_hooks';
import { FluoError } from '@fluojs/core';
const requestContextStore = new AsyncLocalStorage();
import { resolveAsyncLocalStorageConstructor } from './request-context-node-store.js';
import { createStackRequestContextStore } from './request-context-stack-store.js';
const requestContextStore = await createRequestContextStore();
/**
* Runs a callback inside the request-scoped AsyncLocalStorage context.
* Runs a callback inside the request-scoped async context.
*
* Hosts with `AsyncLocalStorage` preserve the context across awaited work. Hosts without an async
* context primitive use a stack fallback that keeps the context only for the synchronous callback
* frame and clears it before awaited continuations resume.
*
* @param context Request context snapshot to bind to the current async execution chain.

@@ -42,5 +47,5 @@ * @param callback Callback executed with `context` available through request-context helpers.

/**
* Creates a defensive clone of a request context for AsyncLocalStorage storage.
* Creates a defensive clone of a request context for async-context storage.
*
* @param context Request context to clone before storing in AsyncLocalStorage.
* @param context Request context to clone before storing in the active async-context store.
* @returns A shallow clone with copied metadata map to avoid cross-request mutation.

@@ -90,2 +95,9 @@ */

context.metadata[key.id] = value;
}
async function createRequestContextStore() {
const AsyncLocalStorage = await resolveAsyncLocalStorageConstructor();
if (typeof AsyncLocalStorage === 'function') {
return new AsyncLocalStorage();
}
return createStackRequestContextStore();
}

@@ -1,1 +0,1 @@

{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/dispatch/dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,YAAY,CAAC;AAQnE,OAAO,KAAK,EACV,MAAM,EACN,yBAAyB,EACzB,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EAIjB,cAAc,EAEd,eAAe,EAEf,cAAc,EAId,mBAAmB,EACpB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAKL,KAAK,aAAa,EAOnB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE5F,gEAAgE;AAChE,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;AAEpK,uDAAuD;AACvD,MAAM,WAAW,uBAAuB;IACtC,iDAAiD;IACjD,aAAa,CAAC,EAAE,cAAc,EAAE,CAAC;IACjC,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,kBAAkB,CAAC,EAAE,yBAAyB,CAAC;IAC/C,sDAAsD;IACtD,cAAc,EAAE,cAAc,CAAC;IAC/B,2DAA2D;IAC3D,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;IACjC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAClC,+DAA+D;IAC/D,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qCAAqC;IACrC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,sEAAsE;IACtE,YAAY,CAAC,EAAE;QACb,wDAAwD;QACxD,oBAAoB,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;KACjD,CAAC;IACF,qDAAqD;IACrD,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,qDAAqD;IACrD,aAAa,EAAE,SAAS,CAAC;IACzB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAoyBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,UAAU,CAuF7E;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,GAAG,SAAS,CAE5F;AAED,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC"}
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/dispatch/dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,YAAY,CAAC;AAQnE,OAAO,KAAK,EACV,MAAM,EACN,yBAAyB,EACzB,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EAIjB,cAAc,EAEd,eAAe,EAEf,cAAc,EAId,mBAAmB,EACpB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAKL,KAAK,aAAa,EAOnB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE5F,gEAAgE;AAChE,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;AAEpK,uDAAuD;AACvD,MAAM,WAAW,uBAAuB;IACtC,iDAAiD;IACjD,aAAa,CAAC,EAAE,cAAc,EAAE,CAAC;IACjC,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,kBAAkB,CAAC,EAAE,yBAAyB,CAAC;IAC/C,sDAAsD;IACtD,cAAc,EAAE,cAAc,CAAC;IAC/B,2DAA2D;IAC3D,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;IACjC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAClC,+DAA+D;IAC/D,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qCAAqC;IACrC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,sEAAsE;IACtE,YAAY,CAAC,EAAE;QACb,wDAAwD;QACxD,oBAAoB,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;KACjD,CAAC;IACF,qDAAqD;IACrD,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,qDAAqD;IACrD,aAAa,EAAE,SAAS,CAAC;IACzB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAyyBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,UAAU,CAuF7E;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,GAAG,SAAS,CAE5F;AAED,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC"}

@@ -359,2 +359,6 @@ import { getCompiledDtoBindingPlan } from '../adapters/dto-binding-plan.js';

}
if (options.fastPathDebugHeaders === true && eligibility && !response.committed) {
const debugInfo = createPathDebugInfo(eligibility);
addPathDebugHeader(response.setHeader.bind(response), debugInfo);
}
const dispatchRequest = request;

@@ -361,0 +365,0 @@ const dispatchScope = createRootDispatchScope(options.rootContainer);

@@ -0,4 +1,6 @@

export { createFetchStyleHttpAdapterRealtimeCapability, type HttpApplicationAdapter, } from './adapter.js';
export { DefaultBinder } from './adapters/binding.js';
export { resolveClientIdentity } from './client-identity.js';
export type { Dispatcher } from './types.js';
export { attachFrameworkRequestNativeRouteHandoff, bindRawRequestNativeRouteHandoff, consumeRawRequestNativeRouteHandoff, isRoutePathNormalizationSensitive, readFrameworkRequestNativeRouteHandoff, type NativeRouteHandoff, } from './dispatch/native-route-handoff.js';
//# sourceMappingURL=internal.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EACL,wCAAwC,EACxC,gCAAgC,EAChC,mCAAmC,EACnC,iCAAiC,EACjC,sCAAsC,EACtC,KAAK,kBAAkB,GACxB,MAAM,oCAAoC,CAAC"}
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6CAA6C,EAC7C,KAAK,sBAAsB,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EACL,wCAAwC,EACxC,gCAAgC,EAChC,mCAAmC,EACnC,iCAAiC,EACjC,sCAAsC,EACtC,KAAK,kBAAkB,GACxB,MAAM,oCAAoC,CAAC"}

@@ -0,3 +1,4 @@

export { createFetchStyleHttpAdapterRealtimeCapability } from './adapter.js';
export { DefaultBinder } from './adapters/binding.js';
export { resolveClientIdentity } from './client-identity.js';
export { attachFrameworkRequestNativeRouteHandoff, bindRawRequestNativeRouteHandoff, consumeRawRequestNativeRouteHandoff, isRoutePathNormalizationSensitive, readFrameworkRequestNativeRouteHandoff } from './dispatch/native-route-handoff.js';

@@ -1,1 +0,1 @@

{"version":3,"file":"correlation.d.ts","sourceRoot":"","sources":["../../src/middleware/correlation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAY9C;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,UAAU,CAYxD"}
{"version":3,"file":"correlation.d.ts","sourceRoot":"","sources":["../../src/middleware/correlation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAsB9C;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,UAAU,CAYxD"}

@@ -1,2 +0,1 @@

import { randomUUID } from 'node:crypto';
const REQUEST_ID_HEADER = 'x-request-id';

@@ -7,4 +6,11 @@ const CORRELATION_ID_HEADER = 'x-correlation-id';

const value = Array.isArray(requestId) ? requestId[0] : requestId;
return value ?? randomUUID();
return value ?? createRequestId();
}
function createRequestId() {
const randomUUID = globalThis.crypto?.randomUUID;
if (randomUUID) {
return randomUUID.call(globalThis.crypto);
}
return `req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`;
}

@@ -11,0 +17,0 @@ /**

@@ -13,3 +13,3 @@ {

],
"version": "1.0.0-beta.10",
"version": "1.0.0-beta.11",
"private": false,

@@ -45,5 +45,5 @@ "license": "MIT",

"dependencies": {
"@fluojs/core": "^1.0.0-beta.4",
"@fluojs/validation": "^1.0.0-beta.3",
"@fluojs/di": "^1.0.0-beta.6"
"@fluojs/core": "^1.0.0-beta.6",
"@fluojs/validation": "^1.0.0-beta.4",
"@fluojs/di": "^1.0.0-beta.8"
},

@@ -50,0 +50,0 @@ "devDependencies": {

@@ -99,2 +99,4 @@ # @fluojs/http

`runWithRequestContext(...)`는 호스트가 `globalThis.AsyncLocalStorage` 또는 Node 내장 `node:async_hooks` 모듈로 `AsyncLocalStorage`를 제공할 때 활성 컨텍스트를 `await` 이후까지 보존합니다. 선언된 `>=20.0.0` 지원 범위의 Node 런타임은 `process.getBuiltinModule(...)`이 없어도 `node:async_hooks`를 동적으로 해석해 ALS 의미론을 유지합니다. 비동기 컨텍스트 primitive가 없는 비 Node 호스트에서는 동기 stack fallback을 사용하며, 겹치는 비동기 요청이 서로의 컨텍스트를 관찰하지 않도록 awaited continuation이 재개되기 전에 컨텍스트를 비웁니다.
### 프록시 뒤의 속도 제한

@@ -137,3 +139,3 @@

디스패처는 활성 dispatch 동안에만 `AsyncLocalStorage`로 `RequestContext`를 바인딩합니다. 요청이 controller graph, middleware, guard, interceptor, observer, DTO converter, custom binder 또는 수동 `getCurrentRequestContext()` / `assertRequestContext()` container 접근을 통해 request-scoped DI를 사용할 수 있으면, 디스패처는 요청 observer가 끝난 뒤 `finally` 경로에서 isolated request-scoped DI 컨테이너를 생성하고 dispose합니다. Singleton-only route는 `RequestContext.container`가 접근되기 전까지 이 컨테이너 lifecycle을 건너뛰어 baseline 경로의 불필요한 per-request allocation을 피하면서도, graph가 모호하거나 request-scoped이면 request-scoped provider isolation을 유지합니다. 따라서 공개 `RequestContext.container` 읽기는 request-scoped provider resolve에 항상 안전합니다. singleton-only fast path는 내부 dispatcher 최적화일 뿐, 공개 context가 root container를 노출한다는 약속이 아닙니다.
디스패처는 활성 dispatch 동안에만 호스트 비동기 컨텍스트 저장소로 `RequestContext`를 바인딩합니다. 지원되는 Node 20+ 런타임을 포함해 `AsyncLocalStorage`가 있는 호스트에서는 컨텍스트가 awaited work 이후까지 유지됩니다. 비동기 컨텍스트 primitive가 없는 비 Node 호스트에서는 fallback 컨텍스트가 동기 프레임에만 유효하고, 겹치는 요청이 서로의 컨텍스트를 관찰하지 않도록 `await` 이후에는 의도적으로 사용할 수 없습니다. 요청이 controller graph, middleware, guard, interceptor, observer, DTO converter, custom binder 또는 수동 `getCurrentRequestContext()` / `assertRequestContext()` container 접근을 통해 request-scoped DI를 사용할 수 있으면, 디스패처는 요청 observer가 끝난 뒤 `finally` 경로에서 isolated request-scoped DI 컨테이너를 생성하고 dispose합니다. Singleton-only route는 `RequestContext.container`가 접근되기 전까지 이 컨테이너 lifecycle을 건너뛰어 baseline 경로의 불필요한 per-request allocation을 피하면서도, graph가 모호하거나 request-scoped이면 request-scoped provider isolation을 유지합니다. 따라서 공개 `RequestContext.container` 읽기는 request-scoped provider resolve에 항상 안전합니다. singleton-only fast path는 내부 dispatcher 최적화일 뿐, 공개 context가 root container를 노출한다는 약속이 아닙니다.

@@ -163,2 +165,3 @@ 어댑터는 플랫폼이 제공한다면 `FrameworkRequest.signal`에 `AbortSignal`을 전달해야 합니다. SSE에서는 가능하면 `FrameworkResponse.stream.onClose(...)`도 노출해야 합니다. `SseResponse`는 request abort와 raw stream close를 모두 구독하고, 멱등하게 닫히며, 어느 쪽이 먼저 종료되더라도 등록한 listener를 제거합니다.

- `resolveClientIdentity(request)`: 속도 제한과 런타임 통합에서 사용하는 보수적 클라이언트 식별 해석기.
- `createFetchStyleHttpAdapterRealtimeCapability(...)`, `Dispatcher`, `HttpApplicationAdapter`: 전체 HTTP root barrel을 instantiate하면 안 되는 edge/fetch-style platform package를 위한 내부 adapter seam.

@@ -165,0 +168,0 @@ ## 관련 패키지

@@ -101,2 +101,4 @@ # @fluojs/http

`runWithRequestContext(...)` preserves the active context across awaited work when the host provides `AsyncLocalStorage` through `globalThis.AsyncLocalStorage` or Node's built-in `node:async_hooks` module. Node runtimes in the declared `>=20.0.0` support range keep ALS semantics even when `process.getBuiltinModule(...)` is unavailable by resolving `node:async_hooks` dynamically. Non-Node hosts without an async-context primitive use a synchronous stack fallback that clears the context before awaited continuations resume, avoiding cross-request leaks instead of pretending to isolate overlapping async work.
### Rate limiting behind proxies

@@ -139,3 +141,3 @@

The dispatcher binds `RequestContext` with `AsyncLocalStorage` for the active dispatch only. When a request may use request-scoped DI through its controller graph, middleware, guards, interceptors, observers, DTO converters, a custom binder, or manual `getCurrentRequestContext()` / `assertRequestContext()` container access, the dispatcher creates and disposes an isolated request-scoped DI container from its `finally` path after request observers finish. Singleton-only routes skip that container lifecycle until `RequestContext.container` is accessed, so the baseline path avoids unnecessary per-request allocation while preserving request-scoped provider isolation whenever the graph is ambiguous or request-scoped. Public `RequestContext.container` reads are therefore always safe for resolving request-scoped providers; the singleton-only fast path is an internal dispatcher optimization, not a promise that the public context exposes the root container.
The dispatcher binds `RequestContext` with host async-context storage for the active dispatch only. On hosts with `AsyncLocalStorage`, including supported Node 20+ runtimes, the context remains available across awaited work. On non-Node hosts without an async-context primitive, the fallback context is synchronous-only and intentionally unavailable after `await` so overlapping requests cannot observe one another's context. When a request may use request-scoped DI through its controller graph, middleware, guards, interceptors, observers, DTO converters, a custom binder, or manual `getCurrentRequestContext()` / `assertRequestContext()` container access, the dispatcher creates and disposes an isolated request-scoped DI container from its `finally` path after request observers finish. Singleton-only routes skip that container lifecycle until `RequestContext.container` is accessed, so the baseline path avoids unnecessary per-request allocation while preserving request-scoped provider isolation whenever the graph is ambiguous or request-scoped. Public `RequestContext.container` reads are therefore always safe for resolving request-scoped providers; the singleton-only fast path is an internal dispatcher optimization, not a promise that the public context exposes the root container.

@@ -165,2 +167,3 @@ Adapters should pass an `AbortSignal` on `FrameworkRequest.signal` when the platform exposes one. For SSE, adapters should also expose `FrameworkResponse.stream.onClose(...)` when possible; `SseResponse` listens to both request abort and raw stream close, closes idempotently, and removes registered listeners when either side terminates first.

- `resolveClientIdentity(request)`: Conservative client identity resolver used by rate limiting and other runtime integrations.
- `createFetchStyleHttpAdapterRealtimeCapability(...)`, `Dispatcher`, and `HttpApplicationAdapter`: internal adapter seams for edge/fetch-style platform packages that must avoid instantiating the full HTTP root barrel.

@@ -167,0 +170,0 @@ ## Related Packages